Move functions for building modules outside of the C++ interface.
authorLei Zhang <antiagainst@google.com>
Fri, 9 Sep 2016 18:45:18 +0000 (14:45 -0400)
committerLei Zhang <antiagainst@google.com>
Fri, 16 Sep 2016 18:02:47 +0000 (14:02 -0400)
12 files changed:
source/opt/CMakeLists.txt
source/opt/build_module.cpp [new file with mode: 0644]
source/opt/build_module.h [new file with mode: 0644]
source/opt/libspirv.cpp
source/opt/libspirv.hpp
test/cpp_interface.cpp
test/opt/pass_fixture.h
test/opt/test_def_use.cpp
test/opt/test_ir_loader.cpp
test/opt/test_module.cpp
test/opt/test_type_manager.cpp
tools/opt/opt.cpp

index 431f2d1..b9a586f 100644 (file)
@@ -13,6 +13,7 @@
 # limitations under the License.
 add_library(SPIRV-Tools-opt
   basic_block.h
+  build_module.h
   constants.h
   def_use_manager.h
   eliminate_dead_constant_pass.h
@@ -35,6 +36,7 @@ add_library(SPIRV-Tools-opt
   type_manager.h
   unify_const_pass.h
 
+  build_module.cpp
   def_use_manager.cpp
   eliminate_dead_constant_pass.cpp
   function.cpp
diff --git a/source/opt/build_module.cpp b/source/opt/build_module.cpp
new file mode 100644 (file)
index 0000000..5686275
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "build_module.h"
+
+#include "ir_loader.h"
+#include "libspirv.hpp"
+#include "make_unique.h"
+#include "table.h"
+
+namespace spvtools {
+
+namespace {
+
+// Sets the module header for IrLoader. Meets the interface requirement of
+// spvBinaryParse().
+spv_result_t SetSpvHeader(void* builder, spv_endianness_t, uint32_t magic,
+                          uint32_t version, uint32_t generator,
+                          uint32_t id_bound, uint32_t reserved) {
+  reinterpret_cast<ir::IrLoader*>(builder)->SetModuleHeader(
+      magic, version, generator, id_bound, reserved);
+  return SPV_SUCCESS;
+};
+
+// Processes a parsed instruction for IrLoader. Meets the interface requirement
+// of spvBinaryParse().
+spv_result_t SetSpvInst(void* builder, const spv_parsed_instruction_t* inst) {
+  reinterpret_cast<ir::IrLoader*>(builder)->AddInstruction(inst);
+  return SPV_SUCCESS;
+};
+
+}  // annoymous namespace
+
+std::unique_ptr<ir::Module> BuildModule(spv_target_env env,
+                                        MessageConsumer consumer,
+                                        const std::vector<uint32_t>& binary) {
+  auto context = spvContextCreate(env);
+  SetContextMessageConsumer(context, consumer);
+
+  auto module = MakeUnique<ir::Module>();
+  ir::IrLoader loader(context->consumer, module.get());
+
+  spv_result_t status =
+      spvBinaryParse(context, &loader, binary.data(), binary.size(),
+                     SetSpvHeader, SetSpvInst, nullptr);
+  loader.EndModule();
+
+  spvContextDestroy(context);
+
+  return status == SPV_SUCCESS ? std::move(module) : nullptr;
+}
+
+std::unique_ptr<ir::Module> BuildModule(spv_target_env env,
+                                        MessageConsumer consumer,
+                                        const std::string& text) {
+  SpvTools t(env);
+  t.SetMessageConsumer(consumer);
+  std::vector<uint32_t> binary;
+  if (t.Assemble(text, &binary) != SPV_SUCCESS) return nullptr;
+  return BuildModule(env, consumer, binary);
+}
+
+}  // namespace spvtools
diff --git a/source/opt/build_module.h b/source/opt/build_module.h
new file mode 100644 (file)
index 0000000..65d5107
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (c) 2016 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SPIRV_TOOLS_OPT_BUILD_MODULE_H_
+#define SPIRV_TOOLS_OPT_BUILD_MODULE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "message.h"
+#include "module.h"
+#include "spirv-tools/libspirv.h"
+
+namespace spvtools {
+
+// Builds and returns an ir::Module from the given SPIR-V |binary|. The |binary|
+// will be decoded according to the given target |env|. Returns nullptr if erors
+// occur and sends the errors to |consumer|.
+std::unique_ptr<ir::Module> BuildModule(spv_target_env env,
+                                        MessageConsumer consumer,
+                                        const std::vector<uint32_t>& binary);
+
+// Builds and returns an ir::Module from the given SPIR-V assembly |text|.
+// The |text| will be encoded according to the given target |env|. Returns
+// nullptr if erors occur and sends the errors to |consumer|.
+std::unique_ptr<ir::Module> BuildModule(spv_target_env env,
+                                        MessageConsumer consumer,
+                                        const std::string& text);
+
+}  // namespace spvtools
+
+#endif  // SPIRV_TOOLS_OPT_BUILD_MODULE_H_
index 47be681..2b7850b 100644 (file)
 
 namespace spvtools {
 
-namespace {
-
-// Sets the module header. Meets the interface requirement of spvBinaryParse().
-spv_result_t SetSpvHeader(void* builder, spv_endianness_t, uint32_t magic,
-                          uint32_t version, uint32_t generator,
-                          uint32_t id_bound, uint32_t reserved) {
-  reinterpret_cast<ir::IrLoader*>(builder)
-      ->SetModuleHeader(magic, version, generator, id_bound, reserved);
-  return SPV_SUCCESS;
-};
-
-// Processes a parsed instruction. Meets the interface requirement of
-// spvBinaryParse().
-spv_result_t SetSpvInst(void* builder, const spv_parsed_instruction_t* inst) {
-  reinterpret_cast<ir::IrLoader*>(builder)->AddInstruction(inst);
-  return SPV_SUCCESS;
-};
-
-}  // annoymous namespace
-
 void SpvTools::SetMessageConsumer(MessageConsumer consumer) {
   SetContextMessageConsumer(context_, std::move(consumer));
 }
@@ -78,29 +58,4 @@ spv_result_t SpvTools::Disassemble(const std::vector<uint32_t>& binary,
   return status;
 }
 
-std::unique_ptr<ir::Module> SpvTools::BuildModule(
-    const std::vector<uint32_t>& binary) {
-  spv_diagnostic diagnostic = nullptr;
-
-  auto module = MakeUnique<ir::Module>();
-  ir::IrLoader loader(context_->consumer, module.get());
-
-  spv_result_t status =
-      spvBinaryParse(context_, &loader, binary.data(), binary.size(),
-                     SetSpvHeader, SetSpvInst, &diagnostic);
-
-  spvDiagnosticDestroy(diagnostic);
-
-  loader.EndModule();
-
-  if (status == SPV_SUCCESS) return module;
-  return nullptr;
-}
-
-std::unique_ptr<ir::Module> SpvTools::BuildModule(const std::string& text) {
-  std::vector<uint32_t> binary;
-  if (Assemble(text, &binary) != SPV_SUCCESS) return nullptr;
-  return BuildModule(binary);
-}
-
 }  // namespace spvtools
index e645fcc..fed408a 100644 (file)
 #ifndef SPIRV_TOOLS_LIBSPIRV_HPP_
 #define SPIRV_TOOLS_LIBSPIRV_HPP_
 
-#include <memory>
 #include <string>
 #include <vector>
 
 #include "message.h"
-#include "module.h"
 #include "spirv-tools/libspirv.h"
 
 namespace spvtools {
@@ -53,12 +51,6 @@ class SpvTools {
       uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
                          SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
 
-  // Builds and returns a Module from the given SPIR-V |binary|.
-  std::unique_ptr<ir::Module> BuildModule(const std::vector<uint32_t>& binary);
-
-  // Builds and returns a Module from the given SPIR-V assembly |text|.
-  std::unique_ptr<ir::Module> BuildModule(const std::string& text);
-
  private:
   // Context for the current invocation. Thread-safety of this class depends on
   // the constness of this field.
index 9fc796b..104958d 100644 (file)
@@ -15,6 +15,7 @@
 #include <gtest/gtest.h>
 
 #include "opt/libspirv.hpp"
+#include "spirv/1.1/spirv.h"
 
 namespace {
 
index 436ed42..df41ad5 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <gtest/gtest.h>
 
+#include "opt/build_module.h"
 #include "opt/libspirv.hpp"
 #include "opt/make_unique.h"
 #include "opt/pass_manager.h"
@@ -49,7 +50,8 @@ class PassTest : public TestT {
   // and the boolean value returned from pass Process() function.
   std::tuple<std::string, bool> OptimizeAndDisassemble(
       opt::Pass* pass, const std::string& original, bool skip_nop) {
-    std::unique_ptr<ir::Module> module = tools_.BuildModule(original);
+    std::unique_ptr<ir::Module> module =
+        BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer_, original);
     EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
                                << original << std::endl;
     if (!module) {
@@ -110,7 +112,8 @@ class PassTest : public TestT {
   void RunAndCheck(const std::string& original, const std::string& expected) {
     assert(manager_->NumPasses());
 
-    std::unique_ptr<ir::Module> module = tools_.BuildModule(original);
+    std::unique_ptr<ir::Module> module =
+        BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, original);
     ASSERT_NE(nullptr, module);
 
     manager_->Run(module.get());
index 412bf64..9d9089c 100644 (file)
@@ -18,6 +18,7 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "opt/build_module.h"
 #include "opt/def_use_manager.h"
 #include "opt/libspirv.hpp"
 #include "pass_utils.h"
@@ -128,7 +129,7 @@ TEST_P(ParseDefUseTest, Case) {
   // Build module.
   const std::vector<const char*> text = {tc.text};
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(JoinAllInsts(text));
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, JoinAllInsts(text));
   ASSERT_NE(nullptr, module);
 
   // Analyze def and use.
@@ -509,7 +510,7 @@ TEST_P(ReplaceUseTest, Case) {
   // Build module.
   const std::vector<const char*> text = {tc.before};
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(JoinAllInsts(text));
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, JoinAllInsts(text));
   ASSERT_NE(nullptr, module);
 
   // Analyze def and use.
@@ -811,7 +812,7 @@ TEST_P(KillDefTest, Case) {
   // Build module.
   const std::vector<const char*> text = {tc.before};
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(JoinAllInsts(text));
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, JoinAllInsts(text));
   ASSERT_NE(nullptr, module);
 
   // Analyze def and use.
@@ -1061,7 +1062,7 @@ TEST(DefUseTest, OpSwitch) {
       "      OpFunctionEnd";
 
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(original_text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, original_text);
   ASSERT_NE(nullptr, module);
 
   // Analyze def and use.
@@ -1184,7 +1185,7 @@ TEST_P(AnalyzeInstDefUseTest, Case) {
 
   // Build module.
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(tc.module_text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, tc.module_text);
   ASSERT_NE(nullptr, module);
 
   // Analyze the instructions.
@@ -1307,7 +1308,7 @@ TEST_P(KillInstTest, Case) {
 
   // Build module.
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(tc.before);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, tc.before);
   ASSERT_NE(nullptr, module);
 
   // KillInst
@@ -1415,7 +1416,7 @@ TEST_P(GetAnnotationsTest, Case) {
 
   // Build module.
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(tc.code);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, tc.code);
   ASSERT_NE(nullptr, module);
 
   // Get annotations
index 03c4415..27860c7 100644 (file)
@@ -15,6 +15,7 @@
 #include <gtest/gtest.h>
 #include <algorithm>
 
+#include "opt/build_module.h"
 #include "opt/libspirv.hpp"
 
 namespace {
@@ -23,7 +24,8 @@ using namespace spvtools;
 
 void DoRoundTripCheck(const std::string& text) {
   SpvTools t(SPV_ENV_UNIVERSAL_1_1);
-  std::unique_ptr<ir::Module> module = t.BuildModule(text);
+  std::unique_ptr<ir::Module> module =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   ASSERT_NE(nullptr, module) << "Failed to assemble\n" << text;
 
   std::vector<uint32_t> binary;
@@ -209,7 +211,8 @@ TEST(IrBuilder, OpUndefOutsideFunction) {
   // clang-format on
 
   SpvTools t(SPV_ENV_UNIVERSAL_1_1);
-  std::unique_ptr<ir::Module> module = t.BuildModule(text);
+  std::unique_ptr<ir::Module> module =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   ASSERT_NE(nullptr, module);
 
   const auto opundef_count = std::count_if(
index 0056c96..e76817b 100644 (file)
@@ -17,6 +17,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
+#include "opt/build_module.h"
 #include "opt/libspirv.hpp"
 #include "opt/module.h"
 
@@ -42,9 +43,9 @@ TEST(ModuleTest, SetIdBound) {
 
 // Returns a module formed by assembling the given text,
 // then loading the result.
-std::unique_ptr<Module> BuildModule(std::string text) {
-  spvtools::SpvTools t(SPV_ENV_UNIVERSAL_1_1);
-  return t.BuildModule(text);
+inline std::unique_ptr<Module> BuildModule(std::string text) {
+  return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, spvtools::IgnoreMessage,
+                               text);
 }
 
 TEST(ModuleTest, ComputeIdBound) {
@@ -69,4 +70,3 @@ TEST(ModuleTest, ComputeIdBound) {
 }
 
 }  // anonymous namespace
-
index 1fb2776..b493d98 100644 (file)
@@ -15,8 +15,8 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
+#include "opt/build_module.h"
 #include "opt/instruction.h"
-#include "opt/libspirv.hpp"
 #include "opt/type_manager.h"
 
 namespace {
@@ -89,7 +89,7 @@ TEST(TypeManager, TypeStrings) {
   };
 
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   opt::analysis::TypeManager manager(IgnoreMessage, *module);
 
   EXPECT_EQ(type_id_strs.size(), manager.NumTypes());
@@ -119,7 +119,7 @@ TEST(Struct, DecorationOnStruct) {
     %struct7 = OpTypeStruct %f32      ; no decoration
   )";
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   opt::analysis::TypeManager manager(IgnoreMessage, *module);
 
   ASSERT_EQ(7u, manager.NumTypes());
@@ -169,7 +169,7 @@ TEST(Struct, DecorationOnMember) {
     %struct10 = OpTypeStruct %u32 %f32 ; no member decoration
   )";
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   opt::analysis::TypeManager manager(IgnoreMessage, *module);
 
   ASSERT_EQ(10u, manager.NumTypes());
@@ -207,7 +207,7 @@ TEST(Types, DecorationEmpty) {
     %struct5  = OpTypeStruct %f32
   )";
   std::unique_ptr<ir::Module> module =
-      SpvTools(SPV_ENV_UNIVERSAL_1_1).BuildModule(text);
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, IgnoreMessage, text);
   opt::analysis::TypeManager manager(IgnoreMessage, *module);
 
   ASSERT_EQ(5u, manager.NumTypes());
index d5784e1..d15b27c 100644 (file)
@@ -17,8 +17,8 @@
 #include <vector>
 
 #include "message.h"
+#include "source/opt/build_module.h"
 #include "source/opt/ir_loader.h"
-#include "source/opt/libspirv.hpp"
 #include "source/opt/pass_manager.h"
 #include "tools/io.h"
 
@@ -139,7 +139,8 @@ int main(int argc, char** argv) {
   spvDiagnosticDestroy(diagnostic);
   spvContextDestroy(context);
 
-  std::unique_ptr<ir::Module> module = SpvTools(target_env).BuildModule(source);
+  std::unique_ptr<ir::Module> module =
+      BuildModule(target_env, pass_manager.consumer(), source);
   pass_manager.Run(module.get());
 
   std::vector<uint32_t> target;