diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-04-07 21:28:26 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-04-07 21:28:26 -0700 |
commit | d30b98d47697daa167333db66ac0fe3d8a693eae (patch) | |
tree | 75ad13773b0422d8f42b184ab8544d69384ef7da /src/ast_utils.h | |
parent | c0f0be986d9009a05a3bbaf42c841b863d9b83c1 (diff) | |
parent | 540056ededd811b859e0cf4db9782d8cb7711215 (diff) | |
download | binaryen-d30b98d47697daa167333db66ac0fe3d8a693eae.tar.gz binaryen-d30b98d47697daa167333db66ac0fe3d8a693eae.tar.bz2 binaryen-d30b98d47697daa167333db66ac0fe3d8a693eae.zip |
Merge pull request #319 from WebAssembly/traversal
Refactor traversal into its own header
Diffstat (limited to 'src/ast_utils.h')
-rw-r--r-- | src/ast_utils.h | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/ast_utils.h b/src/ast_utils.h index df2ffe578..5ab427178 100644 --- a/src/ast_utils.h +++ b/src/ast_utils.h @@ -18,6 +18,7 @@ #define wasm_ast_utils_h #include "wasm.h" +#include "wasm-traversal.h" namespace wasm { @@ -38,6 +39,68 @@ struct BreakSeeker : public WasmWalker<BreakSeeker> { } }; +// Look for side effects, including control flow +// TODO: look at individual locals + +struct EffectAnalyzer : public WasmWalker<EffectAnalyzer> { + bool branches = false; + bool calls = false; + bool readsLocal = false; + bool writesLocal = false; + bool readsMemory = false; + bool writesMemory = false; + + bool accessesLocal() { return readsLocal || writesLocal; } + bool accessesMemory() { return calls || readsMemory || writesMemory; } + bool hasSideEffects() { return calls || writesLocal || writesMemory; } + bool hasAnything() { return branches || calls || readsLocal || writesLocal || readsMemory || writesMemory; } + + // checks if these effects would invalidate another set (e.g., if we write, we invalidate someone that reads, they can't be moved past us) + bool invalidates(EffectAnalyzer& other) { + return branches || other.branches + || ((writesMemory || calls) && other.accessesMemory()) || (writesLocal && other.accessesLocal()) + || (accessesMemory() && (other.writesMemory || other.calls)) || (accessesLocal() && other.writesLocal); + } + + // the checks above happen after the node's children were processed, in the order of execution + // we must also check for control flow that happens before the children, i.e., loops + bool checkPre(Expression* curr) { + if (curr->is<Loop>()) { + branches = true; + return true; + } + return false; + } + + bool checkPost(Expression* curr) { + visit(curr); + return hasAnything(); + } + + void visitBlock(Block *curr) { branches = true; } + void visitLoop(Loop *curr) { branches = true; } + void visitIf(If *curr) { branches = true; } + void visitBreak(Break *curr) { branches = true; } + void visitSwitch(Switch *curr) { branches = true; } + void visitCall(Call *curr) { calls = true; } + void visitCallImport(CallImport *curr) { calls = true; } + void visitCallIndirect(CallIndirect *curr) { calls = true; } + void visitGetLocal(GetLocal *curr) { readsLocal = true; } + void visitSetLocal(SetLocal *curr) { writesLocal = true; } + void visitLoad(Load *curr) { readsMemory = true; } + void visitStore(Store *curr) { writesMemory = true; } + void visitReturn(Return *curr) { branches = true; } + void visitHost(Host *curr) { calls = true; } + void visitUnreachable(Unreachable *curr) { branches = true; } +}; + +struct ExpressionManipulator { + // Nop is the smallest node, so we can always nop-ify another node in our arena + static void nop(Expression* target) { + *static_cast<Nop*>(target) = Nop(); + } +}; + } // namespace wasm #endif // wasm_ast_utils_h |