working on rewriting spirv_to_llvm
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 24 Oct 2017 06:20:21 +0000 (23:20 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 24 Oct 2017 06:20:21 +0000 (23:20 -0700)
17 files changed:
src/spirv_to_llvm/CMakeLists.txt
src/spirv_to_llvm/debug_info.cpp [deleted file]
src/spirv_to_llvm/debug_info.h [deleted file]
src/spirv_to_llvm/parser_callbacks.h [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_annotations.cpp [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_annotations.h [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_capabilities.cpp [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_capabilities.h [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_debug.cpp [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_debug.h [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_extensions.cpp [new file with mode: 0644]
src/spirv_to_llvm/parser_callbacks_extensions.h [new file with mode: 0644]
src/spirv_to_llvm/spirv_id.h
src/spirv_to_llvm/spirv_to_llvm.h
src/spirv_to_llvm/translator.cpp
src/spirv_to_llvm/translator.h
src/vulkan/api_objects.h

index 7802909e4d20bf5c80b778ffb19a789e5db84d65..2e5b114d9d0642c62991f59cdf8ec9d31a6eb614 100644 (file)
 cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
 
 set(sources core_instructions.cpp
-            debug_info.cpp
             fragment_entry_point.cpp
             glsl_instructions.cpp
             opencl_instructions.cpp
+            parser_callbacks_annotations.cpp
+            parser_callbacks_capabilities.cpp
+            parser_callbacks_debug.cpp
+            parser_callbacks_extensions.cpp
             spirv_to_llvm.cpp
             translator.cpp
             vertex_entry_point.cpp)
diff --git a/src/spirv_to_llvm/debug_info.cpp b/src/spirv_to_llvm/debug_info.cpp
deleted file mode 100644 (file)
index 1c487e2..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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 "debug_info.h"
-
-namespace kazan
-{
-namespace spirv_to_llvm
-{
-void Parser_debug_callbacks::clear_line_info_because_end_of_block()
-{
-    handle_instruction_op_no_line({}, 0);
-}
-
-Spirv_location Parser_debug_callbacks::get_location(std::size_t instruction_start_index) const
-    noexcept
-{
-    return Spirv_location(current_location, instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_source_continued(
-    spirv::Op_source_continued instruction, std::size_t instruction_start_index)
-{
-    static_cast<void>(instruction);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_source(spirv::Op_source instruction,
-                                                          std::size_t instruction_start_index)
-{
-    if(instruction.file)
-    {
-        auto *filename = get_id<Spirv_string>(*instruction.file);
-        current_location.filename = filename;
-        source_filename = filename;
-    }
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_source_extension(
-    spirv::Op_source_extension instruction, std::size_t instruction_start_index)
-{
-    static_cast<void>(instruction);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_name(spirv::Op_name instruction,
-                                                        std::size_t instruction_start_index)
-{
-    auto &map = per_shader_state->names;
-    if(map.count(instruction.target) == 0)
-        map[instruction.target] = std::string(instruction.name);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_member_name(spirv::Op_member_name instruction,
-                                                               std::size_t instruction_start_index)
-{
-    auto &map = per_shader_state->member_names[instruction.type];
-    if(map.count(instruction.member) == 0)
-        map[instruction.member] = std::string(instruction.name);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_string(spirv::Op_string instruction,
-                                                          std::size_t instruction_start_index)
-{
-    if(!get_id(instruction.result))
-        set_id(instruction.result,
-               std::make_unique<Spirv_string>(static_cast<std::string>(instruction.string)));
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_line(spirv::Op_line instruction,
-                                                        std::size_t instruction_start_index)
-{
-    current_location.filename = get_id<Spirv_string>(instruction.file);
-    current_location.line_info = Spirv_location::Line_info(instruction.line, instruction.column);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_no_line(spirv::Op_no_line instruction,
-                                                           std::size_t instruction_start_index)
-{
-    current_location.filename = source_filename;
-    current_location.line_info.reset();
-    static_cast<void>(instruction);
-    static_cast<void>(instruction_start_index);
-}
-
-void Parser_debug_callbacks::handle_instruction_op_module_processed(
-    spirv::Op_module_processed instruction, std::size_t instruction_start_index)
-{
-    static_cast<void>(instruction);
-    static_cast<void>(instruction_start_index);
-}
-}
-}
diff --git a/src/spirv_to_llvm/debug_info.h b/src/spirv_to_llvm/debug_info.h
deleted file mode 100644 (file)
index dd61e17..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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_TO_LLVM_DEBUG_INFO_H_
-#define SPIRV_TO_LLVM_DEBUG_INFO_H_
-
-#include <cstddef>
-#include "spirv/spirv.h"
-#include "vulkan/api_objects.h"
-#include <string>
-#include "translator.h"
-
-namespace kazan
-{
-namespace spirv_to_llvm
-{
-struct Spirv_string final : public Spirv_id
-{
-    const std::string value;
-    explicit Spirv_string(std::string value) noexcept : value(std::move(value))
-    {
-    }
-};
-
-struct Spirv_location_without_instruction_start_index
-{
-    const vulkan::Vulkan_shader_module *shader_module;
-    const Spirv_string *filename;
-    util::string_view get_filename_string() const noexcept
-    {
-        if(filename)
-            return filename->value;
-        return {};
-    }
-    struct Line_info
-    {
-        spirv::Word line = 0;
-        spirv::Word column = 0;
-        constexpr Line_info() noexcept
-        {
-        }
-        constexpr Line_info(spirv::Word line, spirv::Word column) noexcept : line(line),
-                                                                             column(column)
-        {
-        }
-    };
-    util::optional<Line_info> line_info;
-    Spirv_location_without_instruction_start_index() noexcept : shader_module(nullptr),
-                                                                filename(nullptr),
-                                                                line_info()
-    {
-    }
-    Spirv_location_without_instruction_start_index(
-        const vulkan::Vulkan_shader_module *shader_module,
-        const Spirv_string *filename,
-        util::optional<Line_info> line_info) noexcept : shader_module(shader_module),
-                                                        filename(filename),
-                                                        line_info(line_info)
-    {
-    }
-};
-
-struct Spirv_location : public Spirv_location_without_instruction_start_index
-{
-    std::size_t instruction_start_index;
-    Spirv_location() noexcept : Spirv_location_without_instruction_start_index(),
-                                instruction_start_index(0)
-    {
-    }
-    Spirv_location(Spirv_location_without_instruction_start_index location,
-                   std::size_t instruction_start_index) noexcept
-        : Spirv_location_without_instruction_start_index(location),
-          instruction_start_index(instruction_start_index)
-    {
-    }
-};
-
-class Parser_debug_callbacks : public virtual Parser_callbacks_base
-{
-private:
-    const Spirv_string *source_filename = nullptr;
-    Spirv_location_without_instruction_start_index current_location;
-
-protected:
-    virtual void clear_line_info_because_end_of_block() override final;
-    virtual Spirv_location get_location(std::size_t instruction_start_index) const
-        noexcept override final;
-
-public:
-    virtual void handle_instruction_op_source_continued(
-        spirv::Op_source_continued instruction, std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_source(spirv::Op_source instruction,
-                                              std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_source_extension(
-        spirv::Op_source_extension instruction, std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_name(spirv::Op_name instruction,
-                                            std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_member_name(spirv::Op_member_name instruction,
-                                                   std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_string(spirv::Op_string instruction,
-                                              std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_line(spirv::Op_line instruction,
-                                            std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_no_line(spirv::Op_no_line instruction,
-                                               std::size_t instruction_start_index) override;
-    virtual void handle_instruction_op_module_processed(
-        spirv::Op_module_processed instruction, std::size_t instruction_start_index) override;
-};
-}
-}
-
-#endif // SPIRV_TO_LLVM_DEBUG_INFO_H_
diff --git a/src/spirv_to_llvm/parser_callbacks.h b/src/spirv_to_llvm/parser_callbacks.h
new file mode 100644 (file)
index 0000000..33fe863
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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_TO_LLVM_PARSER_CALLBACKS_H_
+#define SPIRV_TO_LLVM_PARSER_CALLBACKS_H_
+
+#include "translator.h"
+#include "parser_callbacks_capabilities.h"
+#include "parser_callbacks_extensions.h"
+#include "parser_callbacks_debug.h"
+#include "parser_callbacks_annotations.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+class Callbacks final : public Header_callbacks,
+                        public Capabilities_callbacks,
+                        public Extensions_callbacks,
+                        public Debug_callbacks,
+                        public Annotations_callbacks
+{
+public:
+    Callbacks(Translator *translator, spirv::Execution_model execution_model) noexcept
+    {
+        init(translator, execution_model);
+    }
+};
+}
+}
+}
+
+#endif // SPIRV_TO_LLVM_PARSER_CALLBACKS_H_
diff --git a/src/spirv_to_llvm/parser_callbacks_annotations.cpp b/src/spirv_to_llvm/parser_callbacks_annotations.cpp
new file mode 100644 (file)
index 0000000..72de7d8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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 "parser_callbacks_annotations.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+void Annotations_callbacks::handle_instruction_op_decorate(spirv::Op_decorate instruction,
+                                                           std::size_t instruction_start_index)
+{
+    auto &decorations = per_shader_state->decorations[instruction.target];
+    decorations.emplace(instruction_start_index, std::move(instruction.decoration));
+}
+
+void Annotations_callbacks::handle_instruction_op_member_decorate(
+    spirv::Op_member_decorate instruction, std::size_t instruction_start_index)
+{
+    auto &decorations =
+        per_shader_state->member_decorations[instruction.structure_type][instruction.member];
+    decorations.emplace(instruction_start_index, std::move(instruction.decoration));
+}
+
+void Annotations_callbacks::handle_instruction_op_decoration_group(
+    spirv::Op_decoration_group instruction, std::size_t instruction_start_index)
+{
+    if(!is_id_defined_at(instruction.result, instruction_start_index))
+    {
+        auto decoration_range = get_decoration_range(instruction.result);
+        set_id(instruction.result,
+               std::make_unique<Spirv_decoration_group>(
+                   instruction_start_index,
+                   Spirv_decoration_set(std::get<0>(decoration_range),
+                                        std::get<1>(decoration_range))));
+    }
+}
+
+void Annotations_callbacks::handle_instruction_op_group_decorate(
+    spirv::Op_group_decorate instruction, std::size_t instruction_start_index)
+{
+    auto &decoration_group = get_id<Spirv_decoration_group>(instruction.decoration_group);
+    for(auto &target : instruction.targets)
+        per_shader_state->decorations[target].insert(decoration_group.value.begin(),
+                                                     decoration_group.value.end());
+    static_cast<void>(instruction_start_index);
+}
+
+void Annotations_callbacks::handle_instruction_op_group_member_decorate(
+    spirv::Op_group_member_decorate instruction, std::size_t instruction_start_index)
+{
+    auto &decoration_group = get_id<Spirv_decoration_group>(instruction.decoration_group);
+    for(auto &target : instruction.targets)
+        per_shader_state->member_decorations[target.part_1][target.part_2].insert(
+            decoration_group.value.begin(), decoration_group.value.end());
+    static_cast<void>(instruction_start_index);
+}
+
+void Annotations_callbacks::handle_instruction_op_decorate_id(spirv::Op_decorate_id instruction,
+                                                              std::size_t instruction_start_index)
+{
+    auto &decorations = per_shader_state->decorations[instruction.target];
+    decorations.emplace(instruction_start_index, std::move(instruction.decoration));
+}
+}
+}
+}
diff --git a/src/spirv_to_llvm/parser_callbacks_annotations.h b/src/spirv_to_llvm/parser_callbacks_annotations.h
new file mode 100644 (file)
index 0000000..002aecf
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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_TO_LLVM_PARSER_CALLBACKS_ANNOTATIONS_H_
+#define SPIRV_TO_LLVM_PARSER_CALLBACKS_ANNOTATIONS_H_
+
+#include "spirv/spirv.h"
+#include "translator.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+struct Spirv_decoration_group final : public Spirv_id
+{
+    const Spirv_decoration_set value;
+    explicit Spirv_decoration_group(std::size_t defining_instruction_start_index,
+                                    Spirv_decoration_set value) noexcept
+        : Spirv_id(defining_instruction_start_index),
+          value(std::move(value))
+    {
+    }
+};
+
+class Annotations_callbacks : public virtual Parser_callbacks_base
+{
+public:
+    virtual void handle_instruction_op_decorate(spirv::Op_decorate instruction,
+                                                std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_member_decorate(
+        spirv::Op_member_decorate instruction, std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_decoration_group(
+        spirv::Op_decoration_group instruction, std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_group_decorate(
+        spirv::Op_group_decorate instruction, std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_group_member_decorate(
+        spirv::Op_group_member_decorate instruction,
+        std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_decorate_id(
+        spirv::Op_decorate_id instruction, std::size_t instruction_start_index) override final;
+};
+}
+}
+}
+
+#endif // SPIRV_TO_LLVM_PARSER_CALLBACKS_ANNOTATIONS_H_
diff --git a/src/spirv_to_llvm/parser_callbacks_capabilities.cpp b/src/spirv_to_llvm/parser_callbacks_capabilities.cpp
new file mode 100644 (file)
index 0000000..0e5b362
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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 "parser_callbacks_capabilities.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+void Capabilities_callbacks::handle_instruction_op_capability(spirv::Op_capability instruction,
+                                                              std::size_t instruction_start_index)
+{
+    using spirv::Capability;
+    util::Enum_set<Capability> work_list{instruction.capability};
+    while(!work_list.empty())
+    {
+        auto capability = *work_list.begin();
+        work_list.erase(capability);
+        if(std::get<1>(enabled_capabilities.insert(capability)))
+        {
+            auto additional_capabilities = get_directly_required_capabilities(capability);
+            work_list.insert(additional_capabilities.begin(), additional_capabilities.end());
+        }
+    }
+    constexpr util::Enum_set<Capability> implemented_capabilities{
+        Capability::matrix,
+        Capability::shader,
+        Capability::float64,
+        Capability::int64,
+        Capability::int16,
+        Capability::input_attachment,
+        Capability::sampled1d,
+        Capability::image1d,
+        Capability::sampled_buffer,
+        Capability::image_buffer,
+        Capability::image_query,
+        Capability::derivative_control,
+    };
+    for(auto capability : enabled_capabilities)
+    {
+        if(implemented_capabilities.count(capability) == 0)
+            throw spirv::Parser_error(
+                instruction_start_index,
+                instruction_start_index,
+                "capability not implemented: " + std::string(get_enumerant_name(capability)));
+    }
+}
+}
+}
+}
diff --git a/src/spirv_to_llvm/parser_callbacks_capabilities.h b/src/spirv_to_llvm/parser_callbacks_capabilities.h
new file mode 100644 (file)
index 0000000..dc8e257
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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_TO_LLVM_PARSER_CALLBACKS_CAPABILITIES_H_
+#define SPIRV_TO_LLVM_PARSER_CALLBACKS_CAPABILITIES_H_
+
+#include "spirv/spirv.h"
+#include "translator.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+class Capabilities_callbacks : public virtual Parser_callbacks_base
+{
+private:
+    util::Enum_set<spirv::Capability> enabled_capabilities;
+
+public:
+    virtual void handle_instruction_op_capability(
+        spirv::Op_capability instruction, std::size_t instruction_start_index) override final;
+};
+}
+}
+}
+
+#endif // SPIRV_TO_LLVM_PARSER_CALLBACKS_CAPABILITIES_H_
diff --git a/src/spirv_to_llvm/parser_callbacks_debug.cpp b/src/spirv_to_llvm/parser_callbacks_debug.cpp
new file mode 100644 (file)
index 0000000..e6eeb1e
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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 "parser_callbacks_debug.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+void Debug_callbacks::clear_line_info_because_end_of_block()
+{
+    handle_instruction_op_no_line({}, 0);
+}
+
+Spirv_location Debug_callbacks::get_location(std::size_t instruction_start_index) const noexcept
+{
+    return Spirv_location(current_location, instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_source_continued(spirv::Op_source_continued instruction,
+                                                             std::size_t instruction_start_index)
+{
+    static_cast<void>(instruction);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_source(spirv::Op_source instruction,
+                                                   std::size_t instruction_start_index)
+{
+    if(instruction.file)
+    {
+        auto &filename = get_id<Spirv_string>(*instruction.file);
+        current_location.filename = &filename;
+        source_filename = &filename;
+    }
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_source_extension(spirv::Op_source_extension instruction,
+                                                             std::size_t instruction_start_index)
+{
+    static_cast<void>(instruction);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_name(spirv::Op_name instruction,
+                                                 std::size_t instruction_start_index)
+{
+    auto &map = per_shader_state->names;
+    if(map.count(instruction.target) == 0)
+        map[instruction.target] = std::string(instruction.name);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_member_name(spirv::Op_member_name instruction,
+                                                        std::size_t instruction_start_index)
+{
+    auto &map = per_shader_state->member_names[instruction.type];
+    if(map.count(instruction.member) == 0)
+        map[instruction.member] = std::string(instruction.name);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_string(spirv::Op_string instruction,
+                                                   std::size_t instruction_start_index)
+{
+    if(!is_id_defined_at(instruction.result, instruction_start_index))
+        set_id(instruction.result,
+               std::make_unique<Spirv_string>(instruction_start_index, static_cast<std::string>(instruction.string)));
+}
+
+void Debug_callbacks::handle_instruction_op_line(spirv::Op_line instruction,
+                                                 std::size_t instruction_start_index)
+{
+    current_location.filename = &get_id<Spirv_string>(instruction.file);
+    current_location.line_info = Spirv_location::Line_info(instruction.line, instruction.column);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_no_line(spirv::Op_no_line instruction,
+                                                    std::size_t instruction_start_index)
+{
+    current_location.filename = source_filename;
+    current_location.line_info.reset();
+    static_cast<void>(instruction);
+    static_cast<void>(instruction_start_index);
+}
+
+void Debug_callbacks::handle_instruction_op_module_processed(spirv::Op_module_processed instruction,
+                                                             std::size_t instruction_start_index)
+{
+    static_cast<void>(instruction);
+    static_cast<void>(instruction_start_index);
+}
+}
+}
+}
diff --git a/src/spirv_to_llvm/parser_callbacks_debug.h b/src/spirv_to_llvm/parser_callbacks_debug.h
new file mode 100644 (file)
index 0000000..8af87ce
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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_TO_LLVM_PARSER_CALLBACKS_DEBUG_H_
+#define SPIRV_TO_LLVM_PARSER_CALLBACKS_DEBUG_H_
+
+#include <cstddef>
+#include "spirv/spirv.h"
+#include "vulkan/api_objects.h"
+#include <string>
+#include "translator.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+struct Spirv_string final : public Spirv_id
+{
+    const std::string value;
+    Spirv_string(std::size_t defining_instruction_start_index, std::string value) noexcept
+        : Spirv_id(defining_instruction_start_index),
+          value(std::move(value))
+    {
+    }
+};
+
+struct Spirv_location_without_instruction_start_index
+{
+    const vulkan::Vulkan_shader_module *shader_module;
+    const Spirv_string *filename;
+    util::string_view get_filename_string() const noexcept
+    {
+        if(filename)
+            return filename->value;
+        return {};
+    }
+    struct Line_info
+    {
+        spirv::Word line = 0;
+        spirv::Word column = 0;
+        constexpr Line_info() noexcept
+        {
+        }
+        constexpr Line_info(spirv::Word line, spirv::Word column) noexcept : line(line),
+                                                                             column(column)
+        {
+        }
+    };
+    util::optional<Line_info> line_info;
+    Spirv_location_without_instruction_start_index() noexcept : shader_module(nullptr),
+                                                                filename(nullptr),
+                                                                line_info()
+    {
+    }
+    Spirv_location_without_instruction_start_index(
+        const vulkan::Vulkan_shader_module *shader_module,
+        const Spirv_string *filename,
+        util::optional<Line_info> line_info) noexcept : shader_module(shader_module),
+                                                        filename(filename),
+                                                        line_info(line_info)
+    {
+    }
+};
+
+struct Spirv_location : public Spirv_location_without_instruction_start_index
+{
+    std::size_t instruction_start_index;
+    Spirv_location() noexcept : Spirv_location_without_instruction_start_index(),
+                                instruction_start_index(0)
+    {
+    }
+    Spirv_location(Spirv_location_without_instruction_start_index location,
+                   std::size_t instruction_start_index) noexcept
+        : Spirv_location_without_instruction_start_index(location),
+          instruction_start_index(instruction_start_index)
+    {
+    }
+};
+
+namespace parser_callbacks
+{
+class Debug_callbacks : public virtual Parser_callbacks_base
+{
+private:
+    const Spirv_string *source_filename = nullptr;
+    Spirv_location_without_instruction_start_index current_location;
+
+protected:
+    virtual void clear_line_info_because_end_of_block() override final;
+    virtual Spirv_location get_location(std::size_t instruction_start_index) const
+        noexcept override final;
+
+public:
+    virtual void handle_instruction_op_source_continued(
+        spirv::Op_source_continued instruction, std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_source(spirv::Op_source instruction,
+                                              std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_source_extension(
+        spirv::Op_source_extension instruction, std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_name(spirv::Op_name instruction,
+                                            std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_member_name(spirv::Op_member_name instruction,
+                                                   std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_string(spirv::Op_string instruction,
+                                              std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_line(spirv::Op_line instruction,
+                                            std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_no_line(spirv::Op_no_line instruction,
+                                               std::size_t instruction_start_index) override;
+    virtual void handle_instruction_op_module_processed(
+        spirv::Op_module_processed instruction, std::size_t instruction_start_index) override;
+};
+}
+}
+}
+
+#endif // SPIRV_TO_LLVM_PARSER_CALLBACKS_DEBUG_H_
diff --git a/src/spirv_to_llvm/parser_callbacks_extensions.cpp b/src/spirv_to_llvm/parser_callbacks_extensions.cpp
new file mode 100644 (file)
index 0000000..2d0ca93
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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 "parser_callbacks_extensions.h"
+#include "json/json.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+void Extensions_callbacks::handle_instruction_op_extension(spirv::Op_extension instruction,
+                                                           std::size_t instruction_start_index)
+{
+    throw spirv::Parser_error(instruction_start_index,
+                              instruction_start_index,
+                              "unimplemented SPIR-V extension: " + std::string(instruction.name));
+}
+
+void Extensions_callbacks::handle_instruction_op_ext_inst_import(
+    spirv::Op_ext_inst_import instruction, std::size_t instruction_start_index)
+{
+    for(auto instruction_set : util::Enum_traits<spirv::Extension_instruction_set>::values)
+    {
+        if(instruction_set == spirv::Extension_instruction_set::unknown)
+            continue;
+        if(instruction.name == get_enumerant_name(instruction_set))
+        {
+            if(!is_id_defined_at(instruction.result, instruction_start_index))
+                set_id(instruction.result,
+                       std::make_unique<Spirv_extended_instruction_set>(instruction_start_index,
+                                                                        instruction_set));
+            return;
+        }
+    }
+    throw spirv::Parser_error(
+        instruction_start_index,
+        instruction_start_index,
+        "unknown SPIR-V extension instruction set: \"" + std::string(instruction.name) + "\"");
+}
+
+void Extensions_callbacks::handle_instruction_op_ext_inst(spirv::Op_ext_inst instruction,
+                                                          std::size_t instruction_start_index)
+{
+    // handles unknown extension instructions;
+    // the correct handle_instruction_* callback is called instead for known instructions
+    auto &instruction_set = get_id<Spirv_extended_instruction_set>(instruction.set);
+    throw spirv::Parser_error(instruction_start_index,
+                              instruction_start_index,
+                              json::ast::Number_value::append_unsigned_integer_to_string(
+                                  instruction.instruction,
+                                  "unknown SPIR-V extension instruction: "
+                                      + std::string(get_enumerant_name(instruction_set.value))
+                                      + ": 0x",
+                                  0x10));
+}
+}
+}
+}
diff --git a/src/spirv_to_llvm/parser_callbacks_extensions.h b/src/spirv_to_llvm/parser_callbacks_extensions.h
new file mode 100644 (file)
index 0000000..6995e29
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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_TO_LLVM_PARSER_CALLBACKS_EXTENSIONS_H_
+#define SPIRV_TO_LLVM_PARSER_CALLBACKS_EXTENSIONS_H_
+
+#include "spirv/spirv.h"
+#include "translator.h"
+
+namespace kazan
+{
+namespace spirv_to_llvm
+{
+namespace parser_callbacks
+{
+struct Spirv_extended_instruction_set final : public Spirv_id
+{
+    const spirv::Extension_instruction_set value;
+    Spirv_extended_instruction_set(std::size_t defining_instruction_start_index,
+                                   spirv::Extension_instruction_set value) noexcept
+        : Spirv_id(defining_instruction_start_index),
+          value(value)
+    {
+    }
+};
+
+class Extensions_callbacks : public virtual Parser_callbacks_base
+{
+public:
+    virtual void handle_instruction_op_extension(
+        spirv::Op_extension instruction, std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_ext_inst_import(
+        spirv::Op_ext_inst_import instruction, std::size_t instruction_start_index) override final;
+    virtual void handle_instruction_op_ext_inst(spirv::Op_ext_inst instruction,
+                                                std::size_t instruction_start_index) override final;
+};
+}
+}
+}
+
+#endif // SPIRV_TO_LLVM_PARSER_CALLBACKS_EXTENSIONS_H_
index 2d2963d5115825d03b3de5c0cd54a40e4d6f59c0..9be7a2c8f363e7aebf9c0d0f16569ae56fe85ff7 100644 (file)
@@ -36,6 +36,11 @@ namespace spirv_to_llvm
 class Spirv_id
 {
 public:
+    const std::size_t defining_instruction_start_index;
+    explicit Spirv_id(std::size_t defining_instruction_start_index) noexcept
+        : defining_instruction_start_index(defining_instruction_start_index)
+    {
+    }
     virtual ~Spirv_id() = default;
 };
 
@@ -62,17 +67,30 @@ public:
         return id_list[id - 1];
     }
     template <typename T = Spirv_id>
-    typename std::enable_if<std::is_base_of<Spirv_id, T>::value, T>::type *get_or_null(spirv::Id id) const noexcept
+    typename std::enable_if<std::is_base_of<Spirv_id, T>::value, T>::type *get_or_null(
+        spirv::Id id) const noexcept
     {
-        return dynamic_cast<T *>(operator[](id).get());
+        auto *base = operator[](id).get();
+        if(!base)
+            return nullptr;
+        auto *retval = dynamic_cast<T *>(base);
+        assert(retval && "SPIR-V id is of improper type");
+        return retval;
     }
     template <typename T = Spirv_id>
-    typename std::enable_if<std::is_base_of<Spirv_id, T>::value, T>::type &get(spirv::Id id) const noexcept
+    typename std::enable_if<std::is_base_of<Spirv_id, T>::value, T>::type &get(spirv::Id id) const
+        noexcept
     {
         auto *retval = get_or_null<T>(id);
-        assert(retval && "SPIR-V id is undefined or of improper type");
+        assert(retval && "SPIR-V id is undefined");
         return *retval;
     }
+    bool is_defined_at(spirv::Id id, std::size_t defining_instruction_start_index) const noexcept
+    {
+        if(auto *v = operator[](id).get())
+            return v->defining_instruction_start_index == defining_instruction_start_index;
+        return false;
+    }
     void set(spirv::Id id, std::unique_ptr<Spirv_id> value) noexcept
     {
         auto &v = operator[](id);
index 7899dc2e778412bec4d775df229bd7706aa80f88..532015527916a13cdad26a17bbb3236f57440bbb 100644 (file)
@@ -32,6 +32,7 @@
 #include <type_traits>
 #include <utility>
 #include <cstddef>
+#include <unordered_map>
 #include "llvm_wrapper/llvm_wrapper.h"
 #include "util/string_view.h"
 #include "vulkan/vulkan.h"
@@ -43,11 +44,8 @@ namespace kazan
 {
 namespace spirv_to_llvm
 {
-struct Spirv_decoration
-{
-    std::size_t instruction_start_index;
-    spirv::Decoration_with_parameters decoration;
-};
+/// std::size_t is instruction_start_index
+typedef std::unordered_map<std::size_t, spirv::Decoration_with_parameters> Spirv_decoration_set;
 
 namespace spirv_types
 {
@@ -185,9 +183,9 @@ public:
     {
         return instruction_start_index;
     }
-    virtual std::shared_ptr<Type> get_type_with_decoration(const Spirv_decoration &decoration) = 0;
+    virtual std::shared_ptr<Type> get_type_with_decoration(const Spirv_decoration_set::value_type &decoration) = 0;
     virtual std::shared_ptr<Type> get_type_with_member_decoration(
-        std::uint32_t member_index, const Spirv_decoration &decoration)
+        std::uint32_t member_index, const Spirv_decoration_set::value_type &decoration)
     {
         assert(!"type has no members to decorate");
         return shared_from_this();
@@ -210,18 +208,6 @@ struct Jit_symbol_resolver
             static_cast<Jit_symbol_resolver *>(user_data)->resolve(name));
     }
 };
-
-class Spirv_to_llvm;
-
-Converted_module spirv_to_llvm(::LLVMContextRef context,
-                               ::LLVMTargetMachineRef target_machine,
-                               const spirv::Word *shader_words,
-                               std::size_t shader_size,
-                               std::uint64_t shader_id,
-                               spirv::Execution_model execution_model,
-                               util::string_view entry_point_name,
-                               const VkPipelineVertexInputStateCreateInfo *vertex_input_state,
-                               pipeline::Instantiated_pipeline_layout &pipeline_layout);
 }
 }
 
index ff92586a97d5213afa04d62634cc5c883cfe7dfa..ade2596bc2ca299fe0cd3000108191239574ffcc 100644 (file)
@@ -26,16 +26,16 @@ namespace kazan
 {
 namespace spirv_to_llvm
 {
-void Parser_header_callbacks::handle_header(unsigned version_number_major,
-                                            unsigned version_number_minor,
-                                            spirv::Word generator_magic_number,
-                                            spirv::Word id_bound,
-                                            spirv::Word instruction_schema)
+void parser_callbacks::Header_callbacks::handle_header(unsigned version_number_major,
+                                                       unsigned version_number_minor,
+                                                       spirv::Word generator_magic_number,
+                                                       spirv::Word id_bound,
+                                                       spirv::Word instruction_schema)
 {
     if(translator->per_shader_states.count(execution_model) == 0)
     {
         per_shader_state = &std::get<1>(
-            *std::get<0>(translator->per_shader_states.emplace(execution_model, id_bound)));
+            *std::get<0>(translator->per_shader_states.emplace(execution_model, Translator::Per_shader_state(id_bound))));
     }
 }
 }
index 39403237ad75409d2e49e3f0834edbe641062b85..d9b677ad56699c06b882952c73c73b29959a918e 100644 (file)
@@ -43,7 +43,9 @@ struct Translator
         Spirv_id_list id_list;
         std::unordered_map<spirv::Id, std::string> names;
         std::unordered_map<spirv::Id, std::unordered_map<spirv::Word, std::string>> member_names;
-        std::unordered_multimap<spirv::Id, Spirv_decoration> decorations;
+        std::unordered_map<spirv::Id, Spirv_decoration_set> decorations;
+        std::unordered_map<spirv::Id, std::unordered_map<spirv::Word, Spirv_decoration_set>>
+            member_decorations;
         explicit Per_shader_state(spirv::Word id_bound) : id_list(id_bound)
         {
         }
@@ -72,6 +74,10 @@ struct Translator
     {
         return get_per_shader_state(execution_model).id_list.get<T>(id);
     }
+    bool is_id_defined_at(spirv::Execution_model execution_model, spirv::Id id, std::size_t defining_instruction_start_index) const noexcept
+    {
+        return get_per_shader_state(execution_model).id_list.is_defined_at(id, defining_instruction_start_index);
+    }
     void set_id(spirv::Execution_model execution_model,
                 spirv::Id id,
                 std::unique_ptr<Spirv_id> value) noexcept
@@ -103,57 +109,49 @@ struct Translator
             return {std::get<1>(*iter).begin(), std::get<1>(*iter).end()};
         return {};
     }
-    std::pair<std::unordered_multimap<spirv::Id, Spirv_decoration>::const_iterator,
-              std::unordered_multimap<spirv::Id, Spirv_decoration>::const_iterator>
+    std::pair<Spirv_decoration_set::const_iterator, Spirv_decoration_set::const_iterator>
         get_decoration_range(spirv::Execution_model execution_model, spirv::Id id) const
     {
-        return get_per_shader_state(execution_model).decorations.equal_range(id);
-    }
-
-private:
-    template <typename Fn,
-              typename... Args,
-              typename = typename std::enable_if<std::is_void<decltype(
-                  std::declval<Fn &>()(std::declval<Args>()...))>::value>::type>
-    static bool for_each_helper(Fn &&fn, Args &&... args)
-    {
-        fn(std::forward<Args>(args)...);
-        return true;
-    }
-    template <typename Fn, typename... Args>
-    static typename std::
-        enable_if<!std::is_void<decltype(std::declval<Fn &>()(std::declval<Args>()...))>::value,
-                  bool>::type
-        for_each_helper(Fn &&fn, Args &&... args)
-    {
-        return fn(std::forward<Args>(args)...);
+        auto &map = get_per_shader_state(execution_model).decorations;
+        auto iter = map.find(id);
+        if(iter != map.end())
+            return {std::get<1>(*iter).begin(), std::get<1>(*iter).end()};
+        return {};
     }
-
-public:
-    /// fn is the callback function; have fn return true or void to continue, false to break
-    template <typename Fn>
-    bool for_each_decoration(spirv::Execution_model execution_model, spirv::Id id, Fn &&fn)
+    std::pair<Spirv_decoration_set::const_iterator, Spirv_decoration_set::const_iterator>
+        get_member_decoration_range(spirv::Execution_model execution_model,
+                                    spirv::Id id,
+                                    spirv::Word member_index) const
     {
-        std::unordered_multimap<spirv::Id, Spirv_decoration>::const_iterator start, finish;
-        std::tie(start, finish) = get_decoration_range(execution_model, id);
-        for(auto iter = start; iter != finish; ++iter)
-            if(!for_each_helper(fn, std::get<1>(*iter)))
-                return false;
-        return true;
+        auto &map = get_per_shader_state(execution_model).member_decorations;
+        auto iter = map.find(id);
+        if(iter != map.end())
+        {
+            auto &map2 = std::get<1>(*iter);
+            auto iter2 = map2.find(member_index);
+            if(iter2 != map2.end())
+                return {std::get<1>(*iter2).begin(), std::get<1>(*iter2).end()};
+            return {};
+        }
+        return {};
     }
 };
 
-class Parser_callbacks_implementation;
+namespace parser_callbacks
+{
+class Callbacks;
+}
+
 struct Spirv_location;
 
 class Parser_callbacks_base : public spirv::Parser_callbacks
 {
-    friend class Parser_callbacks_implementation;
+    friend class parser_callbacks::Callbacks;
 
 protected:
     Translator *translator{};
     spirv::Execution_model execution_model{};
-    Per_shader_state *per_shader_state{};
+    Translator::Per_shader_state *per_shader_state{};
 
 private:
     void init(Translator *translator, spirv::Execution_model execution_model) noexcept
@@ -166,32 +164,34 @@ protected:
     template <typename T = Spirv_id>
     T *get_id_or_null(spirv::Id id) const noexcept
     {
-        return translator->get_id_or_null<T>(execution_model, id);
+        return per_shader_state->id_list.get_or_null<T>(id);
     }
     template <typename T = Spirv_id>
-    T *get_id(spirv::Id id) const noexcept
+    T &get_id(spirv::Id id) const noexcept
+    {
+        return per_shader_state->id_list.get<T>(id);
+    }
+    bool is_id_defined_at(spirv::Id id, std::size_t defining_instruction_start_index) const noexcept
     {
-        return translator->get_id<T>(execution_model, id);
+        return per_shader_state->id_list.is_defined_at(id, defining_instruction_start_index);
     }
     void set_id(spirv::Id id, std::unique_ptr<Spirv_id> value) noexcept
     {
-        translator->set_id(execution_model, id, std::move(value));
+        per_shader_state->id_list.set(id, std::move(value));
     }
     util::string_view get_name(spirv::Id id, util::string_view default_name = {})
     {
         return translator->get_name(execution_model, id, default_name);
     }
-    std::pair<std::unordered_multimap<spirv::Id, Spirv_decoration>::const_iterator,
-              std::unordered_multimap<spirv::Id, Spirv_decoration>::const_iterator>
-        get_decoration_range(spirv::Id id) noexcept
+    std::pair<Spirv_decoration_set::const_iterator, Spirv_decoration_set::const_iterator>
+        get_decoration_range(spirv::Id id) const
     {
         return translator->get_decoration_range(execution_model, id);
     }
-    /// fn is the callback function; have fn return true or void to continue, false to break
-    template <typename Fn>
-    bool for_each_decoration(spirv::Id id, Fn &&fn)
+    std::pair<Spirv_decoration_set::const_iterator, Spirv_decoration_set::const_iterator>
+        get_member_decoration_range(spirv::Id id, spirv::Word member_index) const
     {
-        return translator->for_each_decoration(execution_model, id, fn);
+        return translator->get_member_decoration_range(execution_model, id, member_index);
     }
 
 protected:
@@ -199,7 +199,9 @@ protected:
     virtual Spirv_location get_location(std::size_t instruction_start_index) const noexcept = 0;
 };
 
-class Parser_header_callbacks : public virtual Parser_callbacks_base
+namespace parser_callbacks
+{
+class Header_callbacks : public virtual Parser_callbacks_base
 {
 public:
     virtual void handle_header(unsigned version_number_major,
@@ -210,5 +212,6 @@ public:
 };
 }
 }
+}
 
 #endif // SPIRV_TO_LLVM_TRANSLATOR_H_
index b6f42da5c784b5e8c32708fe0f95abb7e113fbb5..197e2503c49c3736994e8cca1def56a9cb40ac1c 100644 (file)
@@ -1779,9 +1779,9 @@ struct Vulkan_physical_device
               .shaderStorageImageArrayDynamicIndexing = true,
               .shaderClipDistance = false,
               .shaderCullDistance = false,
-              .shaderFloat64 = false,
+              .shaderFloat64 = true,
               .shaderInt64 = true,
-              .shaderInt16 = false,
+              .shaderInt16 = true,
               .shaderResourceResidency = false,
               .shaderResourceMinLod = false,
               .sparseBinding = false,