Add forwarding so that passes' ctor can have args.
Also removed the default argument value of `skip_nop` for function
`SinglePassRunAndCheck()` and `SinglePassRunAndDisassemble()`. This is
required to support variadic arguments.
diff --git a/source/opt/pass_manager.h b/source/opt/pass_manager.h
index a4ca586..9424370 100644
--- a/source/opt/pass_manager.h
+++ b/source/opt/pass_manager.h
@@ -50,9 +50,11 @@
void AddPass(std::unique_ptr<Pass> pass) {
passes_.push_back(std::move(pass));
}
- template <typename PassT>
- void AddPass() {
- passes_.emplace_back(new PassT);
+ // Uses the argument to construct a pass instance of type PassT, and adds the
+ // pass instance to this pass manger.
+ template <typename PassT, typename... Args>
+ void AddPass(Args&&... args) {
+ passes_.emplace_back(new PassT(std::forward<Args>(args)...));
}
// Returns the number of passes added.
diff --git a/test/opt/assembly_builder.h b/test/opt/assembly_builder.h
old mode 100755
new mode 100644
diff --git a/test/opt/pass_fixture.h b/test/opt/pass_fixture.h
index 848de7d..dd560eb 100644
--- a/test/opt/pass_fixture.h
+++ b/test/opt/pass_fixture.h
@@ -34,9 +34,9 @@
#include <gtest/gtest.h>
#include "opt/libspirv.hpp"
+#include "opt/make_unique.h"
#include "opt/pass_manager.h"
#include "opt/passes.h"
-#include "opt/make_unique.h"
namespace spvtools {
@@ -57,10 +57,10 @@
// disassebles the optimized binary. Returns a tuple of disassembly string
// 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 = false) {
+ opt::Pass* pass, const std::string& original, bool skip_nop) {
std::unique_ptr<ir::Module> module = tools_.BuildModule(original);
- EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" << original
- << std::endl;
+ EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n"
+ << original << std::endl;
if (!module) {
return std::make_tuple(std::string(), false);
}
@@ -71,17 +71,18 @@
module->ToBinary(&binary, skip_nop);
std::string optimized;
EXPECT_EQ(SPV_SUCCESS, tools_.Disassemble(binary, &optimized))
- << "Disassembling failed for shader:\n" << original << std::endl;
+ << "Disassembling failed for shader:\n"
+ << original << std::endl;
return std::make_tuple(optimized, modified);
}
// Runs a single pass of class |PassT| on the binary assembled from the
// |assembly|, disassembles the optimized binary. Returns a tuple of
// disassembly string and the boolean value from the pass Process() function.
- template <typename PassT>
+ template <typename PassT, typename... Args>
std::tuple<std::string, bool> SinglePassRunAndDisassemble(
- const std::string& assembly, bool skip_nop = false) {
- auto pass = MakeUnique<PassT>();
+ const std::string& assembly, bool skip_nop, Args&&... args) {
+ auto pass = MakeUnique<PassT>(std::forward<Args>(args)...);
return OptimizeAndDisassemble(pass.get(), assembly, skip_nop);
}
@@ -89,23 +90,23 @@
// |original| assembly, and checks whether the optimized binary can be
// disassembled to the |expected| assembly. This does *not* involve pass
// manager. Callers are suggested to use SCOPED_TRACE() for better messages.
- template <typename PassT>
+ template <typename PassT, typename... Args>
void SinglePassRunAndCheck(const std::string& original,
- const std::string& expected,
- bool skip_nop = false) {
+ const std::string& expected, bool skip_nop,
+ Args&&... args) {
std::string optimized;
bool modified = false;
- std::tie(optimized, modified) =
- SinglePassRunAndDisassemble<PassT>(original, skip_nop);
+ std::tie(optimized, modified) = SinglePassRunAndDisassemble<PassT>(
+ original, skip_nop, std::forward<Args>(args)...);
// Check whether the pass returns the correct modification indication.
EXPECT_EQ(original != expected, modified);
EXPECT_EQ(expected, optimized);
}
// Adds a pass to be run.
- template <typename PassT>
- void AddPass() {
- manager_->AddPass<PassT>();
+ template <typename PassT, typename... Args>
+ void AddPass(Args&&... args) {
+ manager_->AddPass<PassT>(std::forward<Args>(args)...);
}
// Renews the pass manager, including clearing all previously added passes.
diff --git a/test/opt/test_assembly_builder.cpp b/test/opt/test_assembly_builder.cpp
index 597229e..6da1e8f 100644
--- a/test/opt/test_assembly_builder.cpp
+++ b/test/opt/test_assembly_builder.cpp
@@ -57,7 +57,8 @@
};
SinglePassRunAndCheck<opt::NullPass>(builder.GetCode(),
- JoinAllInsts(expected));
+ JoinAllInsts(expected),
+ /* skip_nop = */ false);
}
TEST_F(AssemblyBuilderTest, ShaderWithConstants) {
@@ -170,7 +171,8 @@
// clang-format on
};
SinglePassRunAndCheck<opt::NullPass>(builder.GetCode(),
- JoinAllInsts(expected));
+ JoinAllInsts(expected),
+ /* skip_nop = */ false);
}
TEST_F(AssemblyBuilderTest, SpecConstants) {
@@ -250,7 +252,8 @@
};
SinglePassRunAndCheck<opt::NullPass>(builder.GetCode(),
- JoinAllInsts(expected));
+ JoinAllInsts(expected),
+ /* skip_nop = */ false);
}
TEST_F(AssemblyBuilderTest, AppendNames) {
@@ -283,7 +286,8 @@
};
SinglePassRunAndCheck<opt::NullPass>(builder.GetCode(),
- JoinAllInsts(expected));
+ JoinAllInsts(expected),
+ /* skip_nop = */ false);
}
} // anonymous namespace
diff --git a/test/opt/test_freeze_spec_const.cpp b/test/opt/test_freeze_spec_const.cpp
index 2be826b..ecb3c62 100644
--- a/test/opt/test_freeze_spec_const.cpp
+++ b/test/opt/test_freeze_spec_const.cpp
@@ -53,7 +53,7 @@
"OpCapability Shader", "OpMemoryModel Logical GLSL450",
test_case.type_decl, test_case.expected_frozen_const};
SinglePassRunAndCheck<opt::FreezeSpecConstantValuePass>(
- JoinAllInsts(text), JoinAllInsts(expected));
+ JoinAllInsts(text), JoinAllInsts(expected), /* skip_nop = */ false);
}
// Test each primary type.
diff --git a/test/opt/test_pass_manager.cpp b/test/opt/test_pass_manager.cpp
index 8b93fc5..51fcd55 100644
--- a/test/opt/test_pass_manager.cpp
+++ b/test/opt/test_pass_manager.cpp
@@ -26,6 +26,8 @@
#include "gmock/gmock.h"
+#include <initializer_list>
+
#include "module_utils.h"
#include "opt/make_unique.h"
#include "pass_fixture.h"
@@ -36,6 +38,17 @@
using spvtest::GetIdBound;
using ::testing::Eq;
+// A null pass whose construtors accept arguments
+class NullPassWithArgs : public opt::NullPass {
+ public:
+ NullPassWithArgs(uint32_t) : NullPass() {}
+ NullPassWithArgs(std::string) : NullPass() {}
+ NullPassWithArgs(const std::vector<int>&) : NullPass() {}
+ NullPassWithArgs(const std::vector<int>&, uint32_t) : NullPass() {}
+
+ const char* name() const override { return "null-with-args"; }
+};
+
TEST(PassManager, Interface) {
opt::PassManager manager;
EXPECT_EQ(0u, manager.NumPasses());
@@ -54,6 +67,19 @@
EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
EXPECT_STREQ("null", manager.GetPass(1)->name());
EXPECT_STREQ("strip-debug", manager.GetPass(2)->name());
+
+ manager.AddPass<NullPassWithArgs>(1u);
+ manager.AddPass<NullPassWithArgs>("null pass args");
+ manager.AddPass<NullPassWithArgs>(std::initializer_list<int>{1, 2});
+ manager.AddPass<NullPassWithArgs>(std::initializer_list<int>{1, 2}, 3);
+ EXPECT_EQ(7u, manager.NumPasses());
+ EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
+ EXPECT_STREQ("null", manager.GetPass(1)->name());
+ EXPECT_STREQ("strip-debug", manager.GetPass(2)->name());
+ EXPECT_STREQ("null-with-args", manager.GetPass(3)->name());
+ EXPECT_STREQ("null-with-args", manager.GetPass(4)->name());
+ EXPECT_STREQ("null-with-args", manager.GetPass(5)->name());
+ EXPECT_STREQ("null-with-args", manager.GetPass(6)->name());
}
// A pass that appends an OpNop instruction to the debug section.
@@ -66,6 +92,24 @@
}
};
+// A pass that appends specified number of OpNop instructions to the debug
+// section.
+class AppendMultipleOpNopPass : public opt::Pass {
+ public:
+ AppendMultipleOpNopPass(uint32_t num_nop) : num_nop_(num_nop) {}
+ const char* name() const override { return "AppendOpNop"; }
+ bool Process(ir::Module* module) override {
+ for (uint32_t i = 0; i < num_nop_; i++) {
+ auto inst = MakeUnique<ir::Instruction>();
+ module->AddDebugInst(std::move(inst));
+ }
+ return true;
+ }
+
+ private:
+ uint32_t num_nop_;
+};
+
// A pass that duplicates the last instruction in the debug section.
class DuplicateInstPass : public opt::Pass {
const char* name() const override { return "DuplicateInst"; }
@@ -94,6 +138,10 @@
AddPass<DuplicateInstPass>();
AddPass<AppendOpNopPass>();
RunAndCheck(text.c_str(), (text + "OpSource ESSL 310\nOpNop\n").c_str());
+
+ RenewPassManger();
+ AddPass<AppendMultipleOpNopPass>(3);
+ RunAndCheck(text.c_str(), (text + "OpNop\nOpNop\nOpNop\n").c_str());
}
// A pass that appends an OpTypeVoid instruction that uses a given id.
diff --git a/test/opt/test_strip_debug_info.cpp b/test/opt/test_strip_debug_info.cpp
index d9b35e1..2e59243 100644
--- a/test/opt/test_strip_debug_info.cpp
+++ b/test/opt/test_strip_debug_info.cpp
@@ -61,7 +61,8 @@
// clang-format on
};
SinglePassRunAndCheck<opt::StripDebugInfoPass>(JoinAllInsts(text),
- JoinNonDebugInsts(text));
+ JoinNonDebugInsts(text),
+ /* skip_nop = */ false);
// Let's add more debug instruction before the "OpString" instruction.
const std::vector<const char*> more_text = {
@@ -79,7 +80,8 @@
};
text.insert(text.begin() + 4, more_text.cbegin(), more_text.cend());
SinglePassRunAndCheck<opt::StripDebugInfoPass>(JoinAllInsts(text),
- JoinNonDebugInsts(text));
+ JoinNonDebugInsts(text),
+ /* skip_nop = */ false);
}
using StripDebugInfoTest = PassTest<::testing::TestWithParam<const char*>>;
@@ -89,7 +91,8 @@
"OpCapability Shader", "OpMemoryModel Logical GLSL450", GetParam(),
};
SinglePassRunAndCheck<opt::StripDebugInfoPass>(JoinAllInsts(text),
- JoinNonDebugInsts(text));
+ JoinNonDebugInsts(text),
+ /* skip_nop = */ false);
}
// Test each possible non-line debug instruction.