// OpSpecConstantOp.
class EliminateDeadConstantPass : public Pass {
public:
- explicit EliminateDeadConstantPass(const MessageConsumer& c) : Pass(c) {}
-
const char* name() const override { return "eliminate-dead-const"; }
Status Process(ir::Module*) override;
};
}
} // anonymous namespace
-FoldSpecConstantOpAndCompositePass::FoldSpecConstantOpAndCompositePass(
- const MessageConsumer& c)
- : Pass(c),
- max_id_(0),
+FoldSpecConstantOpAndCompositePass::FoldSpecConstantOpAndCompositePass()
+ : max_id_(0),
module_(nullptr),
def_use_mgr_(nullptr),
type_mgr_(nullptr),
// TODO(qining): Add support for the operations listed above.
class FoldSpecConstantOpAndCompositePass : public Pass {
public:
- explicit FoldSpecConstantOpAndCompositePass(const MessageConsumer& c);
+ FoldSpecConstantOpAndCompositePass();
const char* name() const override { return "fold-spec-const-op-composite"; }
Status Process(ir::Module* module) override {
// other spec constants defined by OpSpecConstantComposite or OpSpecConstantOp.
class FreezeSpecConstantValuePass : public Pass {
public:
- explicit FreezeSpecConstantValuePass(const MessageConsumer& c) : Pass(c) {}
-
const char* name() const override { return "freeze-spec-const"; }
Status Process(ir::Module*) override;
};
// A null pass that does nothing.
class NullPass : public Pass {
public:
- explicit NullPass(const MessageConsumer& c) : Pass(c) {}
-
const char* name() const override { return "null"; }
Status Process(ir::Module*) override { return Status::SuccessWithoutChange; }
};
SuccessWithoutChange = 0x11,
};
- // Constructs a new pass with the given message consumer, which will be
- // invoked every time there is a message to be communicated to the outside.
+ // Constructs a new pass.
//
- // This pass just keeps a reference to the message consumer; so the message
- // consumer should outlive this pass.
- explicit Pass(const MessageConsumer& c) : consumer_(c) {}
+ // The constructed instance will have an empty message consumer, which just
+ // ignores all messages from the library. Use SetMessageConsumer() to supply
+ // one if messages are of concern.
+ Pass() : consumer_(IgnoreMessage) {}
// Returns a descriptive name for this pass.
virtual const char* name() const = 0;
+
+ // Sets the message consumer to the given |consumer|. |consumer| which will be
+ // invoked every time there is a message to be communicated to the outside.
+ void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
// Returns the reference to the message consumer for this pass.
const MessageConsumer& consumer() const { return consumer_; }
virtual Status Process(ir::Module* module) = 0;
private:
- const MessageConsumer& consumer_; // Message consumer.
+ MessageConsumer consumer_; // Message consumer.
};
} // namespace opt
// to run on a module. Passes are executed in the exact order of addition.
class PassManager {
public:
- // Constructs a pass manager with the given message consumer.
- explicit PassManager(MessageConsumer c) : consumer_(std::move(c)) {}
+ // Constructs a pass manager.
+ //
+ // The constructed instance will have an empty message consumer, which just
+ // ignores all messages from the library. Use SetMessageConsumer() to supply
+ // one if messages are of concern.
+ PassManager() : consumer_(IgnoreMessage) {}
+
+ // Sets the message consumer to the given |consumer|.
+ void SetMessageConsumer(MessageConsumer c) { consumer_ = std::move(c); }
// Adds an externally constructed pass.
void AddPass(std::unique_ptr<Pass> pass);
template <typename T, typename... Args>
inline void PassManager::AddPass(Args&&... args) {
- passes_.emplace_back(new T(consumer_, std::forward<Args>(args)...));
+ passes_.emplace_back(new T(std::forward<Args>(args)...));
+ passes_.back()->SetMessageConsumer(consumer_);
}
inline uint32_t PassManager::NumPasses() const {
using SpecIdToInstMap = std::unordered_map<uint32_t, ir::Instruction*>;
// Constructs a pass instance with a map from spec ids to default values.
- SetSpecConstantDefaultValuePass(const MessageConsumer& c,
- const SpecIdToValueStrMap& default_values)
- : Pass(c), spec_id_to_value_(default_values) {}
- SetSpecConstantDefaultValuePass(const MessageConsumer& c,
- SpecIdToValueStrMap&& default_values)
- : Pass(c), spec_id_to_value_(std::move(default_values)) {}
+ explicit SetSpecConstantDefaultValuePass(
+ const SpecIdToValueStrMap& default_values)
+ : spec_id_to_value_(default_values) {}
+ explicit SetSpecConstantDefaultValuePass(SpecIdToValueStrMap&& default_values)
+ : spec_id_to_value_(std::move(default_values)) {}
const char* name() const override { return "set-spec-const-default-value"; }
Status Process(ir::Module*) override;
// Section 3.32.2 of the SPIR-V spec).
class StripDebugInfoPass : public Pass {
public:
- explicit StripDebugInfoPass(const MessageConsumer& c) : Pass(c) {}
-
const char* name() const override { return "strip-debug"; }
Status Process(ir::Module* module) override;
};
// 3) NaN in float point format with different bit patterns are not unified.
class UnifyConstantPass : public Pass {
public:
- explicit UnifyConstantPass(const MessageConsumer& c) : Pass(c) {}
-
const char* name() const override { return "unify-const"; }
Status Process(ir::Module*) override;
};
PassTest()
: consumer_(IgnoreMessage),
tools_(SPV_ENV_UNIVERSAL_1_1),
- manager_(new opt::PassManager(consumer_)) {}
+ manager_(new opt::PassManager()) {}
// Runs the given |pass| on the binary assembled from the |assembly|, and
// disassebles the optimized binary. Returns a tuple of disassembly string
template <typename PassT, typename... Args>
std::tuple<std::string, opt::Pass::Status> SinglePassRunAndDisassemble(
const std::string& assembly, bool skip_nop, Args&&... args) {
- auto pass = MakeUnique<PassT>(consumer_, std::forward<Args>(args)...);
+ auto pass = MakeUnique<PassT>(std::forward<Args>(args)...);
+ pass->SetMessageConsumer(consumer_);
return OptimizeAndDisassemble(pass.get(), assembly, skip_nop);
}
}
// Renews the pass manager, including clearing all previously added passes.
- void RenewPassManger() { manager_.reset(new opt::PassManager(consumer_)); }
+ void RenewPassManger() {
+ manager_.reset(new opt::PassManager());
+ manager_->SetMessageConsumer(consumer_);
+ }
// Runs the passes added thus far using a pass manager on the binary assembled
// from the |original| assembly, and checks whether the optimized binary can
// A pass turning all none debug line instructions into Nop.
class NopifyPass : public opt::Pass {
public:
- explicit NopifyPass(const MessageConsumer& c) : opt::Pass(c) {}
-
const char* name() const override { return "NopifyPass"; }
Status Process(ir::Module* module) override {
bool modified = false;
// A null pass whose construtors accept arguments
class NullPassWithArgs : public opt::NullPass {
public:
- NullPassWithArgs(const MessageConsumer& c, uint32_t) : NullPass(c) {}
- NullPassWithArgs(const MessageConsumer& c, std::string) : NullPass(c) {}
- NullPassWithArgs(const MessageConsumer& c, const std::vector<int>&)
- : NullPass(c) {}
- NullPassWithArgs(const MessageConsumer& c, const std::vector<int>&, uint32_t)
- : NullPass(c) {}
+ NullPassWithArgs(uint32_t) {}
+ NullPassWithArgs(std::string) {}
+ NullPassWithArgs(const std::vector<int>&) {}
+ NullPassWithArgs(const std::vector<int>&, uint32_t) {}
const char* name() const override { return "null-with-args"; }
};
TEST(PassManager, Interface) {
- opt::PassManager manager(IgnoreMessage);
+ opt::PassManager manager;
EXPECT_EQ(0u, manager.NumPasses());
manager.AddPass<opt::StripDebugInfoPass>();
EXPECT_EQ(1u, manager.NumPasses());
EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
- manager.AddPass(MakeUnique<opt::NullPass>(IgnoreMessage));
+ manager.AddPass(MakeUnique<opt::NullPass>());
EXPECT_EQ(2u, manager.NumPasses());
EXPECT_STREQ("strip-debug", manager.GetPass(0)->name());
EXPECT_STREQ("null", manager.GetPass(1)->name());
// A pass that appends an OpNop instruction to the debug section.
class AppendOpNopPass : public opt::Pass {
public:
- explicit AppendOpNopPass(const MessageConsumer& c) : opt::Pass(c) {}
-
const char* name() const override { return "AppendOpNop"; }
Status Process(ir::Module* module) override {
module->AddDebugInst(MakeUnique<ir::Instruction>());
// section.
class AppendMultipleOpNopPass : public opt::Pass {
public:
- AppendMultipleOpNopPass(const MessageConsumer& c, uint32_t num_nop)
- : opt::Pass(c), num_nop_(num_nop) {}
+ explicit AppendMultipleOpNopPass(uint32_t num_nop) : num_nop_(num_nop) {}
const char* name() const override { return "AppendOpNop"; }
Status Process(ir::Module* module) override {
// A pass that duplicates the last instruction in the debug section.
class DuplicateInstPass : public opt::Pass {
public:
- explicit DuplicateInstPass(const MessageConsumer& c) : opt::Pass(c) {}
-
const char* name() const override { return "DuplicateInst"; }
Status Process(ir::Module* module) override {
auto inst = MakeUnique<ir::Instruction>(*(--module->debug_end()));
// A pass that appends an OpTypeVoid instruction that uses a given id.
class AppendTypeVoidInstPass : public opt::Pass {
public:
- AppendTypeVoidInstPass(const MessageConsumer& c, uint32_t result_id)
- : opt::Pass(c), result_id_(result_id) {}
+ explicit AppendTypeVoidInstPass(uint32_t result_id) : result_id_(result_id) {}
const char* name() const override { return "AppendTypeVoidInstPass"; }
Status Process(ir::Module* module) override {
ir::Module module;
EXPECT_THAT(GetIdBound(module), Eq(0u));
- opt::PassManager manager(IgnoreMessage);
+ opt::PassManager manager;
manager.Run(&module);
manager.AddPass<AppendOpNopPass>();
// With no ID changes, the ID bound does not change.
EXPECT_THAT(GetIdBound(module), Eq(0u));
// Now we force an Id of 100 to be used.
- manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(IgnoreMessage, 100));
+ manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(100));
EXPECT_THAT(GetIdBound(module), Eq(0u));
manager.Run(&module);
// The Id has been updated automatically, even though the pass
EXPECT_THAT(GetIdBound(module), Eq(101u));
// Try one more time!
- manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(IgnoreMessage, 200));
+ manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(200));
manager.Run(&module);
EXPECT_THAT(GetIdBound(module), Eq(201u));
// Add another pass, but which uses a lower Id.
- manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(IgnoreMessage, 10));
+ manager.AddPass(MakeUnique<AppendTypeVoidInstPass>(10));
manager.Run(&module);
// The Id stays high.
EXPECT_THAT(GetIdBound(module), Eq(201u));
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_1;
- opt::PassManager pass_manager([](MessageLevel level, const char* source,
- const spv_position_t& position,
- const char* message) {
+ opt::PassManager pass_manager;
+ pass_manager.SetMessageConsumer([](MessageLevel level, const char* source,
+ const spv_position_t& position,
+ const char* message) {
std::cerr << StringifyMessage(level, source, position, message);
});