From 53d360a5e91b30b7ee7585934f61be7eb9d20da1 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Mon, 3 Jul 2017 20:57:08 -0700 Subject: [PATCH] implemented spirv::Literal_string --- CMakeLists.txt | 5 +- src/generate_spirv_parser/generate.cpp | 14 +- src/spirv/CMakeLists.txt | 2 +- src/spirv/literal_string.cpp | 31 ++ src/spirv/literal_string.h | 431 +++++++++++++++++++++++++ src/spirv/word.h | 36 +++ src/util/CMakeLists.txt | 10 + src/util/endian.h | 43 +++ src/util/endian_config.h.in | 29 ++ 9 files changed, 591 insertions(+), 10 deletions(-) create mode 100644 src/spirv/literal_string.cpp create mode 100644 src/spirv/literal_string.h create mode 100644 src/spirv/word.h create mode 100644 src/util/endian.h create mode 100644 src/util/endian_config.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 6890d6b..69c39ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,9 +23,12 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) -project(vulkan-cpu CXX) +project(vulkan-cpu CXX C) if(NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") message(FATAL_ERROR "compiler is not clang") endif() +if(NOT ${CMAKE_C_COMPILER_ID} MATCHES "Clang") + message(FATAL_ERROR "compiler is not clang") +endif() add_compile_options(-Wall -ftemplate-depth=1024) add_subdirectory(src) diff --git a/src/generate_spirv_parser/generate.cpp b/src/generate_spirv_parser/generate.cpp index 601e095..03e9c68 100644 --- a/src/generate_spirv_parser/generate.cpp +++ b/src/generate_spirv_parser/generate.cpp @@ -369,6 +369,8 @@ private: write_system_include(spirv_h, "iterator"); write_local_include(spirv_h, "util/string_view.h"); write_local_include(spirv_h, "util/enum.h"); + write_local_include(spirv_h, "spirv/word.h"); + write_local_include(spirv_h, "spirv/literal_string.h"); } static void write_opening_namespaces(detail::Generated_output_stream &os) { @@ -606,12 +608,8 @@ private: } void write_basic_types() { - spirv_h << R"(typedef std::uint32_t Word; -typedef Word Id; - -#error add Literal_string + spirv_h << R"(typedef Word Id; )"; -#warning add Literal_string } static std::string instruction_set_version_name(const ast::Extension_instruction_set &v) { @@ -815,7 +813,8 @@ private: struct Literal_kind_hasher { // use my own hasher because libstdc++ from gcc 5 doesn't support std::hash on enums - constexpr std::size_t operator()(ast::Operand_kinds::Operand_kind::Literal_kind v) const noexcept + constexpr std::size_t operator()(ast::Operand_kinds::Operand_kind::Literal_kind v) const + noexcept { return static_cast(v); } @@ -825,8 +824,7 @@ private: #warning replace with util::Enum_map when finished std::unordered_map - literal_type_descriptors; + Literal_kind_hasher> literal_type_descriptors; private: void fill_literal_type_descriptors() diff --git a/src/spirv/CMakeLists.txt b/src/spirv/CMakeLists.txt index e1fefdf..6e1148d 100644 --- a/src/spirv/CMakeLists.txt +++ b/src/spirv/CMakeLists.txt @@ -20,7 +20,7 @@ # cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -set(sources) +set(sources literal_string.cpp) set(spirv_parser_generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/generated) set(spirv_parser_generated_dir ${spirv_parser_generated_include_dir}/spirv) diff --git a/src/spirv/literal_string.cpp b/src/spirv/literal_string.cpp new file mode 100644 index 0000000..edf7c52 --- /dev/null +++ b/src/spirv/literal_string.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#include "literal_string.h" + +namespace vulkan_cpu +{ +namespace spirv +{ +constexpr std::size_t Literal_string::npos; +} +} diff --git a/src/spirv/literal_string.h b/src/spirv/literal_string.h new file mode 100644 index 0000000..d21529b --- /dev/null +++ b/src/spirv/literal_string.h @@ -0,0 +1,431 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef SPIRV_LITERAL_STRING_H_ +#define SPIRV_LITERAL_STRING_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "word.h" +#include "util/endian.h" +#include "util/string_view.h" + +namespace vulkan_cpu +{ +namespace spirv +{ +/** reference to a SPIR-V string */ +class Literal_string +{ + static_assert(sizeof(Word) == 4, ""); + static_assert(std::is_same::value, ""); + +public: + constexpr Literal_string() noexcept : begin_iter(), byte_count(0) + { + } + constexpr Literal_string(const Word *word_array, std::size_t byte_count) noexcept + : begin_iter(word_array, 0), + byte_count(byte_count) + { + } + class const_iterator + { + friend class Literal_string; + + public: + typedef std::ptrdiff_t difference_type; + typedef char value_type; + typedef const char *pointer; + typedef const char &reference; + typedef std::random_access_iterator_tag iterator_category; + + private: + const Word *word_array; + std::size_t index; + + private: + static constexpr std::size_t get_memory_offset(std::size_t index) noexcept + { + switch(util::endian) + { + case util::Endian::Big: + static_assert((sizeof(Word) & (sizeof(Word) - 1)) == 0, + "sizeof(Word) is not a power of 2"); + return index ^ (sizeof(Word) - 1); + case util::Endian::Little: + return index; + } + } + + private: + constexpr explicit const_iterator(const Word *word_array, std::size_t index) noexcept + : word_array(word_array), + index(index) + { + } + static const char *get_memory_pointer(const Word *word_array, std::size_t index) noexcept + { + return reinterpret_cast(word_array) + get_memory_offset(index); + } + + public: + constexpr const_iterator() noexcept : word_array(nullptr), index(0) + { + } + const char *operator->() const noexcept + { + return get_memory_pointer(word_array, index); + } + const char &operator*() const noexcept + { + return *get_memory_pointer(word_array, index); + } + constexpr const_iterator &operator++() noexcept + { + index++; + return *this; + } + constexpr const_iterator &operator--() noexcept + { + index--; + return *this; + } + constexpr const_iterator operator++(int) noexcept + { + return const_iterator(word_array, index++); + } + constexpr const_iterator operator--(int) noexcept + { + auto retval = *this; + operator--(); + return retval; + } + constexpr const_iterator &operator+=(std::ptrdiff_t offset) noexcept + { + index += offset; + return *this; + } + constexpr const_iterator &operator-=(std::ptrdiff_t offset) noexcept + { + index -= offset; + return *this; + } + friend constexpr const_iterator operator+(std::ptrdiff_t offset, + const_iterator iter) noexcept + { + return iter += offset; + } + friend constexpr const_iterator operator+(const_iterator iter, + std::ptrdiff_t offset) noexcept + { + return iter += offset; + } + friend constexpr const_iterator operator-(const_iterator iter, + std::ptrdiff_t offset) noexcept + { + return iter -= offset; + } + friend constexpr std::ptrdiff_t operator-(const_iterator l, const_iterator r) noexcept + { + return static_cast(l.index) - static_cast(r.index); + } + const char &operator[](std::ptrdiff_t offset) const noexcept + { + return *get_memory_pointer(word_array, index + offset); + } + constexpr bool operator==(const const_iterator &r) noexcept + { + return index == r.index; + } + constexpr bool operator!=(const const_iterator &r) noexcept + { + return index != r.index; + } + constexpr bool operator<=(const const_iterator &r) noexcept + { + return index <= r.index; + } + constexpr bool operator>=(const const_iterator &r) noexcept + { + return index >= r.index; + } + constexpr bool operator<(const const_iterator &r) noexcept + { + return index < r.index; + } + constexpr bool operator>(const const_iterator &r) noexcept + { + return index > r.index; + } + }; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + constexpr std::size_t size() const noexcept + { + return byte_count; + } + constexpr const_iterator begin() const noexcept + { + return begin_iter; + } + constexpr const_iterator end() const noexcept + { + return begin_iter + byte_count; + } + constexpr const_iterator cbegin() const noexcept + { + return begin_iter; + } + constexpr const_iterator cend() const noexcept + { + return begin_iter + byte_count; + } + const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator(end()); + } + const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator(begin()); + } + const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator(end()); + } + const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator(begin()); + } + const char &operator[](std::size_t index) const noexcept + { + assert(index < byte_count); + return begin()[index]; + } + const char &front() const noexcept + { + return operator[](0); + } + const char &back() const noexcept + { + return operator[](byte_count - 1); + } + constexpr bool empty() const noexcept + { + return byte_count == 0; + } + constexpr void swap(Literal_string &rt) noexcept + { + auto temp = *this; + *this = rt; + rt = temp; + } + constexpr void remove_prefix(std::size_t count) noexcept + { + assert(count <= byte_count); + begin_iter += count; + byte_count -= count; + } + constexpr void remove_suffix(std::size_t count) noexcept + { + assert(count <= byte_count); + byte_count -= count; + } + static constexpr std::size_t npos = -1; + constexpr Literal_string substr(std::size_t pos = 0, std::size_t count = npos) const + { + if(pos > byte_count) + throw std::out_of_range("Literal_string::substr"); + auto retval = *this; + retval.remove_prefix(pos); + if(count < retval.byte_count) + retval.byte_count = count; + return retval; + } + +private: + template + constexpr int compare_implementation(T rt) const noexcept + { + auto l_iter = begin(); + auto r_iter = rt.begin(); + for(; l_iter != end() && r_iter != rt.end(); ++l_iter, ++r_iter) + { + unsigned char l_char = *l_iter; + unsigned char r_char = *r_iter; + if(l_char < r_char) + return -1; + if(l_char > r_char) + return 1; + } + if(l_iter != end()) + return 1; + if(r_iter != rt.end()) + return -1; + return 0; + } + +public: + constexpr int compare(Literal_string rt) const noexcept + { + return compare_implementation(rt); + } + constexpr int compare(util::string_view rt) const noexcept + { + return compare_implementation(rt); + } + int compare(const char *rt) const noexcept + { + return compare(util::string_view(rt)); + } + constexpr int compare(std::size_t l_pos, std::size_t l_count, Literal_string rt) const + { + return substr(l_pos, l_count).compare(rt); + } + constexpr int compare(std::size_t l_pos, std::size_t l_count, util::string_view rt) const + { + return substr(l_pos, l_count).compare(rt); + } + constexpr int compare(std::size_t l_pos, std::size_t l_count, const char *rt) const + { + return substr(l_pos, l_count).compare(rt); + } + constexpr int compare(std::size_t l_pos, + std::size_t l_count, + Literal_string rt, + std::size_t r_pos, + std::size_t r_count) const + { + return substr(l_pos, l_count).compare(rt.substr(r_pos, r_count)); + } + constexpr int compare(std::size_t l_pos, + std::size_t l_count, + util::string_view rt, + std::size_t r_pos, + std::size_t r_count) const + { + return substr(l_pos, l_count).compare(rt.substr(r_pos, r_count)); + } + constexpr int compare(std::size_t l_pos, + std::size_t l_count, + const char *rt, + std::size_t r_count) const + { + return substr(l_pos, l_count).compare(util::string_view(rt, r_count)); + } + template + explicit operator std::basic_string, Allocator>() const + { + return std::basic_string, Allocator>(begin(), end()); + } + friend constexpr bool operator==(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) == 0; + } + friend constexpr bool operator==(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) == 0; + } + friend constexpr bool operator==(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) == 0; + } + friend constexpr bool operator!=(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) != 0; + } + friend constexpr bool operator!=(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) != 0; + } + friend constexpr bool operator!=(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) != 0; + } + friend constexpr bool operator>(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) > 0; + } + friend constexpr bool operator>(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) < 0; + } + friend constexpr bool operator>(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) > 0; + } + friend constexpr bool operator<(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) < 0; + } + friend constexpr bool operator<(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) > 0; + } + friend constexpr bool operator<(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) < 0; + } + friend constexpr bool operator>=(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) >= 0; + } + friend constexpr bool operator>=(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) <= 0; + } + friend constexpr bool operator>=(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) >= 0; + } + friend constexpr bool operator<=(Literal_string a, Literal_string b) noexcept + { + return a.compare(b) <= 0; + } + friend constexpr bool operator<=(util::string_view a, Literal_string b) noexcept + { + return b.compare(a) >= 0; + } + friend constexpr bool operator<=(Literal_string a, util::string_view b) noexcept + { + return a.compare(b) <= 0; + } + friend std::ostream &operator<<(std::ostream &os, Literal_string v) + { + os << static_cast(v); + return os; + } + +private: + const_iterator begin_iter; + std::size_t byte_count; +}; +} +} + +#endif /* SPIRV_LITERAL_STRING_H_ */ diff --git a/src/spirv/word.h b/src/spirv/word.h new file mode 100644 index 0000000..35bbea3 --- /dev/null +++ b/src/spirv/word.h @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef SPIRV_WORD_H_ +#define SPIRV_WORD_H_ + +#include + +namespace vulkan_cpu +{ +namespace spirv +{ +typedef std::uint32_t Word; +} +} + +#endif /* SPIRV_WORD_H_ */ diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index b27d6bf..2f6d1a3 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -19,6 +19,14 @@ # SOFTWARE. # cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +include(TestBigEndian) +TEST_BIG_ENDIAN(is_big_endian) +if(is_big_endian) +set(UTIL_ENDIAN Big) +else() +set(UTIL_ENDIAN Little) +endif() +configure_file(endian_config.h.in endian_config.h ESCAPE_QUOTES) set(sources bit_intrinsics.cpp bitset.cpp copy_cv_ref.cpp @@ -33,4 +41,6 @@ set(sources bit_intrinsics.cpp variant.cpp void_t.cpp) add_library(util STATIC ${sources}) +target_include_directories(util PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/..) add_executable(util_test EXCLUDE_FROM_ALL ${sources} util_test.cpp) +target_include_directories(util_test PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/..) diff --git a/src/util/endian.h b/src/util/endian.h new file mode 100644 index 0000000..20a801c --- /dev/null +++ b/src/util/endian.h @@ -0,0 +1,43 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef UTIL_ENDIAN_H_ +#define UTIL_ENDIAN_H_ + +#include "util/endian_config.h" + +namespace vulkan_cpu +{ +namespace util +{ +enum class Endian +{ + Little, + Big, + Native = vulkan_cpu_util_endian_endian, +}; + +constexpr Endian endian = Endian::Native; +} +} + +#endif /* UTIL_ENDIAN_H_ */ diff --git a/src/util/endian_config.h.in b/src/util/endian_config.h.in new file mode 100644 index 0000000..1b5a3a7 --- /dev/null +++ b/src/util/endian_config.h.in @@ -0,0 +1,29 @@ +/* + * Copyright 2017 Jacob Lifshay + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +#ifndef UTIL_ENDIAN_CONFIG_H_ +#define UTIL_ENDIAN_CONFIG_H_ + +#define vulkan_cpu_util_endian_endian @UTIL_ENDIAN@ + +#endif /* UTIL_ENDIAN_CONFIG_H_ */ + -- 2.30.2