16using Passes = std::deque<std::unique_ptr<Pass>>;
26class Stage :
public fe::RuntimeCast<Stage> {
36 virtual std::unique_ptr<Stage>
recreate();
43 world.DLOG(
"apply stage: `{}`", p_def);
45 if (
auto axm = p_def->isa<
Axm>())
46 if (
auto i = stages.find(axm->flags()); i != stages.end()) {
47 auto stage = i->second(
world);
48 if (stage) stage->apply(def->isa<
App>());
51 error(
"stage `{}` not found", axm->sym());
53 error(
"unsupported callee for a stage: `{}`", p_def);
56 template<
class A,
class P>
99 size_t index()
const {
return index_; }
158 virtual void*
alloc() {
return nullptr; }
159 virtual void*
copy(
const void*) {
return nullptr; }
182 bool inspect() const final { fe::unreachable(); }
186 bool empty()
const {
return passes_.empty(); }
187 const auto&
passes()
const {
return passes_; }
197 if (
auto i = registry_.find(key); i != registry_.end())
return i->second;
203 if (
auto pass =
find(std::type_index(
typeid(P))))
return static_cast<P*
>(pass);
207 void add(std::unique_ptr<Pass>&& pass) {
208 fixed_point_ |= pass->fixed_point();
210 auto type_idx = std::type_index(
typeid(*p));
211 if (
auto pass =
find(type_idx))
error(
"already added `{}`", pass);
212 registry_.emplace(type_idx, p);
213 passes_.emplace_back(std::move(pass));
222 State(
const State&) =
delete;
223 State(State&&) =
delete;
224 State& operator=(State) =
delete;
228 Def* curr_mut =
nullptr;
230 std::stack<Def*> stack;
231 MutMap<undo_t> mut2visit;
238 void pop_states(
undo_t undo);
239 State& curr_state() {
240 assert(!states_.empty());
241 return states_.back();
243 const State& curr_state()
const {
244 assert(!states_.empty());
245 return states_.back();
247 undo_t curr_undo()
const {
return states_.size() - 1; }
252 const Def* rewrite(
const Def*);
254 const Def* map(
const Def* old_def,
const Def* new_def) {
255 curr_state().old2new[old_def] = new_def;
256 curr_state().old2new.emplace(new_def, new_def);
260 std::optional<const Def*> lookup(
const Def* old_def) {
261 for (
auto& state : states_ | std::ranges::views::reverse)
262 if (
auto i = state.old2new.find(old_def); i != state.old2new.end())
return i->second;
269 undo_t analyze(
const Def*);
270 bool analyzed(
const Def* def) {
271 for (
auto& state : states_ | std::ranges::views::reverse)
272 if (state.analyzed.contains(def))
return true;
273 curr_state().analyzed.emplace(def);
279 absl::flat_hash_map<std::type_index, Pass*> registry_;
280 std::deque<State> states_;
281 Def* curr_mut_ =
nullptr;
282 bool fixed_point_ =
false;
285 template<
class P,
class M>
292template<
class P,
class M = Def>
301 if constexpr (std::is_same<M, Def>::value)
308 if constexpr (std::is_same<M, Def>::value)
317template<
class P,
class M = Def>
336 assert(!
states().empty());
341 return std::get<I>(
data());
349 template<
size_t I,
class K>
361 const auto& mut2visit =
Super::man().curr_state().mut2visit;
362 if (
auto i = mut2visit.find(mut); i != mut2visit.end())
return i->second;
368 for (
auto i =
states().size(); i-- != 0;)
377 void*
alloc()
override {
return new typename P::Data(); }
378 void*
copy(
const void* p)
override {
return new typename P::Data(*
static_cast<const typename P::Data*
>(p)); }
379 void dealloc(
void* state)
override {
delete static_cast<typename P::Data*
>(state); }
const Def * uncurry_callee() const
World & world() const noexcept
Some "global" variables needed all over the place.
void dealloc(void *state) override
Destructor.
undo_t undo_visit(Def *mut) const
Retrieves the point to backtrack to just before mut was seen the very first time.
FPPass(World &world, flags_t annex)
auto & data(const K &key)
Use this for your convenience if P::Data is a map.
FPPass(World &world, std::string name)
void * copy(const void *p) override
Copy constructor.
undo_t curr_undo() const
Current undo point.
const auto & states() const
bool fixed_point() const override
std::tuple<> Data
Default.
void * alloc() override
Default constructor.
auto & data(const K &key)
Use this for your convenience if P::Data<I> is a map.
undo_t undo_enter(Def *mut) const
Retrieves the point to backtrack to just before rewriting mut's body.
Facility to log what you are doing.
void log(Level level, Loc loc, const char *fmt, Args &&... args) const
An optimizer that combines several optimizations in an optimal way.
void init(PassMan *) final
Pass * find(std::type_index key)
void apply(Stage &stage) final
Dito, but invoked by Stage::recreate.
bool inspect() const final
Should the PassMan even consider this pass?
void run()
Run all registered passes on the whole World.
void add(std::unique_ptr< Pass > &&pass)
PassMan(World &world, flags_t annex)
const auto & passes() const
All Passes that want to be registered in the PassMan must implement this interface.
virtual void enter()
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
const Proxy * proxy(const Def *type, Defs ops, u32 tag=0)
virtual undo_t analyze(const Proxy *)
const PassMan & man() const
virtual void * alloc()
Default constructor.
virtual const Def * rewrite(const Var *var)
virtual void dealloc(void *)
Destructor.
virtual const Def * rewrite(const Proxy *proxy)
virtual undo_t analyze(const Var *)
Pass(World &world, std::string name)
virtual void init(PassMan *)
virtual undo_t analyze(const Def *)
virtual void prepare()
Invoked once before entering the main rewrite loop.
virtual void * copy(const void *)
Copy constructor.
virtual bool fixed_point() const
Pass(World &world, flags_t annex)
virtual bool inspect() const =0
Should the PassMan even consider this pass?
virtual const Def * rewrite(const Def *def)
const Proxy * isa_proxy(const Def *def, u32 tag=0)
Check whether given def is a Proxy whose Proxy::pass matches this Pass's IPass::index.
const Proxy * as_proxy(const Def *def, u32 tag=0)
RWPass(World &world, std::string name)
bool inspect() const override
Should the PassMan even consider this pass?
RWPass(World &world, flags_t annex)
Common base for Phase and Pass.
virtual std::unique_ptr< Stage > recreate()
Creates a new instance; needed by a fixed-point PhaseMan.
static auto create(const Flags2Stages &stages, const Def *def)
virtual void apply(const App *)
Invoked if your Stage has additional args.
std::string_view name() const
static void hook(Flags2Stages &stages)
virtual void apply(Stage &)
Dito, but invoked by Stage::recreate.
Stage(World &world, std::string name)
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Driver & driver() const
const Proxy * proxy(const Def *type, Defs ops, u32 index, u32 tag)
DefMap< const Def * > Def2Def
Vector< const Def * > DefVec
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
std::deque< std::unique_ptr< Pass > > Passes
void error(Loc loc, const char *f, Args &&... args)
absl::flat_hash_map< flags_t, std::function< std::unique_ptr< Stage >(World &)> > Flags2Stages
Maps an an axiom of a Stage to a function that creates one.
GIDSet< const Def * > DefSet
static constexpr undo_t No_Undo
static consteval flags_t base()