diff options
Diffstat (limited to 'src/ir/localize.h')
-rw-r--r-- | src/ir/localize.h | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/src/ir/localize.h b/src/ir/localize.h index c8e85822a..44ec5af32 100644 --- a/src/ir/localize.h +++ b/src/ir/localize.h @@ -17,7 +17,8 @@ #ifndef wasm_ir_localizer_h #define wasm_ir_localizer_h -#include <wasm-builder.h> +#include "ir/iteration.h" +#include "wasm-builder.h" namespace wasm { @@ -26,7 +27,6 @@ namespace wasm { // // Note that if the local is reused, this assumes it is not modified in between // the set and the get, which the caller must ensure. - struct Localizer { Index index; Expression* expr; @@ -44,6 +44,44 @@ struct Localizer { } }; +// Replaces all children with gets of locals, if they have any effects. After +// this, the original input has only local.gets as inputs, or other things that +// have no interacting effects, and so those children can be reordered. +// The sets of the locals are emitted on a |sets| property on the class. Those +// must be emitted right before the input. +// This stops at the first unreachable child, as there is no code executing +// after that point anyhow. +// TODO: use in more places +struct ChildLocalizer { + std::vector<LocalSet*> sets; + + ChildLocalizer(Expression* input, + Function* func, + Module* wasm, + const PassOptions& options) { + Builder builder(*wasm); + ChildIterator iterator(input); + auto& children = iterator.children; + // The children are in reverse order, so allocate the output first and + // apply items as we go. + auto num = children.size(); + for (Index i = 0; i < num; i++) { + auto** childp = children[num - 1 - i]; + auto* child = *childp; + if (child->type == Type::unreachable) { + break; + } + // If there are effects, use a local for this. + // TODO: Compare interactions between their side effects. + if (EffectAnalyzer(options, *wasm, child).hasAnything()) { + auto local = builder.addVar(func, child->type); + sets.push_back(builder.makeLocalSet(local, child)); + *childp = builder.makeLocalGet(local, child->type); + } + } + } +}; + } // namespace wasm #endif // wasm_ir_localizer_h |