summaryrefslogtreecommitdiff
path: root/src/ir/ExpressionManipulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/ExpressionManipulator.cpp')
-rw-r--r--src/ir/ExpressionManipulator.cpp375
1 files changed, 80 insertions, 295 deletions
diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp
index 648a872fc..51fc5af27 100644
--- a/src/ir/ExpressionManipulator.cpp
+++ b/src/ir/ExpressionManipulator.cpp
@@ -23,306 +23,91 @@ namespace ExpressionManipulator {
Expression*
flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
- struct Copier : public OverriddenVisitor<Copier, Expression*> {
- Module& wasm;
- CustomCopier custom;
+ // Perform the copy using a stack of tasks (avoiding recusion).
+ struct CopyTask {
+ // The thing to copy.
+ Expression* original;
+ // The location of the pointer to write the copy to.
+ Expression** destPointer;
+ };
+ std::vector<CopyTask> tasks;
+ Expression* ret;
+ tasks.push_back({original, &ret});
+ while (!tasks.empty()) {
+ auto task = tasks.back();
+ tasks.pop_back();
+ // If the custom copier handled this one, we have nothing to do.
+ auto* copy = custom(task.original);
+ if (copy) {
+ *task.destPointer = copy;
+ continue;
+ }
+ // If the original is a null, just copy that. (This can happen for an
+ // optional child.)
+ auto* original = task.original;
+ if (original == nullptr) {
+ *task.destPointer = nullptr;
+ continue;
+ }
+ // Allocate a new copy, and copy the fields.
- Builder builder;
+#define DELEGATE_ID original->_id
- Copier(Module& wasm, CustomCopier custom)
- : wasm(wasm), custom(custom), builder(wasm) {}
+// Allocate a new expression of the right type, and create cast versions of it
+// for later operations.
+#define DELEGATE_START(id) \
+ copy = wasm.allocator.alloc<id>(); \
+ auto* castOriginal = original->cast<id>(); \
+ WASM_UNUSED(castOriginal); \
+ auto* castCopy = copy->cast<id>(); \
+ WASM_UNUSED(castCopy);
- Expression* copy(Expression* curr) {
- if (!curr) {
- return nullptr;
- }
- auto* ret = custom(curr);
- if (ret) {
- return ret;
- }
- return OverriddenVisitor<Copier, Expression*>::visit(curr);
- }
+// Handle each type of field, copying it appropriately.
+#define DELEGATE_FIELD_CHILD(id, name) \
+ tasks.push_back({castOriginal->name, &castCopy->name});
- Expression* visitBlock(Block* curr) {
- ExpressionList list(wasm.allocator);
- for (Index i = 0; i < curr->list.size(); i++) {
- list.push_back(copy(curr->list[i]));
- }
- return builder.makeBlock(curr->name, list, curr->type);
- }
- Expression* visitIf(If* curr) {
- return builder.makeIf(copy(curr->condition),
- copy(curr->ifTrue),
- copy(curr->ifFalse),
- curr->type);
- }
- Expression* visitLoop(Loop* curr) {
- return builder.makeLoop(curr->name, copy(curr->body), curr->type);
- }
- Expression* visitBreak(Break* curr) {
- return builder.makeBreak(
- curr->name, copy(curr->value), copy(curr->condition));
- }
- Expression* visitSwitch(Switch* curr) {
- return builder.makeSwitch(curr->targets,
- curr->default_,
- copy(curr->condition),
- copy(curr->value));
- }
- Expression* visitCall(Call* curr) {
- auto* ret =
- builder.makeCall(curr->target, {}, curr->type, curr->isReturn);
- for (Index i = 0; i < curr->operands.size(); i++) {
- ret->operands.push_back(copy(curr->operands[i]));
- }
- return ret;
- }
- Expression* visitCallIndirect(CallIndirect* curr) {
- std::vector<Expression*> copiedOps;
- for (auto op : curr->operands) {
- copiedOps.push_back(copy(op));
- }
- return builder.makeCallIndirect(
- copy(curr->target), copiedOps, curr->sig, curr->isReturn);
- }
- Expression* visitLocalGet(LocalGet* curr) {
- return builder.makeLocalGet(curr->index, curr->type);
- }
- Expression* visitLocalSet(LocalSet* curr) {
- if (curr->isTee()) {
- return builder.makeLocalTee(curr->index, copy(curr->value), curr->type);
- } else {
- return builder.makeLocalSet(curr->index, copy(curr->value));
- }
- }
- Expression* visitGlobalGet(GlobalGet* curr) {
- return builder.makeGlobalGet(curr->name, curr->type);
- }
- Expression* visitGlobalSet(GlobalSet* curr) {
- return builder.makeGlobalSet(curr->name, copy(curr->value));
- }
- Expression* visitLoad(Load* curr) {
- if (curr->isAtomic) {
- return builder.makeAtomicLoad(
- curr->bytes, curr->offset, copy(curr->ptr), curr->type);
- }
- return builder.makeLoad(curr->bytes,
- LoadUtils::isSignRelevant(curr) ? curr->signed_
- : false,
- curr->offset,
- curr->align,
- copy(curr->ptr),
- curr->type);
- }
- Expression* visitStore(Store* curr) {
- if (curr->isAtomic) {
- return builder.makeAtomicStore(curr->bytes,
- curr->offset,
- copy(curr->ptr),
- copy(curr->value),
- curr->valueType);
- }
- return builder.makeStore(curr->bytes,
- curr->offset,
- curr->align,
- copy(curr->ptr),
- copy(curr->value),
- curr->valueType);
- }
- Expression* visitAtomicRMW(AtomicRMW* curr) {
- return builder.makeAtomicRMW(curr->op,
- curr->bytes,
- curr->offset,
- copy(curr->ptr),
- copy(curr->value),
- curr->type);
- }
- Expression* visitAtomicCmpxchg(AtomicCmpxchg* curr) {
- return builder.makeAtomicCmpxchg(curr->bytes,
- curr->offset,
- copy(curr->ptr),
- copy(curr->expected),
- copy(curr->replacement),
- curr->type);
- }
- Expression* visitAtomicWait(AtomicWait* curr) {
- return builder.makeAtomicWait(copy(curr->ptr),
- copy(curr->expected),
- copy(curr->timeout),
- curr->expectedType,
- curr->offset);
- }
- Expression* visitAtomicNotify(AtomicNotify* curr) {
- return builder.makeAtomicNotify(
- copy(curr->ptr), copy(curr->notifyCount), curr->offset);
- }
- Expression* visitAtomicFence(AtomicFence* curr) {
- return builder.makeAtomicFence();
- }
- Expression* visitSIMDExtract(SIMDExtract* curr) {
- return builder.makeSIMDExtract(curr->op, copy(curr->vec), curr->index);
- }
- Expression* visitSIMDReplace(SIMDReplace* curr) {
- return builder.makeSIMDReplace(
- curr->op, copy(curr->vec), curr->index, copy(curr->value));
- }
- Expression* visitSIMDShuffle(SIMDShuffle* curr) {
- return builder.makeSIMDShuffle(
- copy(curr->left), copy(curr->right), curr->mask);
- }
- Expression* visitSIMDTernary(SIMDTernary* curr) {
- return builder.makeSIMDTernary(
- curr->op, copy(curr->a), copy(curr->b), copy(curr->c));
- }
- Expression* visitSIMDShift(SIMDShift* curr) {
- return builder.makeSIMDShift(
- curr->op, copy(curr->vec), copy(curr->shift));
- }
- Expression* visitSIMDLoad(SIMDLoad* curr) {
- return builder.makeSIMDLoad(
- curr->op, curr->offset, curr->align, copy(curr->ptr));
- }
- Expression* visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
- return builder.makeSIMDLoadStoreLane(curr->op,
- curr->offset,
- curr->align,
- curr->index,
- copy(curr->ptr),
- copy(curr->vec));
- }
- Expression* visitConst(Const* curr) {
- return builder.makeConst(curr->value);
- }
- Expression* visitMemoryInit(MemoryInit* curr) {
- return builder.makeMemoryInit(
- curr->segment, copy(curr->dest), copy(curr->offset), copy(curr->size));
- }
- Expression* visitDataDrop(DataDrop* curr) {
- return builder.makeDataDrop(curr->segment);
- }
- Expression* visitMemoryCopy(MemoryCopy* curr) {
- return builder.makeMemoryCopy(
- copy(curr->dest), copy(curr->source), copy(curr->size));
- }
- Expression* visitMemoryFill(MemoryFill* curr) {
- return builder.makeMemoryFill(
- copy(curr->dest), copy(curr->value), copy(curr->size));
- }
- Expression* visitUnary(Unary* curr) {
- return builder.makeUnary(curr->op, copy(curr->value));
- }
- Expression* visitBinary(Binary* curr) {
- return builder.makeBinary(curr->op, copy(curr->left), copy(curr->right));
- }
- Expression* visitSelect(Select* curr) {
- return builder.makeSelect(copy(curr->condition),
- copy(curr->ifTrue),
- copy(curr->ifFalse),
- curr->type);
- }
- Expression* visitDrop(Drop* curr) {
- return builder.makeDrop(copy(curr->value));
- }
- Expression* visitReturn(Return* curr) {
- return builder.makeReturn(copy(curr->value));
- }
- Expression* visitMemorySize(MemorySize* curr) {
- return builder.makeMemorySize();
- }
- Expression* visitMemoryGrow(MemoryGrow* curr) {
- return builder.makeMemoryGrow(copy(curr->delta));
- }
- Expression* visitRefNull(RefNull* curr) {
- return builder.makeRefNull(curr->type);
- }
- Expression* visitRefIsNull(RefIsNull* curr) {
- return builder.makeRefIsNull(copy(curr->value));
- }
- Expression* visitRefFunc(RefFunc* curr) {
- return builder.makeRefFunc(curr->func);
- }
- Expression* visitRefEq(RefEq* curr) {
- return builder.makeRefEq(copy(curr->left), copy(curr->right));
- }
- Expression* visitTry(Try* curr) {
- return builder.makeTry(
- copy(curr->body), copy(curr->catchBody), curr->type);
- }
- Expression* visitThrow(Throw* curr) {
- std::vector<Expression*> operands;
- for (Index i = 0; i < curr->operands.size(); i++) {
- operands.push_back(copy(curr->operands[i]));
- }
- return builder.makeThrow(curr->event, std::move(operands));
- }
- Expression* visitRethrow(Rethrow* curr) {
- return builder.makeRethrow(copy(curr->exnref));
- }
- Expression* visitBrOnExn(BrOnExn* curr) {
- return builder.makeBrOnExn(
- curr->name, curr->event, copy(curr->exnref), curr->sent);
- }
- Expression* visitNop(Nop* curr) { return builder.makeNop(); }
- Expression* visitUnreachable(Unreachable* curr) {
- return builder.makeUnreachable();
- }
- Expression* visitPop(Pop* curr) { return builder.makePop(curr->type); }
- Expression* visitTupleMake(TupleMake* curr) {
- std::vector<Expression*> operands;
- for (auto* op : curr->operands) {
- operands.push_back(copy(op));
- }
- return builder.makeTupleMake(std::move(operands));
- }
- Expression* visitTupleExtract(TupleExtract* curr) {
- return builder.makeTupleExtract(copy(curr->tuple), curr->index);
- }
- Expression* visitI31New(I31New* curr) {
- return builder.makeI31New(copy(curr->value));
- }
- Expression* visitI31Get(I31Get* curr) {
- return builder.makeI31Get(copy(curr->i31), curr->signed_);
- }
- Expression* visitRefTest(RefTest* curr) {
- WASM_UNREACHABLE("TODO (gc): ref.test");
- }
- Expression* visitRefCast(RefCast* curr) {
- WASM_UNREACHABLE("TODO (gc): ref.cast");
- }
- Expression* visitBrOnCast(BrOnCast* curr) {
- WASM_UNREACHABLE("TODO (gc): br_on_cast");
- }
- Expression* visitRttCanon(RttCanon* curr) {
- WASM_UNREACHABLE("TODO (gc): rtt.canon");
- }
- Expression* visitRttSub(RttSub* curr) {
- WASM_UNREACHABLE("TODO (gc): rtt.sub");
- }
- Expression* visitStructNew(StructNew* curr) {
- WASM_UNREACHABLE("TODO (gc): struct.new");
- }
- Expression* visitStructGet(StructGet* curr) {
- WASM_UNREACHABLE("TODO (gc): struct.get");
- }
- Expression* visitStructSet(StructSet* curr) {
- WASM_UNREACHABLE("TODO (gc): struct.set");
- }
- Expression* visitArrayNew(ArrayNew* curr) {
- WASM_UNREACHABLE("TODO (gc): array.new");
- }
- Expression* visitArrayGet(ArrayGet* curr) {
- WASM_UNREACHABLE("TODO (gc): array.get");
- }
- Expression* visitArraySet(ArraySet* curr) {
- WASM_UNREACHABLE("TODO (gc): array.set");
- }
- Expression* visitArrayLen(ArrayLen* curr) {
- WASM_UNREACHABLE("TODO (gc): array.len");
- }
- };
+#define DELEGATE_FIELD_CHILD_VECTOR(id, name) \
+ castCopy->name.resize(castOriginal->name.size()); \
+ for (Index i = 0; i < castOriginal->name.size(); i++) { \
+ tasks.push_back({castOriginal->name[i], &castCopy->name[i]}); \
+ }
+
+#define COPY_FIELD(name) castCopy->name = castOriginal->name;
+
+#define DELEGATE_FIELD_INT(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_LITERAL(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_NAME(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_SCOPE_NAME(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_SIGNATURE(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_TYPE(id, name) COPY_FIELD(name)
+#define DELEGATE_FIELD_ADDRESS(id, name) COPY_FIELD(name)
- Copier copier(wasm, custom);
- return copier.copy(original);
+#define COPY_FIELD_LIST(name) \
+ for (Index i = 0; i < castOriginal->name.size(); i++) { \
+ castCopy->name[i] = castOriginal->name[i]; \
+ }
+
+#define COPY_VECTOR(name) \
+ castCopy->name.resize(castOriginal->name.size()); \
+ COPY_FIELD_LIST(name)
+
+#define COPY_ARRAY(name) \
+ assert(castCopy->name.size() == castOriginal->name.size()); \
+ COPY_FIELD_LIST(name)
+
+#define DELEGATE_FIELD_SCOPE_NAME_VECTOR(id, name) COPY_VECTOR(name)
+
+#define DELEGATE_FIELD_INT_ARRAY(id, name) COPY_ARRAY(name)
+
+#include "wasm-delegations-fields.h"
+
+ // The type can be simply copied.
+ copy->type = original->type;
+
+ // Write the copy to where it should be referred to.
+ *task.destPointer = copy;
+ }
+ return ret;
}
// Splice an item into the middle of a block's list