diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 8 | ||||
-rw-r--r-- | src/pass.h | 46 | ||||
-rw-r--r-- | src/passes/LowerIfElse.cpp | 4 | ||||
-rw-r--r-- | src/passes/LowerInt64.cpp | 43 | ||||
-rw-r--r-- | src/passes/MergeBlocks.cpp | 4 | ||||
-rw-r--r-- | src/passes/RemoveImports.cpp | 6 | ||||
-rw-r--r-- | src/passes/RemoveUnusedBrs.cpp | 6 | ||||
-rw-r--r-- | src/passes/RemoveUnusedNames.cpp | 8 | ||||
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 4 | ||||
-rw-r--r-- | src/s2wasm.h | 4 | ||||
-rw-r--r-- | src/wasm-binary.h | 2 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 40 | ||||
-rw-r--r-- | src/wasm-validator.h | 24 | ||||
-rw-r--r-- | src/wasm.h | 410 | ||||
-rw-r--r-- | src/wasm2asm.h | 72 |
15 files changed, 344 insertions, 337 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 75862abc8..7fa252c8c 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1489,8 +1489,8 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { void Asm2WasmBuilder::optimize() { // Optimization passes. Note: no effort is made to free nodes that are no longer held on to. - struct BlockBreakOptimizer : public WasmWalker { - void visitBlock(Block *curr) override { + struct BlockBreakOptimizer : public WasmWalker<BlockBreakOptimizer> { + void visitBlock(Block *curr) { // if the block ends in a break on this very block, then just put the value there Break *last = curr->list[curr->list.size()-1]->dyn_cast<Break>(); if (last && last->value && last->name == curr->name) { @@ -1504,13 +1504,13 @@ void Asm2WasmBuilder::optimize() { } // we might be broken to, but maybe there isn't a break (and we may have removed it, leading to this) - struct BreakSeeker : public WasmWalker { + struct BreakSeeker : public WasmWalker<BreakSeeker> { IString target; // look for this one size_t found; BreakSeeker(IString target) : target(target), found(false) {} - void visitBreak(Break *curr) override { + void visitBreak(Break *curr) { if (curr->name == target) found++; } }; diff --git a/src/pass.h b/src/pass.h index d3f1d9edb..f8b56aff6 100644 --- a/src/pass.h +++ b/src/pass.h @@ -88,14 +88,28 @@ struct PassRunner { // // Core pass class // -class Pass : public WasmWalker { - public: - // Override this to perform preparation work before the pass runs +class Pass { +public: + virtual ~Pass() {}; + // Override this to perform preparation work before the pass runs. virtual void prepare(PassRunner* runner, Module* module) {} + virtual void run(PassRunner* runner, Module* module) = 0; +protected: + Pass() {} + Pass(Pass &) {} + Pass &operator=(const Pass&) = delete; +}; - void run(PassRunner* runner, Module* module) { +// +// Core pass class that uses AST walking. This class can be parameterized by +// different types of AST walkers. +// +template <typename WalkerType> +class WalkerPass : public Pass, public WalkerType { +public: + void run(PassRunner* runner, Module* module) override { prepare(runner, module); - startWalk(module); + WalkerType::startWalk(module); } }; @@ -104,22 +118,22 @@ class Pass : public WasmWalker { // e.g. through PassRunner::getLast // Handles names in a module, in particular adding names without duplicates -class NameManager : public Pass { +class NameManager : public WalkerPass<WasmWalker<NameManager>> { public: Name getUnique(std::string prefix); // TODO: getUniqueInFunction // visitors - void visitBlock(Block* curr) override; - void visitLoop(Loop* curr) override; - void visitBreak(Break* curr) override; - void visitSwitch(Switch* curr) override; - void visitCall(Call* curr) override; - void visitCallImport(CallImport* curr) override; - void visitFunctionType(FunctionType* curr) override; - void visitFunction(Function* curr) override; - void visitImport(Import* curr) override; - void visitExport(Export* curr) override; + void visitBlock(Block* curr); + void visitLoop(Loop* curr); + void visitBreak(Break* curr); + void visitSwitch(Switch* curr); + void visitCall(Call* curr); + void visitCallImport(CallImport* curr); + void visitFunctionType(FunctionType* curr); + void visitFunction(Function* curr); + void visitImport(Import* curr); + void visitExport(Export* curr); private: std::set<Name> names; diff --git a/src/passes/LowerIfElse.cpp b/src/passes/LowerIfElse.cpp index 711f5469c..dd7fbf998 100644 --- a/src/passes/LowerIfElse.cpp +++ b/src/passes/LowerIfElse.cpp @@ -32,7 +32,7 @@ namespace wasm { -struct LowerIfElse : public Pass { +struct LowerIfElse : public WalkerPass<WasmWalker<LowerIfElse, void>> { MixedArena* allocator; std::unique_ptr<NameManager> namer; @@ -42,7 +42,7 @@ struct LowerIfElse : public Pass { namer->run(runner, module); } - void visitIf(If *curr) override { + void visitIf(If *curr) { if (curr->ifFalse) { auto block = allocator->alloc<Block>(); auto name = namer->getUnique("L"); // TODO: getUniqueInFunction diff --git a/src/passes/LowerInt64.cpp b/src/passes/LowerInt64.cpp index ae3f773bd..58e56cba6 100644 --- a/src/passes/LowerInt64.cpp +++ b/src/passes/LowerInt64.cpp @@ -63,16 +63,16 @@ struct LowerInt64 : public Pass { } } - void visitCall(Call *curr) override { + void visitCall(Call *curr) { fixCall(curr); } - void visitCallImport(CallImport *curr) override { + void visitCallImport(CallImport *curr) { fixCall(curr); } - void visitCallIndirect(CallIndirect *curr) override { + void visitCallIndirect(CallIndirect *curr) { fixCall(curr); } - void visitGetLocal(GetLocal *curr) override { + void visitGetLocal(GetLocal *curr) { if (curr->type == i64) { if (locals.count(curr->name) == 0) { Name highName = namer->getUnique("high"); @@ -85,7 +85,7 @@ struct LowerInt64 : public Pass { fixes[curr] = high; } } - void visitSetLocal(SetLocal *curr) override { + void visitSetLocal(SetLocal *curr) { if (curr->type == i64) { Name highName; if (locals.count(curr->name) == 0) { @@ -142,7 +142,7 @@ struct LowerInt64 : public Pass { return ret; } - void visitLoad(Load *curr) override { + void visitLoad(Load *curr) { if (curr->type == i64) { Name local; auto ret = setToLocalForBlock(curr->ptr, local); @@ -158,7 +158,7 @@ struct LowerInt64 : public Pass { replaceCurrent(ret); } } - void visitStore(Store *curr) override { + void visitStore(Store *curr) { if (curr->type == i64) { Name localPtr, localValue; auto ret = setToLocalForBlock(curr->ptr, localPtr); @@ -178,28 +178,7 @@ struct LowerInt64 : public Pass { replaceCurrent(ret); } } - void visitConst(Const *curr) override { - } - void visitUnary(Unary *curr) override { - } - void visitBinary(Binary *curr) override { - } - void visitSelect(Select *curr) override { - } - void visitHost(Host *curr) override { - } - void visitNop(Nop *curr) override { - } - void visitUnreachable(Unreachable *curr) override { - } - - void visitFunctionType(FunctionType *curr) override { - } - void visitImport(Import *curr) override { - } - void visitExport(Export *curr) override { - } - void visitFunction(Function *curr) override { + void visitFunction(Function *curr) { // TODO: new params for (auto localPair : locals) { // TODO: ignore params curr->locals.emplace_back(localPair.second, i32); @@ -207,12 +186,6 @@ struct LowerInt64 : public Pass { fixes.clear(); locals.clear(); } - void visitTable(Table *curr) override { - } - void visitMemory(Memory *curr) override { - } - void visitModule(Module *curr) override { - } }; static RegisterPass<LowerInt64> registerPass("lower-i64", "lowers i64 into pairs of i32s"); diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp index 3d7afc4cb..c85f3d600 100644 --- a/src/passes/MergeBlocks.cpp +++ b/src/passes/MergeBlocks.cpp @@ -23,8 +23,8 @@ namespace wasm { -struct MergeBlocks : public Pass { - void visitBlock(Block *curr) override { +struct MergeBlocks : public WalkerPass<WasmWalker<MergeBlocks>> { + void visitBlock(Block *curr) { bool more = true; while (more) { more = false; diff --git a/src/passes/RemoveImports.cpp b/src/passes/RemoveImports.cpp index 0c4924a45..cd741180f 100644 --- a/src/passes/RemoveImports.cpp +++ b/src/passes/RemoveImports.cpp @@ -27,7 +27,7 @@ namespace wasm { -struct RemoveImports : public Pass { +struct RemoveImports : public WalkerPass<WasmWalker<RemoveImports>> { MixedArena* allocator; std::map<Name, Import*> importsMap; @@ -36,7 +36,7 @@ struct RemoveImports : public Pass { importsMap = module->importsMap; } - void visitCallImport(CallImport *curr) override { + void visitCallImport(CallImport *curr) { WasmType type = importsMap[curr->target]->type->result; if (type == none) { replaceCurrent(allocator->alloc<Nop>()); @@ -47,7 +47,7 @@ struct RemoveImports : public Pass { } } - void visitModule(Module *curr) override { + void visitModule(Module *curr) { curr->importsMap.clear(); curr->imports.clear(); } diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 395b0f1ba..245642055 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -23,11 +23,11 @@ namespace wasm { -struct RemoveUnusedBrs : public Pass { +struct RemoveUnusedBrs : public WalkerPass<WasmWalker<RemoveUnusedBrs>> { // preparation: try to unify branches, as the fewer there are, the higher a chance we can remove them // specifically for if-else, turn an if-else with branches to the same target at the end of each // child, and with a value, to a branch to that target containing the if-else - void visitIf(If* curr) override { + void visitIf(If* curr) { if (!curr->ifFalse) return; if (curr->type != none) return; // already has a returned value // an if_else that indirectly returns a value by breaking to the same target can potentially remove both breaks, and break outside once @@ -63,7 +63,7 @@ struct RemoveUnusedBrs : public Pass { } // main portion - void visitBlock(Block *curr) override { + void visitBlock(Block *curr) { if (curr->name.isNull()) return; if (curr->list.size() == 0) return; // preparation - remove all code after a break, since it can't execute, and it might confuse us (we look at the last) diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp index 62de48567..6929aa671 100644 --- a/src/passes/RemoveUnusedNames.cpp +++ b/src/passes/RemoveUnusedNames.cpp @@ -23,22 +23,22 @@ namespace wasm { -struct RemoveUnusedNames : public Pass { +struct RemoveUnusedNames : public WalkerPass<WasmWalker<RemoveUnusedNames>> { // We maintain a list of branches that we saw in children, then when we reach // a parent block, we know if it was branched to std::set<Name> branchesSeen; - void visitBreak(Break *curr) override { + void visitBreak(Break *curr) { branchesSeen.insert(curr->name); } - void visitBlock(Block *curr) override { + void visitBlock(Block *curr) { if (curr->name.is() && branchesSeen.count(curr->name) == 0) { curr->name = Name(); } } - void visitFunction(Function *curr) override { + void visitFunction(Function *curr) { branchesSeen.clear(); } }; diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index b1adf5c26..cbfc0dd66 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -23,8 +23,8 @@ namespace wasm { -struct SimplifyLocals : public Pass { - void visitBlock(Block *curr) override { +struct SimplifyLocals : public WalkerPass<WasmWalker<SimplifyLocals>> { + void visitBlock(Block *curr) { // look for pairs of setlocal-getlocal, which can be just a setlocal (since it returns a value) if (curr->list.size() == 0) return; for (size_t i = 0; i < curr->list.size() - 1; i++) { diff --git a/src/s2wasm.h b/src/s2wasm.h index 2f9b4c8d8..46cf972c8 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -1102,7 +1102,7 @@ public: o << ";; METADATA: { "; // find asmConst calls, and emit their metadata - struct AsmConstWalker : public WasmWalker { + struct AsmConstWalker : public WasmWalker<AsmConstWalker> { S2WasmBuilder* parent; std::map<std::string, std::set<std::string>> sigsForCode; @@ -1111,7 +1111,7 @@ public: AsmConstWalker(S2WasmBuilder* parent) : parent(parent) {} - void visitCallImport(CallImport* curr) override { + void visitCallImport(CallImport* curr) { if (curr->target == EMSCRIPTEN_ASM_CONST) { auto arg = curr->operands[0]->cast<Const>(); size_t segmentIndex = parent->addressSegments[arg->value.geti32()]; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index cebfa11ae..533a24fe3 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -341,7 +341,7 @@ int8_t binaryWasmType(WasmType type) { } } -class WasmBinaryWriter : public WasmVisitor<void> { +class WasmBinaryWriter : public WasmVisitor<WasmBinaryWriter, void> { Module* wasm; BufferWithRandomAccess& o; bool debug; diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 5dbd09ef1..bcd8dee28 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -173,14 +173,14 @@ private: #endif // Execute a statement - class ExpressionRunner : public WasmVisitor<Flow> { + class ExpressionRunner : public WasmVisitor<ExpressionRunner, Flow> { ModuleInstance& instance; FunctionScope& scope; public: ExpressionRunner(ModuleInstance& instance, FunctionScope& scope) : instance(instance), scope(scope) {} - Flow visitBlock(Block *curr) override { + Flow visitBlock(Block *curr) { NOTE_ENTER("Block"); Flow flow; for (auto expression : curr->list) { @@ -192,7 +192,7 @@ private: } return flow; } - Flow visitIf(If *curr) override { + Flow visitIf(If *curr) { NOTE_ENTER("If"); Flow flow = visit(curr->condition); if (flow.breaking()) return flow; @@ -205,7 +205,7 @@ private: if (curr->ifFalse) return visit(curr->ifFalse); return Flow(); } - Flow visitLoop(Loop *curr) override { + Flow visitLoop(Loop *curr) { NOTE_ENTER("Loop"); while (1) { Flow flow = visit(curr->body); @@ -216,7 +216,7 @@ private: return flow; // loop does not loop automatically, only continue achieves that } } - Flow visitBreak(Break *curr) override { + Flow visitBreak(Break *curr) { NOTE_ENTER("Break"); bool condition = true; if (curr->condition) { @@ -232,7 +232,7 @@ private: } return condition ? flow : Flow(); } - Flow visitSwitch(Switch *curr) override { + Flow visitSwitch(Switch *curr) { NOTE_ENTER("Switch"); Flow flow = visit(curr->value); if (flow.breaking()) { @@ -281,7 +281,7 @@ private: return Flow(); } - Flow visitCall(Call *curr) override { + Flow visitCall(Call *curr) { NOTE_ENTER("Call"); NOTE_NAME(curr->target); LiteralList arguments; @@ -293,14 +293,14 @@ private: #endif return ret; } - Flow visitCallImport(CallImport *curr) override { + Flow visitCallImport(CallImport *curr) { NOTE_ENTER("CallImport"); LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) return flow; return instance.externalInterface->callImport(instance.wasm.importsMap[curr->target], arguments); } - Flow visitCallIndirect(CallIndirect *curr) override { + Flow visitCallIndirect(CallIndirect *curr) { NOTE_ENTER("CallIndirect"); Flow target = visit(curr->target); if (target.breaking()) return target; @@ -315,14 +315,14 @@ private: return instance.callFunction(name, arguments); } - Flow visitGetLocal(GetLocal *curr) override { + Flow visitGetLocal(GetLocal *curr) { NOTE_ENTER("GetLocal"); IString name = curr->name; NOTE_NAME(name); NOTE_EVAL1(scope.locals[name]); return scope.locals[name]; } - Flow visitSetLocal(SetLocal *curr) override { + Flow visitSetLocal(SetLocal *curr) { NOTE_ENTER("SetLocal"); IString name = curr->name; Flow flow = visit(curr->value); @@ -333,13 +333,13 @@ private: scope.locals[name] = flow.value; return flow; } - Flow visitLoad(Load *curr) override { + Flow visitLoad(Load *curr) { NOTE_ENTER("Load"); Flow flow = visit(curr->ptr); if (flow.breaking()) return flow; return instance.externalInterface->load(curr, instance.getFinalAddress(curr, flow.value)); } - Flow visitStore(Store *curr) override { + Flow visitStore(Store *curr) { NOTE_ENTER("Store"); Flow ptr = visit(curr->ptr); if (ptr.breaking()) return ptr; @@ -348,12 +348,12 @@ private: instance.externalInterface->store(curr, instance.getFinalAddress(curr, ptr.value), value.value); return value; } - Flow visitConst(Const *curr) override { + Flow visitConst(Const *curr) { NOTE_ENTER("Const"); NOTE_EVAL1(curr->value); return Flow(curr->value); // heh } - Flow visitUnary(Unary *curr) override { + Flow visitUnary(Unary *curr) { NOTE_ENTER("Unary"); Flow flow = visit(curr->value); if (flow.breaking()) return flow; @@ -434,7 +434,7 @@ private: } abort(); } - Flow visitBinary(Binary *curr) override { + Flow visitBinary(Binary *curr) { NOTE_ENTER("Binary"); Flow flow = visit(curr->left); if (flow.breaking()) return flow; @@ -612,7 +612,7 @@ private: } abort(); } - Flow visitSelect(Select *curr) override { + Flow visitSelect(Select *curr) { NOTE_ENTER("Select"); Flow condition = visit(curr->condition); if (condition.breaking()) return condition; @@ -623,7 +623,7 @@ private: if (ifFalse.breaking()) return ifFalse; return condition.value.geti32() ? ifTrue : ifFalse; // ;-) } - Flow visitHost(Host *curr) override { + Flow visitHost(Host *curr) { NOTE_ENTER("Host"); switch (curr->op) { case PageSize: return Literal((int32_t)pageSize); @@ -649,11 +649,11 @@ private: default: abort(); } } - Flow visitNop(Nop *curr) override { + Flow visitNop(Nop *curr) { NOTE_ENTER("Nop"); return Flow(); } - Flow visitUnreachable(Unreachable *curr) override { + Flow visitUnreachable(Unreachable *curr) { NOTE_ENTER("Unreachable"); trap("unreachable"); return Flow(); diff --git a/src/wasm-validator.h b/src/wasm-validator.h index f0e73fb85..ba4e5fe08 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -25,7 +25,7 @@ namespace wasm { -struct WasmValidator : public WasmWalker { +struct WasmValidator : public WasmWalker<WasmValidator> { bool valid; public: @@ -37,23 +37,23 @@ public: // visitors - void visitLoop(Loop *curr) override { + void visitLoop(Loop *curr) { if (curr->in.is()) { LoopChildChecker childChecker(curr->in); childChecker.walk(curr->body); shouldBeTrue(childChecker.valid); } } - void visitSetLocal(SetLocal *curr) override { + void visitSetLocal(SetLocal *curr) { shouldBeTrue(curr->type == curr->value->type); } - void visitLoad(Load *curr) override { + void visitLoad(Load *curr) { validateAlignment(curr->align); } - void visitStore(Store *curr) override { + void visitStore(Store *curr) { validateAlignment(curr->align); } - void visitSwitch(Switch *curr) override { + void visitSwitch(Switch *curr) { std::set<Name> inTable; for (auto target : curr->targets) { if (target.is()) { @@ -65,14 +65,14 @@ public: } shouldBeFalse(curr->default_.is() && inTable.find(curr->default_) == inTable.end()); } - void visitUnary(Unary *curr) override { + void visitUnary(Unary *curr) { shouldBeTrue(curr->value->type == curr->type); } - void visitFunction(Function *curr) override { + void visitFunction(Function *curr) { shouldBeTrue(curr->result == curr->body->type); } - void visitMemory(Memory *curr) override { + void visitMemory(Memory *curr) { shouldBeFalse(curr->initial > curr->max); size_t top = 0; for (auto segment : curr->segments) { @@ -81,7 +81,7 @@ public: } shouldBeFalse(top > curr->initial); } - void visitModule(Module *curr) override { + void visitModule(Module *curr) { for (auto& exp : curr->exports) { Name name = exp->name; bool found = false; @@ -98,13 +98,13 @@ public: private: // the "in" label has a none type, since no one can receive its value. make sure no one breaks to it with a value. - struct LoopChildChecker : public WasmWalker { + struct LoopChildChecker : public WasmWalker<LoopChildChecker> { Name in; bool valid = true; LoopChildChecker(Name in) : in(in) {} - void visitBreak(Break *curr) override { + void visitBreak(Break *curr) { if (curr->name == in && curr->value) { valid = false; } diff --git a/src/wasm.h b/src/wasm.h index 9edd7645e..ffca28f9e 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1133,100 +1133,106 @@ class AllocatingModule : public Module { }; // -// Simple WebAssembly AST visiting. Useful for anything that wants to do -// something different for each AST node type, like printing, interpreting, -// etc. +// WebAssembly AST visitor. Useful for anything that wants to do something +// different for each AST node type, like printing, interpreting, etc. +// +// This class is specifically designed as a template to avoid virtual function +// call overhead. To write a visitor, derive from this class as follows: +// +// struct MyVisitor : public WasmVisitor<MyVisitor> { .. } // -template<class ReturnType> +template<typename SubType, typename ReturnType> struct WasmVisitor { virtual ~WasmVisitor() {} // should be pure virtual, but https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51048 // Expression visitors - virtual ReturnType visitBlock(Block *curr) { abort(); } - virtual ReturnType visitIf(If *curr) { abort(); } - virtual ReturnType visitLoop(Loop *curr) { abort(); } - virtual ReturnType visitBreak(Break *curr) { abort(); } - virtual ReturnType visitSwitch(Switch *curr) { abort(); } - virtual ReturnType visitCall(Call *curr) { abort(); } - virtual ReturnType visitCallImport(CallImport *curr) { abort(); } - virtual ReturnType visitCallIndirect(CallIndirect *curr) { abort(); } - virtual ReturnType visitGetLocal(GetLocal *curr) { abort(); } - virtual ReturnType visitSetLocal(SetLocal *curr) { abort(); } - virtual ReturnType visitLoad(Load *curr) { abort(); } - virtual ReturnType visitStore(Store *curr) { abort(); } - virtual ReturnType visitConst(Const *curr) { abort(); } - virtual ReturnType visitUnary(Unary *curr) { abort(); } - virtual ReturnType visitBinary(Binary *curr) { abort(); } - virtual ReturnType visitSelect(Select *curr) { abort(); } - virtual ReturnType visitHost(Host *curr) { abort(); } - virtual ReturnType visitNop(Nop *curr) { abort(); } - virtual ReturnType visitUnreachable(Unreachable *curr) { abort(); } + ReturnType visitBlock(Block *curr) { abort(); } + ReturnType visitIf(If *curr) { abort(); } + ReturnType visitLoop(Loop *curr) { abort(); } + ReturnType visitBreak(Break *curr) { abort(); } + ReturnType visitSwitch(Switch *curr) { abort(); } + ReturnType visitCall(Call *curr) { abort(); } + ReturnType visitCallImport(CallImport *curr) { abort(); } + ReturnType visitCallIndirect(CallIndirect *curr) { abort(); } + ReturnType visitGetLocal(GetLocal *curr) { abort(); } + ReturnType visitSetLocal(SetLocal *curr) { abort(); } + ReturnType visitLoad(Load *curr) { abort(); } + ReturnType visitStore(Store *curr) { abort(); } + ReturnType visitConst(Const *curr) { abort(); } + ReturnType visitUnary(Unary *curr) { abort(); } + ReturnType visitBinary(Binary *curr) { abort(); } + ReturnType visitSelect(Select *curr) { abort(); } + ReturnType visitHost(Host *curr) { abort(); } + ReturnType visitNop(Nop *curr) { abort(); } + ReturnType visitUnreachable(Unreachable *curr) { abort(); } // Module-level visitors - virtual ReturnType visitFunctionType(FunctionType *curr) { abort(); } - virtual ReturnType visitImport(Import *curr) { abort(); } - virtual ReturnType visitExport(Export *curr) { abort(); } - virtual ReturnType visitFunction(Function *curr) { abort(); } - virtual ReturnType visitTable(Table *curr) { abort(); } - virtual ReturnType visitMemory(Memory *curr) { abort(); } - virtual ReturnType visitModule(Module *curr) { abort(); } + ReturnType visitFunctionType(FunctionType *curr) { abort(); } + ReturnType visitImport(Import *curr) { abort(); } + ReturnType visitExport(Export *curr) { abort(); } + ReturnType visitFunction(Function *curr) { abort(); } + ReturnType visitTable(Table *curr) { abort(); } + ReturnType visitMemory(Memory *curr) { abort(); } + ReturnType visitModule(Module *curr) { abort(); } + +#define DELEGATE(CLASS_TO_VISIT) \ + return static_cast<SubType*>(this)-> \ + visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT*>(curr)) ReturnType visit(Expression *curr) { assert(curr); switch (curr->_id) { - case Expression::Id::BlockId: return visitBlock((Block*)curr); - case Expression::Id::IfId: return visitIf((If*)curr); - case Expression::Id::LoopId: return visitLoop((Loop*)curr); - case Expression::Id::BreakId: return visitBreak((Break*)curr); - case Expression::Id::SwitchId: return visitSwitch((Switch*)curr); - case Expression::Id::CallId: return visitCall((Call*)curr); - case Expression::Id::CallImportId: return visitCallImport((CallImport*)curr); - case Expression::Id::CallIndirectId: return visitCallIndirect((CallIndirect*)curr); - case Expression::Id::GetLocalId: return visitGetLocal((GetLocal*)curr); - case Expression::Id::SetLocalId: return visitSetLocal((SetLocal*)curr); - case Expression::Id::LoadId: return visitLoad((Load*)curr); - case Expression::Id::StoreId: return visitStore((Store*)curr); - case Expression::Id::ConstId: return visitConst((Const*)curr); - case Expression::Id::UnaryId: return visitUnary((Unary*)curr); - case Expression::Id::BinaryId: return visitBinary((Binary*)curr); - case Expression::Id::SelectId: return visitSelect((Select*)curr); - case Expression::Id::HostId: return visitHost((Host*)curr); - case Expression::Id::NopId: return visitNop((Nop*)curr); - case Expression::Id::UnreachableId: return visitUnreachable((Unreachable*)curr); - default: { - std::cerr << "visiting unknown expression " << curr->_id << '\n'; - abort(); - } + case Expression::Id::InvalidId: abort(); + case Expression::Id::BlockId: DELEGATE(Block); + case Expression::Id::IfId: DELEGATE(If); + case Expression::Id::LoopId: DELEGATE(Loop); + case Expression::Id::BreakId: DELEGATE(Break); + case Expression::Id::SwitchId: DELEGATE(Switch); + case Expression::Id::CallId: DELEGATE(Call); + case Expression::Id::CallImportId: DELEGATE(CallImport); + case Expression::Id::CallIndirectId: DELEGATE(CallIndirect); + case Expression::Id::GetLocalId: DELEGATE(GetLocal); + case Expression::Id::SetLocalId: DELEGATE(SetLocal); + case Expression::Id::LoadId: DELEGATE(Load); + case Expression::Id::StoreId: DELEGATE(Store); + case Expression::Id::ConstId: DELEGATE(Const); + case Expression::Id::UnaryId: DELEGATE(Unary); + case Expression::Id::BinaryId: DELEGATE(Binary); + case Expression::Id::SelectId: DELEGATE(Select); + case Expression::Id::HostId: DELEGATE(Host); + case Expression::Id::NopId: DELEGATE(Nop); + case Expression::Id::UnreachableId: DELEGATE(Unreachable); + default: WASM_UNREACHABLE(); } } }; std::ostream& Expression::print(std::ostream &o, unsigned indent) { - struct ExpressionPrinter : public WasmVisitor<void> { + struct ExpressionPrinter : public WasmVisitor<ExpressionPrinter, void> { std::ostream &o; unsigned indent; ExpressionPrinter(std::ostream &o, unsigned indent) : o(o), indent(indent) {} - void visitBlock(Block *curr) override { curr->doPrint(o, indent); } - void visitIf(If *curr) override { curr->doPrint(o, indent); } - void visitLoop(Loop *curr) override { curr->doPrint(o, indent); } - void visitBreak(Break *curr) override { curr->doPrint(o, indent); } - void visitSwitch(Switch *curr) override { curr->doPrint(o, indent); } - void visitCall(Call *curr) override { curr->doPrint(o, indent); } - void visitCallImport(CallImport *curr) override { curr->doPrint(o, indent); } - void visitCallIndirect(CallIndirect *curr) override { curr->doPrint(o, indent); } - void visitGetLocal(GetLocal *curr) override { curr->doPrint(o, indent); } - void visitSetLocal(SetLocal *curr) override { curr->doPrint(o, indent); } - void visitLoad(Load *curr) override { curr->doPrint(o, indent); } - void visitStore(Store *curr) override { curr->doPrint(o, indent); } - void visitConst(Const *curr) override { curr->doPrint(o, indent); } - void visitUnary(Unary *curr) override { curr->doPrint(o, indent); } - void visitBinary(Binary *curr) override { curr->doPrint(o, indent); } - void visitSelect(Select *curr) override { curr->doPrint(o, indent); } - void visitHost(Host *curr) override { curr->doPrint(o, indent); } - void visitNop(Nop *curr) override { curr->doPrint(o, indent); } - void visitUnreachable(Unreachable *curr) override { curr->doPrint(o, indent); } + void visitBlock(Block *curr) { curr->doPrint(o, indent); } + void visitIf(If *curr) { curr->doPrint(o, indent); } + void visitLoop(Loop *curr) { curr->doPrint(o, indent); } + void visitBreak(Break *curr) { curr->doPrint(o, indent); } + void visitSwitch(Switch *curr) { curr->doPrint(o, indent); } + void visitCall(Call *curr) { curr->doPrint(o, indent); } + void visitCallImport(CallImport *curr) { curr->doPrint(o, indent); } + void visitCallIndirect(CallIndirect *curr) { curr->doPrint(o, indent); } + void visitGetLocal(GetLocal *curr) { curr->doPrint(o, indent); } + void visitSetLocal(SetLocal *curr) { curr->doPrint(o, indent); } + void visitLoad(Load *curr) { curr->doPrint(o, indent); } + void visitStore(Store *curr) { curr->doPrint(o, indent); } + void visitConst(Const *curr) { curr->doPrint(o, indent); } + void visitUnary(Unary *curr) { curr->doPrint(o, indent); } + void visitBinary(Binary *curr) { curr->doPrint(o, indent); } + void visitSelect(Select *curr) { curr->doPrint(o, indent); } + void visitHost(Host *curr) { curr->doPrint(o, indent); } + void visitNop(Nop *curr) { curr->doPrint(o, indent); } + void visitUnreachable(Unreachable *curr) { curr->doPrint(o, indent); } }; ExpressionPrinter(o, indent).visit(this); @@ -1235,12 +1241,106 @@ std::ostream& Expression::print(std::ostream &o, unsigned indent) { } // +// Base class for all WasmWalkers +// +template<typename SubType, typename ReturnType = void> +struct WasmWalkerBase : public WasmVisitor<SubType, ReturnType> { + virtual void walk(Expression*& curr) { abort(); } + virtual void startWalk(Function *func) { abort(); } + virtual void startWalk(Module *module) { abort(); } +}; + +template<typename ParentType> +struct ChildWalker : public WasmWalkerBase<ChildWalker<ParentType>> { + ParentType& parent; + + ChildWalker(ParentType& parent) : parent(parent) {} + + void visitBlock(Block *curr) { + ExpressionList& list = curr->list; + for (size_t z = 0; z < list.size(); z++) { + parent.walk(list[z]); + } + } + void visitIf(If *curr) { + parent.walk(curr->condition); + parent.walk(curr->ifTrue); + parent.walk(curr->ifFalse); + } + void visitLoop(Loop *curr) { + parent.walk(curr->body); + } + void visitBreak(Break *curr) { + parent.walk(curr->condition); + parent.walk(curr->value); + } + void visitSwitch(Switch *curr) { + parent.walk(curr->value); + for (auto& case_ : curr->cases) { + parent.walk(case_.body); + } + } + void visitCall(Call *curr) { + ExpressionList& list = curr->operands; + for (size_t z = 0; z < list.size(); z++) { + parent.walk(list[z]); + } + } + void visitCallImport(CallImport *curr) { + ExpressionList& list = curr->operands; + for (size_t z = 0; z < list.size(); z++) { + parent.walk(list[z]); + } + } + void visitCallIndirect(CallIndirect *curr) { + parent.walk(curr->target); + ExpressionList& list = curr->operands; + for (size_t z = 0; z < list.size(); z++) { + parent.walk(list[z]); + } + } + void visitGetLocal(GetLocal *curr) {} + void visitSetLocal(SetLocal *curr) { + parent.walk(curr->value); + } + void visitLoad(Load *curr) { + parent.walk(curr->ptr); + } + void visitStore(Store *curr) { + parent.walk(curr->ptr); + parent.walk(curr->value); + } + void visitConst(Const *curr) {} + void visitUnary(Unary *curr) { + parent.walk(curr->value); + } + void visitBinary(Binary *curr) { + parent.walk(curr->left); + parent.walk(curr->right); + } + void visitSelect(Select *curr) { + parent.walk(curr->condition); + parent.walk(curr->ifTrue); + parent.walk(curr->ifFalse); + } + void visitHost(Host *curr) { + ExpressionList& list = curr->operands; + for (size_t z = 0; z < list.size(); z++) { + parent.walk(list[z]); + } + } + void visitNop(Nop *curr) {} + void visitUnreachable(Unreachable *curr) {} +}; + +// // Simple WebAssembly children-first walking (i.e., post-order, if you look // at the children as subtrees of the current node), with the ability to replace // the current expression node. Useful for writing optimization passes. // -struct WasmWalker : public WasmVisitor<void> { +template<typename SubType, typename ReturnType = void> +struct WasmWalker : public WasmWalkerBase<SubType, ReturnType> { Expression* replace; WasmWalker() : replace(nullptr) {} @@ -1251,123 +1351,41 @@ struct WasmWalker : public WasmVisitor<void> { } // By default, do nothing - void visitBlock(Block *curr) override {} - void visitIf(If *curr) override {} - void visitLoop(Loop *curr) override {} - void visitBreak(Break *curr) override {} - void visitSwitch(Switch *curr) override {} - void visitCall(Call *curr) override {} - void visitCallImport(CallImport *curr) override {} - void visitCallIndirect(CallIndirect *curr) override {} - void visitGetLocal(GetLocal *curr) override {} - void visitSetLocal(SetLocal *curr) override {} - void visitLoad(Load *curr) override {} - void visitStore(Store *curr) override {} - void visitConst(Const *curr) override {} - void visitUnary(Unary *curr) override {} - void visitBinary(Binary *curr) override {} - void visitSelect(Select *curr) override {} - void visitHost(Host *curr) override {} - void visitNop(Nop *curr) override {} - void visitUnreachable(Unreachable *curr) override {} - - void visitFunctionType(FunctionType *curr) override {} - void visitImport(Import *curr) override {} - void visitExport(Export *curr) override {} - void visitFunction(Function *curr) override {} - void visitTable(Table *curr) override {} - void visitMemory(Memory *curr) override {} - void visitModule(Module *curr) override {} + ReturnType visitBlock(Block *curr) {} + ReturnType visitIf(If *curr) {} + ReturnType visitLoop(Loop *curr) {} + ReturnType visitBreak(Break *curr) {} + ReturnType visitSwitch(Switch *curr) {} + ReturnType visitCall(Call *curr) {} + ReturnType visitCallImport(CallImport *curr) {} + ReturnType visitCallIndirect(CallIndirect *curr) {} + ReturnType visitGetLocal(GetLocal *curr) {} + ReturnType visitSetLocal(SetLocal *curr) {} + ReturnType visitLoad(Load *curr) {} + ReturnType visitStore(Store *curr) {} + ReturnType visitConst(Const *curr) {} + ReturnType visitUnary(Unary *curr) {} + ReturnType visitBinary(Binary *curr) {} + ReturnType visitSelect(Select *curr) {} + ReturnType visitHost(Host *curr) {} + ReturnType visitNop(Nop *curr) {} + ReturnType visitUnreachable(Unreachable *curr) {} + + ReturnType visitFunctionType(FunctionType *curr) {} + ReturnType visitImport(Import *curr) {} + ReturnType visitExport(Export *curr) {} + ReturnType visitFunction(Function *curr) {} + ReturnType visitTable(Table *curr) {} + ReturnType visitMemory(Memory *curr) {} + ReturnType visitModule(Module *curr) {} // children-first - void walk(Expression*& curr) { + void walk(Expression*& curr) override { if (!curr) return; - struct ChildWalker : public WasmVisitor { - WasmWalker& parent; - - ChildWalker(WasmWalker& parent) : parent(parent) {} - - void visitBlock(Block *curr) override { - ExpressionList& list = curr->list; - for (size_t z = 0; z < list.size(); z++) { - parent.walk(list[z]); - } - } - void visitIf(If *curr) override { - parent.walk(curr->condition); - parent.walk(curr->ifTrue); - parent.walk(curr->ifFalse); - } - void visitLoop(Loop *curr) override { - parent.walk(curr->body); - } - void visitBreak(Break *curr) override { - parent.walk(curr->condition); - parent.walk(curr->value); - } - void visitSwitch(Switch *curr) override { - parent.walk(curr->value); - for (auto& case_ : curr->cases) { - parent.walk(case_.body); - } - } - void visitCall(Call *curr) override { - ExpressionList& list = curr->operands; - for (size_t z = 0; z < list.size(); z++) { - parent.walk(list[z]); - } - } - void visitCallImport(CallImport *curr) override { - ExpressionList& list = curr->operands; - for (size_t z = 0; z < list.size(); z++) { - parent.walk(list[z]); - } - } - void visitCallIndirect(CallIndirect *curr) override { - parent.walk(curr->target); - ExpressionList& list = curr->operands; - for (size_t z = 0; z < list.size(); z++) { - parent.walk(list[z]); - } - } - void visitGetLocal(GetLocal *curr) override {} - void visitSetLocal(SetLocal *curr) override { - parent.walk(curr->value); - } - void visitLoad(Load *curr) override { - parent.walk(curr->ptr); - } - void visitStore(Store *curr) override { - parent.walk(curr->ptr); - parent.walk(curr->value); - } - void visitConst(Const *curr) override {} - void visitUnary(Unary *curr) override { - parent.walk(curr->value); - } - void visitBinary(Binary *curr) override { - parent.walk(curr->left); - parent.walk(curr->right); - } - void visitSelect(Select *curr) override { - parent.walk(curr->condition); - parent.walk(curr->ifTrue); - parent.walk(curr->ifFalse); - } - void visitHost(Host *curr) override { - ExpressionList& list = curr->operands; - for (size_t z = 0; z < list.size(); z++) { - parent.walk(list[z]); - } - } - void visitNop(Nop *curr) override {} - void visitUnreachable(Unreachable *curr) override {} - }; - - ChildWalker(*this).visit(curr); + ChildWalker<WasmWalker<SubType, ReturnType>>(*this).visit(curr); - visit(curr); + this->visit(curr); if (replace) { curr = replace; @@ -1375,33 +1393,35 @@ struct WasmWalker : public WasmVisitor<void> { } } - void startWalk(Function *func) { + void startWalk(Function *func) override { walk(func->body); } - void startWalk(Module *module) { + void startWalk(Module *module) override { + // Dispatch statically through the SubType. + SubType* self = static_cast<SubType*>(this); for (auto curr : module->functionTypes) { - visitFunctionType(curr); + self->visitFunctionType(curr); assert(!replace); } for (auto curr : module->imports) { - visitImport(curr); + self->visitImport(curr); assert(!replace); } for (auto curr : module->exports) { - visitExport(curr); + self->visitExport(curr); assert(!replace); } for (auto curr : module->functions) { startWalk(curr); - visitFunction(curr); + self->visitFunction(curr); assert(!replace); } - visitTable(&module->table); + self->visitTable(&module->table); assert(!replace); - visitMemory(&module->memory); + self->visitMemory(&module->memory); assert(!replace); - visitModule(module); + self->visitModule(module); assert(!replace); } }; diff --git a/src/wasm2asm.h b/src/wasm2asm.h index 1a85bc177..f1a58e170 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -387,29 +387,29 @@ Ref Wasm2AsmBuilder::processFunction(Function* func) { } void Wasm2AsmBuilder::scanFunctionBody(Expression* curr) { - struct ExpressionScanner : public WasmWalker { + struct ExpressionScanner : public WasmWalker<ExpressionScanner> { Wasm2AsmBuilder* parent; ExpressionScanner(Wasm2AsmBuilder* parent) : parent(parent) {} // Visitors - void visitBlock(Block *curr) override { + void visitBlock(Block *curr) { parent->setStatement(curr); } - void visitIf(If *curr) override { + void visitIf(If *curr) { parent->setStatement(curr); } - void visitLoop(Loop *curr) override { + void visitLoop(Loop *curr) { parent->setStatement(curr); } - void visitBreak(Break *curr) override { + void visitBreak(Break *curr) { parent->setStatement(curr); } - void visitSwitch(Switch *curr) override { + void visitSwitch(Switch *curr) { parent->setStatement(curr); } - void visitCall(Call *curr) override { + void visitCall(Call *curr) { for (auto item : curr->operands) { if (parent->isStatement(item)) { parent->setStatement(curr); @@ -417,10 +417,10 @@ void Wasm2AsmBuilder::scanFunctionBody(Expression* curr) { } } } - void visitCallImport(CallImport *curr) override { + void visitCallImport(CallImport *curr) { visitCall(curr); } - void visitCallIndirect(CallIndirect *curr) override { + void visitCallIndirect(CallIndirect *curr) { if (parent->isStatement(curr->target)) { parent->setStatement(curr); return; @@ -432,37 +432,37 @@ void Wasm2AsmBuilder::scanFunctionBody(Expression* curr) { } } } - void visitSetLocal(SetLocal *curr) override { + void visitSetLocal(SetLocal *curr) { if (parent->isStatement(curr->value)) { parent->setStatement(curr); } } - void visitLoad(Load *curr) override { + void visitLoad(Load *curr) { if (parent->isStatement(curr->ptr)) { parent->setStatement(curr); } } - void visitStore(Store *curr) override { + void visitStore(Store *curr) { if (parent->isStatement(curr->ptr) || parent->isStatement(curr->value)) { parent->setStatement(curr); } } - void visitUnary(Unary *curr) override { + void visitUnary(Unary *curr) { if (parent->isStatement(curr->value)) { parent->setStatement(curr); } } - void visitBinary(Binary *curr) override { + void visitBinary(Binary *curr) { if (parent->isStatement(curr->left) || parent->isStatement(curr->right)) { parent->setStatement(curr); } } - void visitSelect(Select *curr) override { + void visitSelect(Select *curr) { if (parent->isStatement(curr->condition) || parent->isStatement(curr->ifTrue) || parent->isStatement(curr->ifFalse)) { parent->setStatement(curr); } } - void visitHost(Host *curr) override { + void visitHost(Host *curr) { for (auto item : curr->operands) { if (parent->isStatement(item)) { parent->setStatement(curr); @@ -475,7 +475,7 @@ void Wasm2AsmBuilder::scanFunctionBody(Expression* curr) { } Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { - struct ExpressionProcessor : public WasmVisitor<Ref> { + struct ExpressionProcessor : public WasmVisitor<ExpressionProcessor, Ref> { Wasm2AsmBuilder* parent; IString result; ExpressionProcessor(Wasm2AsmBuilder* parent) : parent(parent) {} @@ -579,7 +579,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { // Visitors - Ref visitBlock(Block *curr) override { + Ref visitBlock(Block *curr) { breakResults[curr->name] = result; Ref ret = ValueBuilder::makeBlock(); size_t size = curr->list.size(); @@ -595,7 +595,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } return ret; } - Ref visitIf(If *curr) override { + Ref visitIf(If *curr) { IString temp; Ref condition = visitForExpression(curr->condition, i32, temp); Ref ifTrue = ValueBuilder::makeStatement(visitAndAssign(curr->ifTrue, result)); @@ -611,7 +611,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { condition[1]->push_back(ValueBuilder::makeIf(ValueBuilder::makeName(temp), ifTrue, ifFalse)); return condition; } - Ref visitLoop(Loop *curr) override { + Ref visitLoop(Loop *curr) { Name asmLabel = curr->out.is() ? curr->out : curr->in; // label using the outside, normal for breaks. if no outside, then inside if (curr->in.is()) continueLabels[curr->in] = asmLabel; Ref body = visit(curr->body, result); @@ -621,7 +621,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } return ret; } - Ref visitBreak(Break *curr) override { + Ref visitBreak(Break *curr) { if (curr->condition) { // we need an equivalent to an if here, so use that code Break fakeBreak = *curr; @@ -645,7 +645,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { ret[1]->push_back(theBreak); return ret; } - Ref visitSwitch(Switch *curr) override { + Ref visitSwitch(Switch *curr) { Ref ret = ValueBuilder::makeLabel(fromName(curr->name), ValueBuilder::makeBlock()); Ref value; if (isStatement(curr->value)) { @@ -694,7 +694,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { return ret; } - Ref visitCall(Call *curr) override { + Ref visitCall(Call *curr) { Ref theCall = ValueBuilder::makeCall(fromName(curr->target)); if (!isStatement(curr)) { // none of our operands is a statement; go right ahead and create a simple expression @@ -706,10 +706,10 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { // we must statementize them all return makeStatementizedCall(curr->operands, ValueBuilder::makeBlock(), theCall, result, curr->type); } - Ref visitCallImport(CallImport *curr) override { + Ref visitCallImport(CallImport *curr) { return visitCall(curr); } - Ref visitCallIndirect(CallIndirect *curr) override { + Ref visitCallIndirect(CallIndirect *curr) { std::string stable = std::string("FUNCTION_TABLE_") + getSig(curr->fullType); IString table = IString(stable.c_str(), false); auto makeTableCall = [&](Ref target) { @@ -733,10 +733,10 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { Ref theCall = makeTableCall(temp.getAstName()); return makeStatementizedCall(curr->operands, ret, theCall, result, curr->type); } - Ref visitGetLocal(GetLocal *curr) override { + Ref visitGetLocal(GetLocal *curr) { return ValueBuilder::makeName(fromName(curr->name)); } - Ref visitSetLocal(SetLocal *curr) override { + Ref visitSetLocal(SetLocal *curr) { if (!isStatement(curr)) { return ValueBuilder::makeAssign(ValueBuilder::makeName(fromName(curr->name)), visit(curr->value, EXPRESSION_RESULT)); } @@ -746,7 +746,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { ret[1]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeAssign(ValueBuilder::makeName(fromName(curr->name)), temp.getAstName()))); return ret; } - Ref visitLoad(Load *curr) override { + Ref visitLoad(Load *curr) { if (isStatement(curr)) { ScopedTemp temp(i32, parent); GetLocal fakeLocal; @@ -808,7 +808,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } return makeAsmCoercion(ret, wasmToAsmType(curr->type)); } - Ref visitStore(Store *curr) override { + Ref visitStore(Store *curr) { if (isStatement(curr)) { ScopedTemp tempPtr(i32, parent); ScopedTemp tempValue(curr->type, parent); @@ -903,7 +903,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } return ValueBuilder::makeAssign(ret, value); } - Ref visitConst(Const *curr) override { + Ref visitConst(Const *curr) { switch (curr->type) { case i32: return ValueBuilder::makeInt(curr->value.i32); case f32: { @@ -924,7 +924,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { default: abort(); } } - Ref visitUnary(Unary *curr) override { + Ref visitUnary(Unary *curr) { if (isStatement(curr)) { ScopedTemp temp(curr->value->type, parent); GetLocal fakeLocal; @@ -972,7 +972,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { default: abort(); } } - Ref visitBinary(Binary *curr) override { + Ref visitBinary(Binary *curr) { if (isStatement(curr)) { ScopedTemp tempLeft(curr->left->type, parent); GetLocal fakeLocalLeft; @@ -1045,7 +1045,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { } return makeAsmCoercion(ret, wasmToAsmType(curr->type)); } - Ref visitSelect(Select *curr) override { + Ref visitSelect(Select *curr) { if (isStatement(curr)) { ScopedTemp tempCondition(i32, parent); GetLocal fakeCondition; @@ -1085,13 +1085,13 @@ Ref Wasm2AsmBuilder::processFunctionBody(Expression* curr, IString result) { ) ); } - Ref visitHost(Host *curr) override { + Ref visitHost(Host *curr) { abort(); } - Ref visitNop(Nop *curr) override { + Ref visitNop(Nop *curr) { return ValueBuilder::makeToplevel(); } - Ref visitUnreachable(Unreachable *curr) override { + Ref visitUnreachable(Unreachable *curr) { return ValueBuilder::makeCall(ABORT_FUNC); } }; |