summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h8
-rw-r--r--src/pass.h46
-rw-r--r--src/passes/LowerIfElse.cpp4
-rw-r--r--src/passes/LowerInt64.cpp43
-rw-r--r--src/passes/MergeBlocks.cpp4
-rw-r--r--src/passes/RemoveImports.cpp6
-rw-r--r--src/passes/RemoveUnusedBrs.cpp6
-rw-r--r--src/passes/RemoveUnusedNames.cpp8
-rw-r--r--src/passes/SimplifyLocals.cpp4
-rw-r--r--src/s2wasm.h4
-rw-r--r--src/wasm-binary.h2
-rw-r--r--src/wasm-interpreter.h40
-rw-r--r--src/wasm-validator.h24
-rw-r--r--src/wasm.h410
-rw-r--r--src/wasm2asm.h72
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);
}
};