summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/AlignmentLowering.cpp171
-rw-r--r--src/passes/Asyncify.cpp88
-rw-r--r--src/passes/AvoidReinterprets.cpp8
-rw-r--r--src/passes/CodeFolding.cpp8
-rw-r--r--src/passes/ConstHoisting.cpp24
-rw-r--r--src/passes/DeadArgumentElimination.cpp12
-rw-r--r--src/passes/DeadCodeElimination.cpp12
-rw-r--r--src/passes/Flatten.cpp16
-rw-r--r--src/passes/FuncCastEmulation.cpp55
-rw-r--r--src/passes/I64ToI32Lowering.cpp301
-rw-r--r--src/passes/Inlining.cpp12
-rw-r--r--src/passes/InstrumentLocals.cpp44
-rw-r--r--src/passes/InstrumentMemory.cpp20
-rw-r--r--src/passes/LegalizeJSInterface.cpp6
-rw-r--r--src/passes/LogExecution.cpp2
-rw-r--r--src/passes/LoopInvariantCodeMotion.cpp2
-rw-r--r--src/passes/MergeBlocks.cpp10
-rw-r--r--src/passes/OptimizeAddedConstants.cpp6
-rw-r--r--src/passes/OptimizeInstructions.cpp36
-rw-r--r--src/passes/PostAssemblyScript.cpp10
-rw-r--r--src/passes/Precompute.cpp13
-rw-r--r--src/passes/Print.cpp17
-rw-r--r--src/passes/ReReloop.cpp4
-rw-r--r--src/passes/RemoveNonJSOps.cpp16
-rw-r--r--src/passes/RemoveUnusedBrs.cpp47
-rw-r--r--src/passes/SafeHeap.cpp68
-rw-r--r--src/passes/SimplifyLocals.cpp36
-rw-r--r--src/passes/SpillPointers.cpp2
-rw-r--r--src/passes/StackIR.cpp4
-rw-r--r--src/passes/TrapMode.cpp8
-rw-r--r--src/passes/Untee.cpp2
-rw-r--r--src/passes/Vacuum.cpp21
32 files changed, 565 insertions, 516 deletions
diff --git a/src/passes/AlignmentLowering.cpp b/src/passes/AlignmentLowering.cpp
index d659fcb69..18fe46398 100644
--- a/src/passes/AlignmentLowering.cpp
+++ b/src/passes/AlignmentLowering.cpp
@@ -32,26 +32,31 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
return;
}
Builder builder(*getModule());
- if (curr->type == unreachable) {
+ if (curr->type == Type::unreachable) {
replaceCurrent(curr->ptr);
return;
}
- assert(curr->type == i32); // TODO: i64, f32, f64
- auto temp = builder.addVar(getFunction(), i32);
+ assert(curr->type == Type::i32); // TODO: i64, f32, f64
+ auto temp = builder.addVar(getFunction(), Type::i32);
Expression* ret;
if (curr->bytes == 2) {
ret = builder.makeBinary(
OrInt32,
- builder.makeLoad(
- 1, false, curr->offset, 1, builder.makeLocalGet(temp, i32), i32),
- builder.makeBinary(ShlInt32,
- builder.makeLoad(1,
- false,
- curr->offset + 1,
- 1,
- builder.makeLocalGet(temp, i32),
- i32),
- builder.makeConst(Literal(int32_t(8)))));
+ builder.makeLoad(1,
+ false,
+ curr->offset,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeBinary(
+ ShlInt32,
+ builder.makeLoad(1,
+ false,
+ curr->offset + 1,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeConst(Literal(int32_t(8)))));
if (curr->signed_) {
ret = Bits::makeSignExt(ret, 2, *getModule());
}
@@ -61,47 +66,59 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
OrInt32,
builder.makeBinary(
OrInt32,
- builder.makeLoad(
- 1, false, curr->offset, 1, builder.makeLocalGet(temp, i32), i32),
- builder.makeBinary(ShlInt32,
- builder.makeLoad(1,
- false,
- curr->offset + 1,
- 1,
- builder.makeLocalGet(temp, i32),
- i32),
- builder.makeConst(Literal(int32_t(8))))),
+ builder.makeLoad(1,
+ false,
+ curr->offset,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeBinary(
+ ShlInt32,
+ builder.makeLoad(1,
+ false,
+ curr->offset + 1,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeConst(Literal(int32_t(8))))),
builder.makeBinary(
OrInt32,
- builder.makeBinary(ShlInt32,
- builder.makeLoad(1,
- false,
- curr->offset + 2,
- 1,
- builder.makeLocalGet(temp, i32),
- i32),
- builder.makeConst(Literal(int32_t(16)))),
- builder.makeBinary(ShlInt32,
- builder.makeLoad(1,
- false,
- curr->offset + 3,
- 1,
- builder.makeLocalGet(temp, i32),
- i32),
- builder.makeConst(Literal(int32_t(24))))));
+ builder.makeBinary(
+ ShlInt32,
+ builder.makeLoad(1,
+ false,
+ curr->offset + 2,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeConst(Literal(int32_t(16)))),
+ builder.makeBinary(
+ ShlInt32,
+ builder.makeLoad(1,
+ false,
+ curr->offset + 3,
+ 1,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeConst(Literal(int32_t(24))))));
} else if (curr->align == 2) {
ret = builder.makeBinary(
OrInt32,
- builder.makeLoad(
- 2, false, curr->offset, 2, builder.makeLocalGet(temp, i32), i32),
- builder.makeBinary(ShlInt32,
- builder.makeLoad(2,
- false,
- curr->offset + 2,
- 2,
- builder.makeLocalGet(temp, i32),
- i32),
- builder.makeConst(Literal(int32_t(16)))));
+ builder.makeLoad(2,
+ false,
+ curr->offset,
+ 2,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeBinary(
+ ShlInt32,
+ builder.makeLoad(2,
+ false,
+ curr->offset + 2,
+ 2,
+ builder.makeLocalGet(temp, Type::i32),
+ Type::i32),
+ builder.makeConst(Literal(int32_t(16)))));
} else {
WASM_UNREACHABLE("invalid alignment");
}
@@ -117,14 +134,14 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
return;
}
Builder builder(*getModule());
- if (curr->type == unreachable) {
+ if (curr->type == Type::unreachable) {
replaceCurrent(builder.makeBlock(
{builder.makeDrop(curr->ptr), builder.makeDrop(curr->value)}));
return;
}
- assert(curr->value->type == i32); // TODO: i64, f32, f64
- auto tempPtr = builder.addVar(getFunction(), i32);
- auto tempValue = builder.addVar(getFunction(), i32);
+ assert(curr->value->type == Type::i32); // TODO: i64, f32, f64
+ auto tempPtr = builder.addVar(getFunction(), Type::i32);
+ auto tempValue = builder.addVar(getFunction(), Type::i32);
auto* block =
builder.makeBlock({builder.makeLocalSet(tempPtr, curr->ptr),
builder.makeLocalSet(tempValue, curr->value)});
@@ -133,71 +150,71 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> {
builder.makeStore(1,
curr->offset,
1,
- builder.makeLocalGet(tempPtr, i32),
- builder.makeLocalGet(tempValue, i32),
- i32));
+ builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempValue, Type::i32),
+ Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 1,
1,
- builder.makeLocalGet(tempPtr, i32),
+ builder.makeLocalGet(tempPtr, Type::i32),
builder.makeBinary(ShrUInt32,
- builder.makeLocalGet(tempValue, i32),
+ builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(Literal(int32_t(8)))),
- i32));
+ Type::i32));
} else if (curr->bytes == 4) {
if (curr->align == 1) {
block->list.push_back(
builder.makeStore(1,
curr->offset,
1,
- builder.makeLocalGet(tempPtr, i32),
- builder.makeLocalGet(tempValue, i32),
- i32));
+ builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempValue, Type::i32),
+ Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 1,
1,
- builder.makeLocalGet(tempPtr, i32),
+ builder.makeLocalGet(tempPtr, Type::i32),
builder.makeBinary(ShrUInt32,
- builder.makeLocalGet(tempValue, i32),
+ builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(Literal(int32_t(8)))),
- i32));
+ Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 2,
1,
- builder.makeLocalGet(tempPtr, i32),
+ builder.makeLocalGet(tempPtr, Type::i32),
builder.makeBinary(ShrUInt32,
- builder.makeLocalGet(tempValue, i32),
+ builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(Literal(int32_t(16)))),
- i32));
+ Type::i32));
block->list.push_back(builder.makeStore(
1,
curr->offset + 3,
1,
- builder.makeLocalGet(tempPtr, i32),
+ builder.makeLocalGet(tempPtr, Type::i32),
builder.makeBinary(ShrUInt32,
- builder.makeLocalGet(tempValue, i32),
+ builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(Literal(int32_t(24)))),
- i32));
+ Type::i32));
} else if (curr->align == 2) {
block->list.push_back(
builder.makeStore(2,
curr->offset,
2,
- builder.makeLocalGet(tempPtr, i32),
- builder.makeLocalGet(tempValue, i32),
- i32));
+ builder.makeLocalGet(tempPtr, Type::i32),
+ builder.makeLocalGet(tempValue, Type::i32),
+ Type::i32));
block->list.push_back(builder.makeStore(
2,
curr->offset + 2,
2,
- builder.makeLocalGet(tempPtr, i32),
+ builder.makeLocalGet(tempPtr, Type::i32),
builder.makeBinary(ShrUInt32,
- builder.makeLocalGet(tempValue, i32),
+ builder.makeLocalGet(tempValue, Type::i32),
builder.makeConst(Literal(int32_t(16)))),
- i32));
+ Type::i32));
} else {
WASM_UNREACHABLE("invalid alignment");
}
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index 8f929d9fe..b7e8c90e0 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -298,10 +298,10 @@ class GlobalHelper {
public:
GlobalHelper(Module& module) : module(module) {
- map[i32] = "asyncify_fake_call_global_i32";
- map[i64] = "asyncify_fake_call_global_i64";
- map[f32] = "asyncify_fake_call_global_f32";
- map[f64] = "asyncify_fake_call_global_f64";
+ map[Type::i32] = "asyncify_fake_call_global_i32";
+ map[Type::i64] = "asyncify_fake_call_global_i64";
+ map[Type::f32] = "asyncify_fake_call_global_f32";
+ map[Type::f64] = "asyncify_fake_call_global_f64";
Builder builder(module);
for (auto& pair : map) {
auto type = pair.first;
@@ -326,7 +326,7 @@ public:
if (iter != rev.end()) {
return iter->second;
}
- return none;
+ return Type::none;
}
private:
@@ -647,8 +647,8 @@ public:
false,
int32_t(DataOffset::BStackPos),
4,
- makeGlobalGet(ASYNCIFY_DATA, i32),
- i32);
+ makeGlobalGet(ASYNCIFY_DATA, Type::i32),
+ Type::i32);
}
Expression* makeIncStackPos(int32_t by) {
@@ -659,14 +659,14 @@ public:
4,
int32_t(DataOffset::BStackPos),
4,
- makeGlobalGet(ASYNCIFY_DATA, i32),
+ makeGlobalGet(ASYNCIFY_DATA, Type::i32),
makeBinary(AddInt32, makeGetStackPos(), makeConst(Literal(by))),
- i32);
+ Type::i32);
}
Expression* makeStateCheck(State value) {
return makeBinary(EqInt32,
- makeGlobalGet(ASYNCIFY_STATE, i32),
+ makeGlobalGet(ASYNCIFY_STATE, Type::i32),
makeConst(Literal(int32_t(value))));
}
@@ -810,11 +810,11 @@ private:
iff->finalize();
return iff;
}
- auto conditionTemp = builder->addVar(func, i32);
+ auto conditionTemp = builder->addVar(func, Type::i32);
// TODO: can avoid pre if the condition is a get or a const
auto* pre =
makeMaybeSkip(builder->makeLocalSet(conditionTemp, iff->condition));
- iff->condition = builder->makeLocalGet(conditionTemp, i32);
+ iff->condition = builder->makeLocalGet(conditionTemp, Type::i32);
iff->condition = builder->makeBinary(
OrInt32, iff->condition, builder->makeStateCheck(State::Rewinding));
iff->ifTrue = process(iff->ifTrue);
@@ -826,7 +826,7 @@ private:
builder->makeBinary(
OrInt32,
builder->makeUnary(EqZInt32,
- builder->makeLocalGet(conditionTemp, i32)),
+ builder->makeLocalGet(conditionTemp, Type::i32)),
builder->makeStateCheck(State::Rewinding)),
process(otherArm));
otherIf->finalize();
@@ -853,7 +853,7 @@ private:
// TODO: stop doing this after code can no longer reach a call that may
// change the state
assert(doesCall(curr));
- assert(curr->type == none);
+ assert(curr->type == Type::none);
// The case of a set is tricky: we must *not* execute the set when
// unwinding, since at that point we have a fake value for the return,
// and if we applied it to the local, it would end up saved and then
@@ -893,8 +893,9 @@ private:
// it when we add its contents, later.)
return builder->makeIf(
builder->makeStateCheck(State::Unwinding),
- builder->makeCall(
- ASYNCIFY_UNWIND, {builder->makeConst(Literal(int32_t(index)))}, none),
+ builder->makeCall(ASYNCIFY_UNWIND,
+ {builder->makeConst(Literal(int32_t(index)))},
+ Type::none),
ifNotUnwinding);
}
@@ -903,13 +904,13 @@ private:
// don't want it to be seen by asyncify itself.
return builder->makeCall(ASYNCIFY_CHECK_CALL_INDEX,
{builder->makeConst(Literal(int32_t(index)))},
- i32);
+ Type::i32);
}
Expression* makeCallIndexPop() {
// Emit an intrinsic for this, as we store the index into a local, and
// don't want it to be seen by asyncify itself.
- return builder->makeCall(ASYNCIFY_GET_CALL_INDEX, {}, none);
+ return builder->makeCall(ASYNCIFY_GET_CALL_INDEX, {}, Type::none);
}
// Given a function that is not instrumented - because we proved it doesn't
@@ -921,11 +922,11 @@ private:
// That is, if in an uninstrumented function, a sleep should not begin
// from any call.
void addAssertsInNonInstrumented(Function* func) {
- auto oldState = builder->addVar(func, i32);
+ auto oldState = builder->addVar(func, Type::i32);
// Add a check at the function entry.
func->body = builder->makeSequence(
builder->makeLocalSet(oldState,
- builder->makeGlobalGet(ASYNCIFY_STATE, i32)),
+ builder->makeGlobalGet(ASYNCIFY_STATE, Type::i32)),
func->body);
// Add a check around every call.
struct Walker : PostWalker<Walker> {
@@ -944,8 +945,8 @@ private:
void handleCall(Expression* call) {
auto* check = builder->makeIf(
builder->makeBinary(NeInt32,
- builder->makeGlobalGet(ASYNCIFY_STATE, i32),
- builder->makeLocalGet(oldState, i32)),
+ builder->makeGlobalGet(ASYNCIFY_STATE, Type::i32),
+ builder->makeLocalGet(oldState, Type::i32)),
builder->makeUnreachable());
Expression* rep;
if (call->type.isConcrete()) {
@@ -991,11 +992,12 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
builder->makeIncStackPos(-4),
builder->makeLocalSet(
rewindIndex,
- builder->makeLoad(4, false, 0, 4, builder->makeGetStackPos(), i32))));
+ builder->makeLoad(
+ 4, false, 0, 4, builder->makeGetStackPos(), Type::i32))));
} else if (curr->target == ASYNCIFY_CHECK_CALL_INDEX) {
replaceCurrent(builder->makeBinary(
EqInt32,
- builder->makeLocalGet(rewindIndex, i32),
+ builder->makeLocalGet(rewindIndex, Type::i32),
builder->makeConst(
Literal(int32_t(curr->operands[0]->cast<Const>()->value.geti32())))));
}
@@ -1003,7 +1005,7 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
void visitGlobalSet(GlobalSet* curr) {
auto type = analyzer->globals.getTypeOrNone(curr->name);
- if (type != none) {
+ if (type != Type::none) {
replaceCurrent(
builder->makeLocalSet(getFakeCallLocal(type), curr->value));
}
@@ -1011,7 +1013,7 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
void visitGlobalGet(GlobalGet* curr) {
auto type = analyzer->globals.getTypeOrNone(curr->name);
- if (type != none) {
+ if (type != Type::none) {
replaceCurrent(builder->makeLocalGet(getFakeCallLocal(type), type));
}
}
@@ -1038,8 +1040,8 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
// well as saving the locals.
// An index is needed for getting the unwinding and rewinding call indexes
// around TODO: can this be the same index?
- auto unwindIndex = builder->addVar(func, i32);
- rewindIndex = builder->addVar(func, i32);
+ auto unwindIndex = builder->addVar(func, Type::i32);
+ rewindIndex = builder->addVar(func, Type::i32);
// Rewrite the function body.
builder = make_unique<AsyncifyBuilder>(*getModule());
walk(func->body);
@@ -1095,7 +1097,7 @@ private:
}
auto* block = builder->makeBlock();
block->list.push_back(builder->makeIncStackPos(-total));
- auto tempIndex = builder->addVar(func, i32);
+ auto tempIndex = builder->addVar(func, Type::i32);
block->list.push_back(
builder->makeLocalSet(tempIndex, builder->makeGetStackPos()));
Index offset = 0;
@@ -1110,7 +1112,7 @@ private:
true,
offset,
STACK_ALIGN,
- builder->makeLocalGet(tempIndex, i32),
+ builder->makeLocalGet(tempIndex, Type::i32),
type)));
offset += size;
}
@@ -1124,7 +1126,7 @@ private:
}
auto* func = getFunction();
auto* block = builder->makeBlock();
- auto tempIndex = builder->addVar(func, i32);
+ auto tempIndex = builder->addVar(func, Type::i32);
block->list.push_back(
builder->makeLocalSet(tempIndex, builder->makeGetStackPos()));
Index offset = 0;
@@ -1137,7 +1139,7 @@ private:
builder->makeStore(size,
offset,
STACK_ALIGN,
- builder->makeLocalGet(tempIndex, i32),
+ builder->makeLocalGet(tempIndex, Type::i32),
builder->makeLocalGet(i, type),
type));
offset += size;
@@ -1154,8 +1156,8 @@ private:
0,
4,
builder->makeGetStackPos(),
- builder->makeLocalGet(tempIndex, i32),
- i32),
+ builder->makeLocalGet(tempIndex, Type::i32),
+ Type::i32),
builder->makeIncStackPos(4));
}
};
@@ -1281,11 +1283,11 @@ private:
void addGlobals(Module* module) {
Builder builder(*module);
module->addGlobal(builder.makeGlobal(ASYNCIFY_STATE,
- i32,
+ Type::i32,
builder.makeConst(Literal(int32_t(0))),
Builder::Mutable));
module->addGlobal(builder.makeGlobal(ASYNCIFY_DATA,
- i32,
+ Type::i32,
builder.makeConst(Literal(int32_t(0))),
Builder::Mutable));
}
@@ -1295,14 +1297,14 @@ private:
auto makeFunction = [&](Name name, bool setData, State state) {
std::vector<Type> params;
if (setData) {
- params.push_back(i32);
+ params.push_back(Type::i32);
}
auto* body = builder.makeBlock();
body->list.push_back(builder.makeGlobalSet(
ASYNCIFY_STATE, builder.makeConst(Literal(int32_t(state)))));
if (setData) {
- body->list.push_back(
- builder.makeGlobalSet(ASYNCIFY_DATA, builder.makeLocalGet(0, i32)));
+ body->list.push_back(builder.makeGlobalSet(
+ ASYNCIFY_DATA, builder.makeLocalGet(0, Type::i32)));
}
// Verify the data is valid.
auto* stackPos =
@@ -1310,15 +1312,15 @@ private:
false,
int32_t(DataOffset::BStackPos),
4,
- builder.makeGlobalGet(ASYNCIFY_DATA, i32),
- i32);
+ builder.makeGlobalGet(ASYNCIFY_DATA, Type::i32),
+ Type::i32);
auto* stackEnd =
builder.makeLoad(4,
false,
int32_t(DataOffset::BStackEnd),
4,
- builder.makeGlobalGet(ASYNCIFY_DATA, i32),
- i32);
+ builder.makeGlobalGet(ASYNCIFY_DATA, Type::i32),
+ Type::i32);
body->list.push_back(
builder.makeIf(builder.makeBinary(GtUInt32, stackPos, stackEnd),
builder.makeUnreachable()));
diff --git a/src/passes/AvoidReinterprets.cpp b/src/passes/AvoidReinterprets.cpp
index f1b3d96d8..4df75dd15 100644
--- a/src/passes/AvoidReinterprets.cpp
+++ b/src/passes/AvoidReinterprets.cpp
@@ -115,7 +115,7 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
auto& info = pair.second;
if (info.reinterpreted && canReplaceWithReinterpret(load)) {
// We should use another load here, to avoid reinterprets.
- info.ptrLocal = Builder::addVar(func, i32);
+ info.ptrLocal = Builder::addVar(func, Type::i32);
info.reinterpretedLocal =
Builder::addVar(func, load->type.reinterpret());
} else {
@@ -165,7 +165,7 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
auto& info = iter->second;
Builder builder(*module);
auto* ptr = curr->ptr;
- curr->ptr = builder.makeLocalGet(info.ptrLocal, i32);
+ curr->ptr = builder.makeLocalGet(info.ptrLocal, Type::i32);
// Note that the other load can have its sign set to false - if the
// original were an integer, the other is a float anyhow; and if
// original were a float, we don't know what sign to use.
@@ -173,8 +173,8 @@ struct AvoidReinterprets : public WalkerPass<PostWalker<AvoidReinterprets>> {
{builder.makeLocalSet(info.ptrLocal, ptr),
builder.makeLocalSet(
info.reinterpretedLocal,
- makeReinterpretedLoad(curr,
- builder.makeLocalGet(info.ptrLocal, i32))),
+ makeReinterpretedLoad(
+ curr, builder.makeLocalGet(info.ptrLocal, Type::i32))),
curr}));
}
}
diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp
index 947e64715..9b6e1143d 100644
--- a/src/passes/CodeFolding.cpp
+++ b/src/passes/CodeFolding.cpp
@@ -201,7 +201,7 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> {
// see if there is a fallthrough
bool hasFallthrough = true;
for (auto* child : curr->list) {
- if (child->type == unreachable) {
+ if (child->type == Type::unreachable) {
hasFallthrough = false;
}
}
@@ -685,12 +685,12 @@ private:
auto* old = getFunction()->body;
auto* inner = builder.makeBlock();
inner->name = innerName;
- if (old->type == unreachable) {
+ if (old->type == Type::unreachable) {
// the old body is not flowed out of anyhow, so just put it there
inner->list.push_back(old);
} else {
// otherwise, we must not flow out to the merged code
- if (old->type == none) {
+ if (old->type == Type::none) {
inner->list.push_back(old);
inner->list.push_back(builder.makeReturn());
} else {
@@ -703,7 +703,7 @@ private:
if (toplevel) {
toplevel->finalize();
}
- if (old->type != unreachable) {
+ if (old->type != Type::unreachable) {
inner->list.push_back(builder.makeReturn(old));
} else {
inner->list.push_back(old);
diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp
index 4e8cd9910..6c79c4215 100644
--- a/src/passes/ConstHoisting.cpp
+++ b/src/passes/ConstHoisting.cpp
@@ -78,29 +78,29 @@ private:
// measure the size of the constant
Index size = 0;
switch (value.type) {
- case i32: {
+ case Type::i32: {
size = getWrittenSize(S32LEB(value.geti32()));
break;
}
- case i64: {
+ case Type::i64: {
size = getWrittenSize(S64LEB(value.geti64()));
break;
}
- case f32:
- case f64: {
+ case Type::f32:
+ case Type::f64: {
size = value.type.getByteSize();
break;
}
- // not implemented yet
- case v128:
- case funcref:
- case anyref:
- case nullref:
- case exnref: {
+ // not implemented yet
+ case Type::v128:
+ case Type::funcref:
+ case Type::anyref:
+ case Type::nullref:
+ case Type::exnref: {
return false;
}
- case none:
- case unreachable:
+ case Type::none:
+ case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
// compute the benefit, of replacing the uses with
diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp
index 4395fc780..43ebc6721 100644
--- a/src/passes/DeadArgumentElimination.cpp
+++ b/src/passes/DeadArgumentElimination.cpp
@@ -294,21 +294,21 @@ struct DAE : public Pass {
assert(call->operands.size() == numParams);
auto* operand = call->operands[i];
if (auto* c = operand->dynCast<Const>()) {
- if (value.type == none) {
+ if (value.type == Type::none) {
// This is the first value seen.
value = c->value;
} else if (value != c->value) {
// Not identical, give up
- value.type = none;
+ value.type = Type::none;
break;
}
} else {
// Not a constant, give up
- value.type = none;
+ value.type = Type::none;
break;
}
}
- if (value.type != none) {
+ if (value.type != Type::none) {
// Success! We can just apply the constant in the function, which
// makes the parameter value unused, which lets us remove it later.
Builder builder(*module);
@@ -466,8 +466,8 @@ private:
Expression** location = iter->second;
*location = call;
// Update the call's type.
- if (call->type != unreachable) {
- call->type = none;
+ if (call->type != Type::unreachable) {
+ call->type = Type::none;
}
}
}
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 7d5385a83..ac984f6cb 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -82,10 +82,14 @@ struct DeadCodeElimination
}
// if a child exists and is unreachable, we can replace ourselves with it
- bool isDead(Expression* child) { return child && child->type == unreachable; }
+ bool isDead(Expression* child) {
+ return child && child->type == Type::unreachable;
+ }
// a similar check, assumes the child exists
- bool isUnreachable(Expression* child) { return child->type == unreachable; }
+ bool isUnreachable(Expression* child) {
+ return child->type == Type::unreachable;
+ }
// things that stop control flow
@@ -170,7 +174,7 @@ struct DeadCodeElimination
if (!reachable && list.size() > 1) {
// to do here: nothing to remove after it)
for (Index i = 0; i < list.size() - 1; i++) {
- if (list[i]->type == unreachable) {
+ if (list[i]->type == Type::unreachable) {
list.resize(i + 1);
break;
}
@@ -393,7 +397,7 @@ struct DeadCodeElimination
// we don't need to drop unreachable nodes
Expression* drop(Expression* toDrop) {
- if (toDrop->type == unreachable) {
+ if (toDrop->type == Type::unreachable) {
return toDrop;
}
return Builder(*getModule()).makeDrop(toDrop);
diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp
index fda8e3f80..13aa985aa 100644
--- a/src/passes/Flatten.cpp
+++ b/src/passes/Flatten.cpp
@@ -105,7 +105,7 @@ struct Flatten
if (last->type.isConcrete()) {
last = builder.makeLocalSet(temp, last);
}
- block->finalize(none);
+ block->finalize(Type::none);
// and we leave just a get of the value
auto* rep = builder.makeLocalGet(temp, type);
replaceCurrent(rep);
@@ -113,7 +113,7 @@ struct Flatten
ourPreludes.push_back(block);
}
// the block now has no return value, and may have become unreachable
- block->finalize(none);
+ block->finalize(Type::none);
} else if (auto* iff = curr->dynCast<If>()) {
// condition preludes go before the entire if
@@ -160,7 +160,7 @@ struct Flatten
rep = builder.makeLocalGet(temp, type);
// the whole if is now a prelude
ourPreludes.push_back(loop);
- loop->type = none;
+ loop->type = Type::none;
}
loop->body = getPreludesWithExpression(originalBody, loop->body);
loop->finalize();
@@ -181,7 +181,7 @@ struct Flatten
if (auto* set = curr->dynCast<LocalSet>()) {
if (set->isTee()) {
// we disallow local.tee
- if (set->value->type == unreachable) {
+ if (set->value->type == Type::unreachable) {
replaceCurrent(set->value); // trivial, no set happens
} else {
// use a set in a prelude + a get
@@ -234,14 +234,14 @@ struct Flatten
if (br->type.isConcrete()) {
replaceCurrent(builder.makeLocalGet(temp, type));
} else {
- assert(br->type == unreachable);
+ assert(br->type == Type::unreachable);
replaceCurrent(builder.makeUnreachable());
}
}
br->value = nullptr;
br->finalize();
} else {
- assert(type == unreachable);
+ assert(type == Type::unreachable);
// we don't need the br at all
replaceCurrent(br->value);
}
@@ -264,7 +264,7 @@ struct Flatten
sw->value = nullptr;
sw->finalize();
} else {
- assert(type == unreachable);
+ assert(type == Type::unreachable);
// we don't need the br at all
replaceCurrent(sw->value);
}
@@ -277,7 +277,7 @@ struct Flatten
curr = getCurrent(); // we may have replaced it
// we have changed children
ReFinalizeNode().visit(curr);
- if (curr->type == unreachable) {
+ if (curr->type == Type::unreachable) {
ourPreludes.push_back(curr);
replaceCurrent(builder.makeUnreachable());
} else if (curr->type.isConcrete()) {
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index 9d5109a83..09c87c212 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -45,38 +45,39 @@ static const int NUM_PARAMS = 16;
static Expression* toABI(Expression* value, Module* module) {
Builder builder(*module);
switch (value->type) {
- case i32: {
+ case Type::i32: {
value = builder.makeUnary(ExtendUInt32, value);
break;
}
- case i64: {
+ case Type::i64: {
// already good
break;
}
- case f32: {
+ case Type::f32: {
value = builder.makeUnary(ExtendUInt32,
builder.makeUnary(ReinterpretFloat32, value));
break;
}
- case f64: {
+ case Type::f64: {
value = builder.makeUnary(ReinterpretFloat64, value);
break;
}
- case v128: {
+ case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case funcref:
- case anyref:
- case nullref:
- case exnref: {
+ case Type::funcref:
+ case Type::anyref:
+ case Type::nullref:
+ case Type::exnref: {
WASM_UNREACHABLE("reference types cannot be converted to i64");
}
- case none: {
+ case Type::none: {
// the value is none, but we need a value here
- value = builder.makeSequence(value, LiteralUtils::makeZero(i64, *module));
+ value =
+ builder.makeSequence(value, LiteralUtils::makeZero(Type::i64, *module));
break;
}
- case unreachable: {
+ case Type::unreachable: {
// can leave it, the call isn't taken anyhow
break;
}
@@ -88,36 +89,36 @@ static Expression* toABI(Expression* value, Module* module) {
static Expression* fromABI(Expression* value, Type type, Module* module) {
Builder builder(*module);
switch (type) {
- case i32: {
+ case Type::i32: {
value = builder.makeUnary(WrapInt64, value);
break;
}
- case i64: {
+ case Type::i64: {
// already good
break;
}
- case f32: {
+ case Type::f32: {
value = builder.makeUnary(ReinterpretInt32,
builder.makeUnary(WrapInt64, value));
break;
}
- case f64: {
+ case Type::f64: {
value = builder.makeUnary(ReinterpretInt64, value);
break;
}
- case v128: {
+ case Type::v128: {
WASM_UNREACHABLE("v128 not implemented yet");
}
- case funcref:
- case anyref:
- case nullref:
- case exnref: {
+ case Type::funcref:
+ case Type::anyref:
+ case Type::nullref:
+ case Type::exnref: {
WASM_UNREACHABLE("reference types cannot be converted from i64");
}
- case none: {
+ case Type::none: {
value = builder.makeDrop(value);
}
- case unreachable: {
+ case Type::unreachable: {
// can leave it, the call isn't taken anyhow
break;
}
@@ -143,12 +144,12 @@ struct ParallelFuncCastEmulation
}
// Add extra operands as needed.
while (curr->operands.size() < NUM_PARAMS) {
- curr->operands.push_back(LiteralUtils::makeZero(i64, *getModule()));
+ curr->operands.push_back(LiteralUtils::makeZero(Type::i64, *getModule()));
}
// Set the new types
curr->sig = ABIType;
auto oldType = curr->type;
- curr->type = i64;
+ curr->type = Type::i64;
curr->finalize(); // may be unreachable
// Fix up return value
replaceCurrent(fromABI(curr, oldType, getModule()));
@@ -203,12 +204,12 @@ private:
std::vector<Expression*> callOperands;
for (Index i = 0; i < params.size(); i++) {
callOperands.push_back(
- fromABI(builder.makeLocalGet(i, i64), params[i], module));
+ fromABI(builder.makeLocalGet(i, Type::i64), params[i], module));
}
auto* call = builder.makeCall(name, callOperands, type);
std::vector<Type> thunkParams;
for (Index i = 0; i < NUM_PARAMS; i++) {
- thunkParams.push_back(i64);
+ thunkParams.push_back(Type::i64);
}
auto* thunkFunc =
builder.makeFunction(thunk,
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index c9a4f46ea..c3ed6fb04 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -109,13 +109,13 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
// add new globals for high bits
for (size_t i = 0, globals = module->globals.size(); i < globals; ++i) {
auto* curr = module->globals[i].get();
- if (curr->type != i64) {
+ if (curr->type != Type::i64) {
continue;
}
originallyI64Globals.insert(curr->name);
- curr->type = i32;
+ curr->type = Type::i32;
auto* high = builder->makeGlobal(makeHighName(curr->name),
- i32,
+ Type::i32,
builder->makeConst(Literal(int32_t(0))),
Builder::Mutable);
module->addGlobal(high);
@@ -125,21 +125,22 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (auto* c = curr->init->dynCast<Const>()) {
uint64_t value = c->value.geti64();
c->value = Literal(uint32_t(value));
- c->type = i32;
+ c->type = Type::i32;
high->init = builder->makeConst(Literal(uint32_t(value >> 32)));
} else if (auto* get = curr->init->dynCast<GlobalGet>()) {
- high->init = builder->makeGlobalGet(makeHighName(get->name), i32);
+ high->init =
+ builder->makeGlobalGet(makeHighName(get->name), Type::i32);
} else {
WASM_UNREACHABLE("unexpected expression type");
}
- curr->init->type = i32;
+ curr->init->type = Type::i32;
}
}
// For functions that return 64-bit values, we use this global variable
// to return the high 32 bits.
auto* highBits = new Global();
- highBits->type = i32;
+ highBits->type = Type::i32;
highBits->name = INT64_TO_32_HIGH_BITS;
highBits->init = builder->makeConst(Literal(int32_t(0)));
highBits->mutable_ = true;
@@ -173,7 +174,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
(i < oldFunc->getVarIndexBase())
? Builder::addParam
: static_cast<Index (*)(Function*, Name, Type)>(Builder::addVar);
- if (paramType == i64) {
+ if (paramType == Type::i64) {
builderFunc(func, lowName, Type::i32);
builderFunc(func, highName, Type::i32);
indexMap[i] = newIdx;
@@ -199,8 +200,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
TempVar lowBits = getTemp();
LocalSet* setLow = builder->makeLocalSet(lowBits, func->body);
GlobalSet* setHigh = builder->makeGlobalSet(
- INT64_TO_32_HIGH_BITS, builder->makeLocalGet(highBits, i32));
- LocalGet* getLow = builder->makeLocalGet(lowBits, i32);
+ INT64_TO_32_HIGH_BITS, builder->makeLocalGet(highBits, Type::i32));
+ LocalGet* getLow = builder->makeLocalGet(lowBits, Type::i32);
func->body = builder->blockify(setLow, setHigh, getLow);
}
}
@@ -224,7 +225,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
args.push_back(e);
if (hasOutParam(e)) {
TempVar argHighBits = fetchOutParam(e);
- args.push_back(builder->makeLocalGet(argHighBits, i32));
+ args.push_back(builder->makeLocalGet(argHighBits, Type::i32));
fixed = true;
}
}
@@ -238,8 +239,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
auto* call = callBuilder(args, Type::i32);
LocalSet* doCall = builder->makeLocalSet(lowBits, call);
LocalSet* setHigh = builder->makeLocalSet(
- highBits, builder->makeGlobalGet(INT64_TO_32_HIGH_BITS, i32));
- LocalGet* getLow = builder->makeLocalGet(lowBits, i32);
+ highBits, builder->makeGlobalGet(INT64_TO_32_HIGH_BITS, Type::i32));
+ LocalGet* getLow = builder->makeLocalGet(lowBits, Type::i32);
Block* result = builder->blockify(doCall, setHigh, getLow);
setOutParam(result, std::move(highBits));
replaceCurrent(result);
@@ -289,13 +290,13 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
// Need to remap the local into the new naming scheme, regardless of
// the type of the local.
curr->index = mappedIndex;
- if (curr->type != i64) {
+ if (curr->type != Type::i64) {
return;
}
- curr->type = i32;
+ curr->type = Type::i32;
TempVar highBits = getTemp();
LocalSet* setHighBits = builder->makeLocalSet(
- highBits, builder->makeLocalGet(mappedIndex + 1, i32));
+ highBits, builder->makeLocalGet(mappedIndex + 1, Type::i32));
Block* result = builder->blockify(setHighBits, curr);
replaceCurrent(result);
setOutParam(result, std::move(highBits));
@@ -304,11 +305,11 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
void lowerTee(LocalSet* curr) {
TempVar highBits = fetchOutParam(curr->value);
TempVar tmp = getTemp();
- curr->type = i32;
+ curr->type = Type::i32;
LocalSet* setLow = builder->makeLocalSet(tmp, curr);
LocalSet* setHigh = builder->makeLocalSet(
- curr->index + 1, builder->makeLocalGet(highBits, i32));
- LocalGet* getLow = builder->makeLocalGet(tmp, i32);
+ curr->index + 1, builder->makeLocalGet(highBits, Type::i32));
+ LocalGet* getLow = builder->makeLocalGet(tmp, Type::i32);
Block* result = builder->blockify(setLow, setHigh, getLow);
replaceCurrent(result);
setOutParam(result, std::move(highBits));
@@ -327,8 +328,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
return;
}
TempVar highBits = fetchOutParam(curr->value);
- auto* setHigh = builder->makeLocalSet(mappedIndex + 1,
- builder->makeLocalGet(highBits, i32));
+ auto* setHigh = builder->makeLocalSet(
+ mappedIndex + 1, builder->makeLocalGet(highBits, Type::i32));
Block* result = builder->blockify(curr, setHigh);
replaceCurrent(result);
}
@@ -340,10 +341,10 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (!originallyI64Globals.count(curr->name)) {
return;
}
- curr->type = i32;
+ curr->type = Type::i32;
TempVar highBits = getTemp();
LocalSet* setHighBits = builder->makeLocalSet(
- highBits, builder->makeGlobalGet(makeHighName(curr->name), i32));
+ highBits, builder->makeGlobalGet(makeHighName(curr->name), Type::i32));
Block* result = builder->blockify(setHighBits, curr);
replaceCurrent(result);
setOutParam(result, std::move(highBits));
@@ -358,12 +359,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
TempVar highBits = fetchOutParam(curr->value);
auto* setHigh = builder->makeGlobalSet(
- makeHighName(curr->name), builder->makeLocalGet(highBits, i32));
+ makeHighName(curr->name), builder->makeLocalGet(highBits, Type::i32));
replaceCurrent(builder->makeSequence(curr, setHigh));
}
void visitLoad(Load* curr) {
- if (curr->type != i64) {
+ if (curr->type != Type::i64) {
return;
}
assert(!curr->isAtomic && "atomic load not implemented");
@@ -379,26 +380,27 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
curr->signed_,
curr->offset + 4,
std::min(uint32_t(curr->align), uint32_t(4)),
- builder->makeLocalGet(ptrTemp, i32),
- i32));
+ builder->makeLocalGet(ptrTemp, Type::i32),
+ Type::i32));
} else if (curr->signed_) {
loadHigh = builder->makeLocalSet(
highBits,
builder->makeBinary(ShrSInt32,
- builder->makeLocalGet(lowBits, i32),
+ builder->makeLocalGet(lowBits, Type::i32),
builder->makeConst(Literal(int32_t(31)))));
} else {
loadHigh = builder->makeLocalSet(highBits,
builder->makeConst(Literal(int32_t(0))));
}
- curr->type = i32;
+ curr->type = Type::i32;
curr->bytes = std::min(curr->bytes, uint8_t(4));
curr->align = std::min(uint32_t(curr->align), uint32_t(4));
- curr->ptr = builder->makeLocalGet(ptrTemp, i32);
- Block* result = builder->blockify(setPtr,
- builder->makeLocalSet(lowBits, curr),
- loadHigh,
- builder->makeLocalGet(lowBits, i32));
+ curr->ptr = builder->makeLocalGet(ptrTemp, Type::i32);
+ Block* result =
+ builder->blockify(setPtr,
+ builder->makeLocalSet(lowBits, curr),
+ loadHigh,
+ builder->makeLocalGet(lowBits, Type::i32));
replaceCurrent(result);
setOutParam(result, std::move(highBits));
}
@@ -413,19 +415,19 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
uint8_t bytes = curr->bytes;
curr->bytes = std::min(curr->bytes, uint8_t(4));
curr->align = std::min(uint32_t(curr->align), uint32_t(4));
- curr->valueType = i32;
+ curr->valueType = Type::i32;
if (bytes == 8) {
TempVar ptrTemp = getTemp();
LocalSet* setPtr = builder->makeLocalSet(ptrTemp, curr->ptr);
- curr->ptr = builder->makeLocalGet(ptrTemp, i32);
+ curr->ptr = builder->makeLocalGet(ptrTemp, Type::i32);
curr->finalize();
Store* storeHigh =
builder->makeStore(4,
curr->offset + 4,
std::min(uint32_t(curr->align), uint32_t(4)),
- builder->makeLocalGet(ptrTemp, i32),
- builder->makeLocalGet(highBits, i32),
- i32);
+ builder->makeLocalGet(ptrTemp, Type::i32),
+ builder->makeLocalGet(highBits, Type::i32),
+ Type::i32);
replaceCurrent(builder->blockify(setPtr, curr, storeHigh));
}
}
@@ -442,7 +444,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (!getFunction()) {
return; // if in a global init, skip - we already handled that.
}
- if (curr->type != i64) {
+ if (curr->type != Type::i64) {
return;
}
TempVar highBits = getTemp();
@@ -463,7 +465,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
auto* result = builder->makeUnary(
EqZInt32,
builder->makeBinary(
- OrInt32, curr->value, builder->makeLocalGet(highBits, i32)));
+ OrInt32, curr->value, builder->makeLocalGet(highBits, Type::i32)));
replaceCurrent(result);
}
@@ -485,11 +487,11 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
LocalSet* setHigh = builder->makeLocalSet(
highBits,
builder->makeBinary(ShrSInt32,
- builder->makeLocalGet(lowBits, i32),
+ builder->makeLocalGet(lowBits, Type::i32),
builder->makeConst(Literal(int32_t(31)))));
- Block* result =
- builder->blockify(setLow, setHigh, builder->makeLocalGet(lowBits, i32));
+ Block* result = builder->blockify(
+ setLow, setHigh, builder->makeLocalGet(lowBits, Type::i32));
setOutParam(result, std::move(highBits));
replaceCurrent(result);
@@ -506,15 +508,16 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
// our f64 through memory at address 0
TempVar highBits = getTemp();
Block* result = builder->blockify(
- builder->makeCall(ABI::wasm2js::SCRATCH_STORE_F64, {curr->value}, none),
+ builder->makeCall(
+ ABI::wasm2js::SCRATCH_STORE_F64, {curr->value}, Type::none),
builder->makeLocalSet(
highBits,
builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_I32,
{builder->makeConst(Literal(int32_t(1)))},
- i32)),
+ Type::i32)),
builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_I32,
{builder->makeConst(Literal(int32_t(0)))},
- i32));
+ Type::i32));
setOutParam(result, std::move(highBits));
replaceCurrent(result);
MemoryUtils::ensureExists(getModule()->memory);
@@ -528,12 +531,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
Block* result = builder->blockify(
builder->makeCall(ABI::wasm2js::SCRATCH_STORE_I32,
{builder->makeConst(Literal(int32_t(0))), curr->value},
- none),
+ Type::none),
builder->makeCall(ABI::wasm2js::SCRATCH_STORE_I32,
{builder->makeConst(Literal(int32_t(1))),
- builder->makeLocalGet(highBits, i32)},
- none),
- builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_F64, {}, f64));
+ builder->makeLocalGet(highBits, Type::i32)},
+ Type::none),
+ builder->makeCall(ABI::wasm2js::SCRATCH_LOAD_F64, {}, Type::f64));
replaceCurrent(result);
MemoryUtils::ensureExists(getModule()->memory);
ABI::wasm2js::ensureScratchMemoryHelpers(getModule());
@@ -567,7 +570,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
u32Max = Literal(((float)UINT_MAX) + 1);
trunc = TruncUFloat32ToInt32;
convert = ConvertUInt32ToFloat32;
- localType = f32;
+ localType = Type::f32;
abs = AbsFloat32;
ge = GeFloat32;
gt = GtFloat32;
@@ -585,7 +588,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
u32Max = Literal(((double)UINT_MAX) + 1);
trunc = TruncUFloat64ToInt32;
convert = ConvertUInt32ToFloat64;
- localType = f64;
+ localType = Type::f64;
abs = AbsFloat64;
ge = GeFloat64;
gt = GtFloat64;
@@ -682,12 +685,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeBinary(
AddFloat64,
builder->makeUnary(ConvertUInt32ToFloat64,
- builder->makeLocalGet(lowBits, i32)),
+ builder->makeLocalGet(lowBits, Type::i32)),
builder->makeBinary(
MulFloat64,
builder->makeConst(Literal((double)UINT_MAX + 1)),
builder->makeUnary(convertHigh,
- builder->makeLocalGet(highBits, i32)))));
+ builder->makeLocalGet(highBits, Type::i32)))));
switch (curr->op) {
case ConvertSInt64ToFloat32:
@@ -711,20 +714,20 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
TempVar firstResult = getTemp();
LocalSet* setFirst = builder->makeLocalSet(
firstResult,
- builder->makeUnary(op32, builder->makeLocalGet(first, i32)));
+ builder->makeUnary(op32, builder->makeLocalGet(first, Type::i32)));
Binary* check =
builder->makeBinary(EqInt32,
- builder->makeLocalGet(firstResult, i32),
+ builder->makeLocalGet(firstResult, Type::i32),
builder->makeConst(Literal(int32_t(32))));
If* conditional = builder->makeIf(
check,
builder->makeBinary(
AddInt32,
- builder->makeUnary(op32, builder->makeLocalGet(second, i32)),
+ builder->makeUnary(op32, builder->makeLocalGet(second, Type::i32)),
builder->makeConst(Literal(int32_t(32)))),
- builder->makeLocalGet(firstResult, i32));
+ builder->makeLocalGet(firstResult, Type::i32));
LocalSet* setHigh = builder->makeLocalSet(
highResult, builder->makeConst(Literal(int32_t(0))));
@@ -783,7 +786,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (handleUnreachable(curr)) {
return;
}
- assert(hasOutParam(curr->value) || curr->type == i64 || curr->type == f64);
+ assert(hasOutParam(curr->value) || curr->type == Type::i64 ||
+ curr->type == Type::f64);
switch (curr->op) {
case ClzInt64:
case CtzInt64:
@@ -837,24 +841,24 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
LocalSet* addLow = builder->makeLocalSet(
lowResult,
builder->makeBinary(AddInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)));
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)));
LocalSet* addHigh = builder->makeLocalSet(
highResult,
builder->makeBinary(AddInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32)));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32)));
LocalSet* carryBit = builder->makeLocalSet(
highResult,
builder->makeBinary(AddInt32,
- builder->makeLocalGet(highResult, i32),
+ builder->makeLocalGet(highResult, Type::i32),
builder->makeConst(Literal(int32_t(1)))));
- If* checkOverflow =
- builder->makeIf(builder->makeBinary(LtUInt32,
- builder->makeLocalGet(lowResult, i32),
- builder->makeLocalGet(rightLow, i32)),
- carryBit);
- LocalGet* getLow = builder->makeLocalGet(lowResult, i32);
+ If* checkOverflow = builder->makeIf(
+ builder->makeBinary(LtUInt32,
+ builder->makeLocalGet(lowResult, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)),
+ carryBit);
+ LocalGet* getLow = builder->makeLocalGet(lowResult, Type::i32);
result = builder->blockify(result, addLow, addHigh, checkOverflow, getLow);
setOutParam(result, std::move(highResult));
return result;
@@ -871,24 +875,24 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
LocalSet* subLow = builder->makeLocalSet(
lowResult,
builder->makeBinary(SubInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)));
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)));
LocalSet* borrowBit = builder->makeLocalSet(
borrow,
builder->makeBinary(LtUInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)));
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)));
LocalSet* subHigh1 = builder->makeLocalSet(
highResult,
builder->makeBinary(AddInt32,
- builder->makeLocalGet(borrow, i32),
- builder->makeLocalGet(rightHigh, i32)));
+ builder->makeLocalGet(borrow, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32)));
LocalSet* subHigh2 = builder->makeLocalSet(
highResult,
builder->makeBinary(SubInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(highResult, i32)));
- LocalGet* getLow = builder->makeLocalGet(lowResult, i32);
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(highResult, Type::i32)));
+ LocalGet* getLow = builder->makeLocalGet(lowResult, Type::i32);
result =
builder->blockify(result, subLow, borrowBit, subHigh1, subHigh2, getLow);
setOutParam(result, std::move(highResult));
@@ -920,11 +924,11 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeLocalSet(
rightHigh,
builder->makeBinary(op32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32))),
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32))),
builder->makeBinary(op32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)));
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)));
setOutParam(result, std::move(rightHigh));
return result;
}
@@ -934,8 +938,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeLocalSet(
highBits,
builder->makeBinary(ShlInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(shift, i32))),
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(shift, Type::i32))),
builder->makeConst(Literal(int32_t(0))));
}
@@ -950,19 +954,19 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeLocalSet(
highBits,
builder->makeBinary(ShrSInt32,
- builder->makeLocalGet(leftHigh, i32),
+ builder->makeLocalGet(leftHigh, Type::i32),
builder->makeConst(Literal(int32_t(31))))),
builder->makeBinary(ShrSInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(shift, i32)));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(shift, Type::i32)));
}
Block* makeLargeShrU(Index highBits, Index leftHigh, Index shift) {
return builder->blockify(
builder->makeLocalSet(highBits, builder->makeConst(Literal(int32_t(0)))),
builder->makeBinary(ShrUInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(shift, i32)));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(shift, Type::i32)));
}
Block* makeSmallShl(Index highBits,
@@ -975,17 +979,17 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
AndInt32,
shiftMask,
builder->makeBinary(
- ShrUInt32, builder->makeLocalGet(leftLow, i32), widthLessShift));
+ ShrUInt32, builder->makeLocalGet(leftLow, Type::i32), widthLessShift));
Binary* shiftHigh =
builder->makeBinary(ShlInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(shift, i32));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(shift, Type::i32));
return builder->blockify(
builder->makeLocalSet(
highBits, builder->makeBinary(OrInt32, shiftedInBits, shiftHigh)),
builder->makeBinary(ShlInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(shift, i32)));
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(shift, Type::i32)));
}
// a >> b where `b` < 32
@@ -1003,17 +1007,18 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
Binary* shiftedInBits = builder->makeBinary(
ShlInt32,
builder->makeBinary(
- AndInt32, shiftMask, builder->makeLocalGet(leftHigh, i32)),
+ AndInt32, shiftMask, builder->makeLocalGet(leftHigh, Type::i32)),
widthLessShift);
- Binary* shiftLow = builder->makeBinary(ShrUInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(shift, i32));
+ Binary* shiftLow =
+ builder->makeBinary(ShrUInt32,
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(shift, Type::i32));
return builder->blockify(
builder->makeLocalSet(
highBits,
builder->makeBinary(ShrSInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(shift, i32))),
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(shift, Type::i32))),
builder->makeBinary(OrInt32, shiftedInBits, shiftLow));
}
@@ -1026,17 +1031,18 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
Binary* shiftedInBits = builder->makeBinary(
ShlInt32,
builder->makeBinary(
- AndInt32, shiftMask, builder->makeLocalGet(leftHigh, i32)),
+ AndInt32, shiftMask, builder->makeLocalGet(leftHigh, Type::i32)),
widthLessShift);
- Binary* shiftLow = builder->makeBinary(ShrUInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(shift, i32));
+ Binary* shiftLow =
+ builder->makeBinary(ShrUInt32,
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(shift, Type::i32));
return builder->blockify(
builder->makeLocalSet(
highBits,
builder->makeBinary(ShrUInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(shift, i32))),
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(shift, Type::i32))),
builder->makeBinary(OrInt32, shiftedInBits, shiftLow));
}
@@ -1058,13 +1064,13 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
LocalSet* setShift = builder->makeLocalSet(
shift,
builder->makeBinary(AndInt32,
- builder->makeLocalGet(rightLow, i32),
+ builder->makeLocalGet(rightLow, Type::i32),
builder->makeConst(Literal(int32_t(32 - 1)))));
Binary* isLargeShift = builder->makeBinary(
LeUInt32,
builder->makeConst(Literal(int32_t(32))),
builder->makeBinary(AndInt32,
- builder->makeLocalGet(rightLow, i32),
+ builder->makeLocalGet(rightLow, Type::i32),
builder->makeConst(Literal(int32_t(64 - 1)))));
Block* largeShiftBlock;
switch (op) {
@@ -1084,12 +1090,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
SubInt32,
builder->makeBinary(ShlInt32,
builder->makeConst(Literal(int32_t(1))),
- builder->makeLocalGet(shift, i32)),
+ builder->makeLocalGet(shift, Type::i32)),
builder->makeConst(Literal(int32_t(1))));
Binary* widthLessShift =
builder->makeBinary(SubInt32,
builder->makeConst(Literal(int32_t(32))),
- builder->makeLocalGet(shift, i32));
+ builder->makeLocalGet(shift, Type::i32));
Block* smallShiftBlock;
switch (op) {
case ShlInt64: {
@@ -1127,11 +1133,11 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeBinary(
AndInt32,
builder->makeBinary(EqInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)),
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)),
builder->makeBinary(EqInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32))));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32))));
}
Block* lowerNe(Block* result,
@@ -1144,11 +1150,11 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeBinary(
OrInt32,
builder->makeBinary(NeInt32,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32)),
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32)),
builder->makeBinary(NeInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32))));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32))));
}
Block* lowerUComp(BinaryOp op,
@@ -1180,14 +1186,16 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
Binary* compHigh =
builder->makeBinary(highOp,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32));
- Binary* eqHigh = builder->makeBinary(EqInt32,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32));
- Binary* compLow = builder->makeBinary(lowOp,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32));
+ Binary* eqHigh =
+ builder->makeBinary(EqInt32,
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32));
+ Binary* compLow =
+ builder->makeBinary(lowOp,
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32));
return builder->blockify(
result,
builder->makeBinary(
@@ -1227,15 +1235,16 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
Binary* compHigh1 =
builder->makeBinary(highOp1,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32));
Binary* compHigh2 =
builder->makeBinary(highOp2,
- builder->makeLocalGet(leftHigh, i32),
- builder->makeLocalGet(rightHigh, i32));
- Binary* compLow = builder->makeBinary(lowOp,
- builder->makeLocalGet(leftLow, i32),
- builder->makeLocalGet(rightLow, i32));
+ builder->makeLocalGet(leftHigh, Type::i32),
+ builder->makeLocalGet(rightHigh, Type::i32));
+ Binary* compLow =
+ builder->makeBinary(lowOp,
+ builder->makeLocalGet(leftLow, Type::i32),
+ builder->makeLocalGet(rightLow, Type::i32));
If* lowIf = builder->makeIf(compLow,
builder->makeConst(Literal(int32_t(0))),
builder->makeConst(Literal(int32_t(1))));
@@ -1405,14 +1414,14 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
builder->makeLocalSet(
lowBits,
builder->makeSelect(
- builder->makeLocalGet(cond, i32), curr->ifTrue, curr->ifFalse)),
+ builder->makeLocalGet(cond, Type::i32), curr->ifTrue, curr->ifFalse)),
builder->makeLocalSet(
highBits,
builder->makeSelect(
- builder->makeLocalGet(cond, i32),
- builder->makeLocalGet(fetchOutParam(curr->ifTrue), i32),
- builder->makeLocalGet(fetchOutParam(curr->ifFalse), i32))),
- builder->makeLocalGet(lowBits, i32));
+ builder->makeLocalGet(cond, Type::i32),
+ builder->makeLocalGet(fetchOutParam(curr->ifTrue), Type::i32),
+ builder->makeLocalGet(fetchOutParam(curr->ifFalse), Type::i32))),
+ builder->makeLocalGet(lowBits, Type::i32));
setOutParam(result, std::move(highBits));
replaceCurrent(result);
}
@@ -1433,8 +1442,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
TempVar highBits = fetchOutParam(curr->value);
LocalSet* setLow = builder->makeLocalSet(lowBits, curr->value);
GlobalSet* setHigh = builder->makeGlobalSet(
- INT64_TO_32_HIGH_BITS, builder->makeLocalGet(highBits, i32));
- curr->value = builder->makeLocalGet(lowBits, i32);
+ INT64_TO_32_HIGH_BITS, builder->makeLocalGet(highBits, Type::i32));
+ curr->value = builder->makeLocalGet(lowBits, Type::i32);
Block* result = builder->blockify(setLow, setHigh, curr);
replaceCurrent(result);
}
@@ -1448,7 +1457,7 @@ private:
std::unordered_set<Name> originallyI64Globals;
Index nextTemp;
- TempVar getTemp(Type ty = i32) {
+ TempVar getTemp(Type ty = Type::i32) {
Index ret;
auto& freeList = freeTemps[(int)ty];
if (freeList.size() > 0) {
@@ -1486,7 +1495,7 @@ private:
// unconditionally before themselves, so it is not valid for an if,
// in particular.
bool handleUnreachable(Expression* curr) {
- if (curr->type != unreachable) {
+ if (curr->type != Type::unreachable) {
return false;
}
std::vector<Expression*> children;
@@ -1494,7 +1503,7 @@ private:
for (auto* child : ChildIterator(curr)) {
if (child->type.isConcrete()) {
child = builder->makeDrop(child);
- } else if (child->type == unreachable) {
+ } else if (child->type == Type::unreachable) {
hasUnreachable = true;
}
children.push_back(child);
@@ -1505,7 +1514,7 @@ private:
// This has an unreachable child, so we can replace it with
// the children.
auto* block = builder->makeBlock(children);
- assert(block->type == unreachable);
+ assert(block->type == Type::unreachable);
replaceCurrent(block);
return true;
}
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index c43d41e7f..5737359a3 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -154,12 +154,12 @@ struct Planner : public WalkerPass<PostWalker<Planner>> {
bool isUnreachable;
if (curr->isReturn) {
// Tail calls are only actually unreachable if an argument is
- isUnreachable =
- std::any_of(curr->operands.begin(),
- curr->operands.end(),
- [](Expression* op) { return op->type == unreachable; });
+ isUnreachable = std::any_of(
+ curr->operands.begin(), curr->operands.end(), [](Expression* op) {
+ return op->type == Type::unreachable;
+ });
} else {
- isUnreachable = curr->type == unreachable;
+ isUnreachable = curr->type == Type::unreachable;
}
if (state->worthInlining.count(curr->target) && !isUnreachable &&
curr->target != getFunction()->name) {
@@ -273,7 +273,7 @@ doInlining(Module* module, Function* into, const InliningAction& action) {
// contained void, that is fine too. a bad case is a void function in which
// we have unreachable code, so we would be replacing a void call with an
// unreachable.
- if (contents->type == unreachable && block->type == none) {
+ if (contents->type == Type::unreachable && block->type == Type::none) {
// Make the block reachable by adding a break to it
block->list.push_back(builder.makeBreak(block->name));
}
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index ae35ec2d1..3e3be6244 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -75,33 +75,33 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
Builder builder(*getModule());
Name import;
switch (curr->type) {
- case i32:
+ case Type::i32:
import = get_i32;
break;
- case i64:
+ case Type::i64:
return; // TODO
- case f32:
+ case Type::f32:
import = get_f32;
break;
- case f64:
+ case Type::f64:
import = get_f64;
break;
- case v128:
+ case Type::v128:
assert(false && "v128 not implemented yet");
- case funcref:
+ case Type::funcref:
import = get_funcref;
break;
- case anyref:
+ case Type::anyref:
import = get_anyref;
break;
- case nullref:
+ case Type::nullref:
import = get_nullref;
break;
- case exnref:
+ case Type::exnref:
import = get_exnref;
break;
- case none:
- case unreachable:
+ case Type::none:
+ case Type::unreachable:
WASM_UNREACHABLE("unexpected type");
}
replaceCurrent(
@@ -123,34 +123,34 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> {
Builder builder(*getModule());
Name import;
switch (curr->value->type) {
- case i32:
+ case Type::i32:
import = set_i32;
break;
- case i64:
+ case Type::i64:
return; // TODO
- case f32:
+ case Type::f32:
import = set_f32;
break;
- case f64:
+ case Type::f64:
import = set_f64;
break;
- case v128:
+ case Type::v128:
assert(false && "v128 not implemented yet");
- case funcref:
+ case Type::funcref:
import = set_funcref;
break;
- case anyref:
+ case Type::anyref:
import = set_anyref;
break;
- case nullref:
+ case Type::nullref:
import = set_nullref;
break;
- case exnref:
+ case Type::exnref:
import = set_exnref;
break;
- case unreachable:
+ case Type::unreachable:
return; // nothing to do here
- case none:
+ case Type::none:
WASM_UNREACHABLE("unexpected type");
}
curr->value =
diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp
index 9a805b19b..54f763734 100644
--- a/src/passes/InstrumentMemory.cpp
+++ b/src/passes/InstrumentMemory.cpp
@@ -84,19 +84,19 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> {
builder.makeConst(Literal(int32_t(curr->bytes))),
builder.makeConst(Literal(int32_t(curr->offset.addr))),
curr->ptr},
- i32);
+ Type::i32);
Name target;
switch (curr->type) {
- case i32:
+ case Type::i32:
target = load_val_i32;
break;
- case i64:
+ case Type::i64:
target = load_val_i64;
break;
- case f32:
+ case Type::f32:
target = load_val_f32;
break;
- case f64:
+ case Type::f64:
target = load_val_f64;
break;
default:
@@ -115,19 +115,19 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> {
builder.makeConst(Literal(int32_t(curr->bytes))),
builder.makeConst(Literal(int32_t(curr->offset.addr))),
curr->ptr},
- i32);
+ Type::i32);
Name target;
switch (curr->value->type) {
- case i32:
+ case Type::i32:
target = store_val_i32;
break;
- case i64:
+ case Type::i64:
target = store_val_i64;
break;
- case f32:
+ case Type::f32:
target = store_val_f32;
break;
- case f64:
+ case Type::f64:
target = store_val_f64;
break;
default:
diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp
index df6651b0d..3a28e1745 100644
--- a/src/passes/LegalizeJSInterface.cpp
+++ b/src/passes/LegalizeJSInterface.cpp
@@ -244,7 +244,7 @@ private:
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(index, call));
block->list.push_back(builder.makeCall(
- f->name, {I64Utilities::getI64High(builder, index)}, none));
+ f->name, {I64Utilities::getI64High(builder, index)}, Type::none));
block->list.push_back(I64Utilities::getI64Low(builder, index));
block->finalize();
legal->body = block;
@@ -281,8 +281,8 @@ private:
if (imParams[i] == Type::i64) {
call->operands.push_back(I64Utilities::getI64Low(builder, i));
call->operands.push_back(I64Utilities::getI64High(builder, i));
- params.push_back(i32);
- params.push_back(i32);
+ params.push_back(Type::i32);
+ params.push_back(Type::i32);
} else {
call->operands.push_back(builder.makeLocalGet(i, imParams[i]));
params.push_back(imParams[i]);
diff --git a/src/passes/LogExecution.cpp b/src/passes/LogExecution.cpp
index 611f79dfd..a6caf1c1f 100644
--- a/src/passes/LogExecution.cpp
+++ b/src/passes/LogExecution.cpp
@@ -72,7 +72,7 @@ private:
Builder builder(*getModule());
return builder.makeSequence(
builder.makeCall(
- LOGGER, {builder.makeConst(Literal(int32_t(id++)))}, none),
+ LOGGER, {builder.makeConst(Literal(int32_t(id++)))}, Type::none),
curr);
}
};
diff --git a/src/passes/LoopInvariantCodeMotion.cpp b/src/passes/LoopInvariantCodeMotion.cpp
index c4880114d..a95f4c8eb 100644
--- a/src/passes/LoopInvariantCodeMotion.cpp
+++ b/src/passes/LoopInvariantCodeMotion.cpp
@@ -189,7 +189,7 @@ struct LoopInvariantCodeMotion
bool interestingToMove(Expression* curr) {
// In theory we could consider blocks, but then heavy nesting of
// switch patterns would be heavy, and almost always pointless.
- if (curr->type != none || curr->is<Nop>() || curr->is<Block>() ||
+ if (curr->type != Type::none || curr->is<Nop>() || curr->is<Block>() ||
curr->is<Loop>()) {
return false;
}
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 8e04ed47f..276c50d9e 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -148,7 +148,7 @@ struct BreakValueDropper : public ControlFlowWalker<BreakValueDropper> {
if (curr->value && curr->name == origin) {
Builder builder(*getModule());
auto* value = curr->value;
- if (value->type == unreachable) {
+ if (value->type == Type::unreachable) {
// the break isn't even reached
replaceCurrent(value);
return;
@@ -172,7 +172,7 @@ struct BreakValueDropper : public ControlFlowWalker<BreakValueDropper> {
static bool hasUnreachableChild(Block* block) {
for (auto* test : block->list) {
- if (test->type == unreachable) {
+ if (test->type == Type::unreachable) {
return true;
}
}
@@ -184,7 +184,7 @@ static bool hasDeadCode(Block* block) {
auto& list = block->list;
auto size = list.size();
for (size_t i = 1; i < size; i++) {
- if (list[i - 1]->type == unreachable) {
+ if (list[i - 1]->type == Type::unreachable) {
return true;
}
}
@@ -437,13 +437,13 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
if (!block->name.is() && block->list.size() >= 2) {
// if we move around unreachable code, type changes could occur. avoid
// that, as anyhow it means we should have run dce before getting here
- if (curr->type == none && hasUnreachableChild(block)) {
+ if (curr->type == Type::none && hasUnreachableChild(block)) {
// moving the block to the outside would replace a none with an
// unreachable
return outer;
}
auto* back = block->list.back();
- if (back->type == unreachable) {
+ if (back->type == Type::unreachable) {
// curr is not reachable, dce could remove it; don't try anything
// fancy here
return outer;
diff --git a/src/passes/OptimizeAddedConstants.cpp b/src/passes/OptimizeAddedConstants.cpp
index a34d1b96d..f0c1ec2d9 100644
--- a/src/passes/OptimizeAddedConstants.cpp
+++ b/src/passes/OptimizeAddedConstants.cpp
@@ -213,7 +213,7 @@ private:
index = parent->getHelperIndex(set);
}
curr->offset = result.total;
- curr->ptr = Builder(*module).makeLocalGet(index, i32);
+ curr->ptr = Builder(*module).makeLocalGet(index, Type::i32);
return true;
}
}
@@ -304,7 +304,7 @@ struct OptimizeAddedConstants
return iter->second;
}
return helperIndexes[set] =
- Builder(*getModule()).addVar(getFunction(), i32);
+ Builder(*getModule()).addVar(getFunction(), Type::i32);
}
bool isPropagatable(LocalSet* set) { return propagatable.count(set); }
@@ -387,7 +387,7 @@ private:
}
auto* value = *target;
Builder builder(*module);
- *target = builder.makeLocalGet(index, i32);
+ *target = builder.makeLocalGet(index, Type::i32);
replaceCurrent(
builder.makeSequence(builder.makeLocalSet(index, value), curr));
}
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index edd6ba2b6..2372df462 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -54,9 +54,9 @@ template<typename LocalInfoProvider>
Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) {
if (auto* const_ = curr->dynCast<Const>()) {
switch (curr->type) {
- case i32:
+ case Type::i32:
return 32 - const_->value.countLeadingZeroes().geti32();
- case i64:
+ case Type::i64:
return 64 - const_->value.countLeadingZeroes().geti64();
default:
WASM_UNREACHABLE("invalid type");
@@ -179,11 +179,11 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) {
}
}
switch (curr->type) {
- case i32:
+ case Type::i32:
return 32;
- case i64:
+ case Type::i64:
return 64;
- case unreachable:
+ case Type::unreachable:
return 64; // not interesting, but don't crash
default:
WASM_UNREACHABLE("invalid type");
@@ -232,7 +232,7 @@ struct LocalScanner : PostWalker<LocalScanner> {
return;
}
auto type = getFunction()->getLocalType(curr->index);
- if (type != i32 && type != i64) {
+ if (type != Type::i32 && type != Type::i64) {
return;
}
// an integer var, worth processing
@@ -261,9 +261,9 @@ struct LocalScanner : PostWalker<LocalScanner> {
Index getBitsForType(Type type) {
switch (type) {
- case i32:
+ case Type::i32:
return 32;
- case i64:
+ case Type::i64:
return 64;
default:
return -1;
@@ -334,7 +334,7 @@ struct OptimizeInstructions
// might change (if might not be unreachable if just one arm is, for
// example). this optimization pass focuses on actually executing code. the
// only exceptions are control flow changes
- if (curr->type == unreachable && !curr->is<Break>() &&
+ if (curr->type == Type::unreachable && !curr->is<Break>() &&
!curr->is<Switch>() && !curr->is<If>()) {
return nullptr;
}
@@ -567,7 +567,7 @@ struct OptimizeInstructions
}
}
// math operations on a constant power of 2 right side can be optimized
- if (right->type == i32) {
+ if (right->type == Type::i32) {
uint32_t c = right->value.geti32();
if (IsPowerOf2(c)) {
if (binary->op == MulInt32) {
@@ -744,7 +744,7 @@ struct OptimizeInstructions
std::swap(iff->ifTrue, iff->ifFalse);
}
}
- if (iff->condition->type != unreachable &&
+ if (iff->condition->type != Type::unreachable &&
ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) {
// sides are identical, fold
// if we can replace the if with one arm, and no side effects in the
@@ -763,7 +763,7 @@ struct OptimizeInstructions
// the types diff. as the condition is reachable, that means the
// if must be concrete while the arm is not
assert(iff->type.isConcrete() &&
- iff->ifTrue->type == unreachable);
+ iff->ifTrue->type == Type::unreachable);
// emit a block with a forced type
auto* ret = builder.makeBlock();
if (needCondition) {
@@ -847,7 +847,7 @@ struct OptimizeInstructions
if (auto* binary = store->value->dynCast<Binary>()) {
if (binary->op == AndInt32) {
if (auto* right = binary->right->dynCast<Const>()) {
- if (right->type == i32) {
+ if (right->type == Type::i32) {
auto mask = right->value.geti32();
if ((store->bytes == 1 && mask == 0xff) ||
(store->bytes == 2 && mask == 0xffff)) {
@@ -866,7 +866,7 @@ struct OptimizeInstructions
} else if (auto* unary = store->value->dynCast<Unary>()) {
if (unary->op == WrapInt64) {
// instead of wrapping to 32, just store some of the bits in the i64
- store->valueType = i64;
+ store->valueType = Type::i64;
store->value = unary->value;
}
}
@@ -968,11 +968,11 @@ private:
return makeZeroExt(ext, Properties::getSignExtBits(binary));
}
} else if (auto* block = boolean->dynCast<Block>()) {
- if (block->type == i32 && block->list.size() > 0) {
+ if (block->type == Type::i32 && block->list.size() > 0) {
block->list.back() = optimizeBoolean(block->list.back());
}
} else if (auto* iff = boolean->dynCast<If>()) {
- if (iff->type == i32) {
+ if (iff->type == Type::i32) {
iff->ifTrue = optimizeBoolean(iff->ifTrue);
iff->ifFalse = optimizeBoolean(iff->ifFalse);
}
@@ -1469,7 +1469,7 @@ private:
case LtUInt32:
case GtSInt32:
case GtUInt32:
- return LiteralUtils::makeZero(i32, *getModule());
+ return LiteralUtils::makeZero(Type::i32, *getModule());
case AndInt32:
case OrInt32:
case AndInt64:
@@ -1485,7 +1485,7 @@ private:
case LeUInt64:
case GeSInt64:
case GeUInt64:
- return LiteralUtils::makeFromInt32(1, i32, *getModule());
+ return LiteralUtils::makeFromInt32(1, Type::i32, *getModule());
default:
return nullptr;
}
diff --git a/src/passes/PostAssemblyScript.cpp b/src/passes/PostAssemblyScript.cpp
index 4e41c8f08..eeb077ce9 100644
--- a/src/passes/PostAssemblyScript.cpp
+++ b/src/passes/PostAssemblyScript.cpp
@@ -88,8 +88,8 @@ struct AliasGraph : LocalGraph {
// consider a full retain pattern, which must also set a local.
static bool isRetainCall(Call* expr) {
// __retain(...)
- return expr->target == RETAIN && expr->type == i32 &&
- expr->operands.size() == 1 && expr->operands[0]->type == i32;
+ return expr->target == RETAIN && expr->type == Type::i32 &&
+ expr->operands.size() == 1 && expr->operands[0]->type == Type::i32;
}
// Tests if a local.set is considered to be a full retain pattern.
@@ -117,8 +117,8 @@ static bool isRetainLocation(Expression** expr) {
// consider a full release pattern, which must also get a local.
static bool isReleaseCall(Call* expr) {
// __release(...)
- return expr->target == RELEASE && expr->type == none &&
- expr->operands.size() == 1 && expr->operands[0]->type == i32;
+ return expr->target == RELEASE && expr->type == Type::none &&
+ expr->operands.size() == 1 && expr->operands[0]->type == Type::i32;
}
// Tests if the given location is that of a full release pattern. Note that
@@ -138,7 +138,7 @@ static bool isReleaseLocation(Expression** expr) {
// Tests if the given call calls any allocation function.
static bool isAllocCall(Call* expr) {
return (expr->target == ALLOC || expr->target == ALLOCARRAY) &&
- expr->type == i32;
+ expr->type == Type::i32;
}
// A pass that eliminates redundant retain and release calls.
diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp
index 85eb026f9..21393c1cf 100644
--- a/src/passes/Precompute.cpp
+++ b/src/passes/Precompute.cpp
@@ -199,7 +199,7 @@ struct Precompute
// this expression causes a return. if it's already a return, reuse the
// node
if (auto* ret = curr->dynCast<Return>()) {
- if (flow.value.type != none) {
+ if (flow.value.type != Type::none) {
// reuse a const value if there is one
if (ret->value) {
if (auto* value = ret->value->dynCast<Const>()) {
@@ -226,7 +226,7 @@ struct Precompute
if (auto* br = curr->dynCast<Break>()) {
br->name = flow.breakTo;
br->condition = nullptr;
- if (flow.value.type != none) {
+ if (flow.value.type != Type::none) {
// reuse a const value if there is one
if (br->value) {
if (auto* value = br->value->dynCast<Const>()) {
@@ -243,10 +243,11 @@ struct Precompute
br->finalize();
} else {
Builder builder(*getModule());
- replaceCurrent(builder.makeBreak(
- flow.breakTo,
- flow.value.type != none ? builder.makeConstExpression(flow.value)
- : nullptr));
+ replaceCurrent(
+ builder.makeBreak(flow.breakTo,
+ flow.value.type != Type::none
+ ? builder.makeConstExpression(flow.value)
+ : nullptr));
}
return;
}
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 549aa661d..106966ef1 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -89,7 +89,9 @@ std::ostream& operator<<(std::ostream& os, SigName sigName) {
// Printing "unreachable" as a instruction prefix type is not valid in wasm text
// format. Print something else to make it pass.
-static Type forceConcrete(Type type) { return type.isConcrete() ? type : i32; }
+static Type forceConcrete(Type type) {
+ return type.isConcrete() ? type : Type::i32;
+}
// Prints the internal contents of an expression: everything but
// the children.
@@ -186,7 +188,8 @@ struct PrintExpressionContents
o << ".atomic";
}
o << ".load";
- if (curr->type != unreachable && curr->bytes < curr->type.getByteSize()) {
+ if (curr->type != Type::unreachable &&
+ curr->bytes < curr->type.getByteSize()) {
if (curr->bytes == 1) {
o << '8';
} else if (curr->bytes == 2) {
@@ -212,7 +215,7 @@ struct PrintExpressionContents
o << ".atomic";
}
o << ".store";
- if (curr->bytes < 4 || (curr->valueType == i64 && curr->bytes < 8)) {
+ if (curr->bytes < 4 || (curr->valueType == Type::i64 && curr->bytes < 8)) {
if (curr->bytes == 1) {
o << '8';
} else if (curr->bytes == 2) {
@@ -233,7 +236,7 @@ struct PrintExpressionContents
}
static void printRMWSize(std::ostream& o, Type type, uint8_t bytes) {
prepareColor(o) << forceConcrete(type) << ".atomic.rmw";
- if (type != unreachable && bytes != type.getByteSize()) {
+ if (type != Type::unreachable && bytes != type.getByteSize()) {
if (bytes == 1) {
o << '8';
} else if (bytes == 2) {
@@ -269,7 +272,8 @@ struct PrintExpressionContents
o << "xchg";
break;
}
- if (curr->type != unreachable && curr->bytes != curr->type.getByteSize()) {
+ if (curr->type != Type::unreachable &&
+ curr->bytes != curr->type.getByteSize()) {
o << "_u";
}
restoreNormalColor(o);
@@ -281,7 +285,8 @@ struct PrintExpressionContents
prepareColor(o);
printRMWSize(o, curr->type, curr->bytes);
o << "cmpxchg";
- if (curr->type != unreachable && curr->bytes != curr->type.getByteSize()) {
+ if (curr->type != Type::unreachable &&
+ curr->bytes != curr->type.getByteSize()) {
o << "_u";
}
restoreNormalColor(o);
diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp
index 53a232dc1..8f83f8a8f 100644
--- a/src/passes/ReReloop.cpp
+++ b/src/passes/ReReloop.cpp
@@ -320,7 +320,7 @@ struct ReReloop final : public Pass {
// anywhere. add a return as needed
for (auto* cfgBlock : relooper->Blocks) {
auto* block = cfgBlock->Code->cast<Block>();
- if (cfgBlock->BranchesOut.empty() && block->type != unreachable) {
+ if (cfgBlock->BranchesOut.empty() && block->type != Type::unreachable) {
block->list.push_back(function->sig.results == Type::none
? (Expression*)builder->makeReturn()
: (Expression*)builder->makeUnreachable());
@@ -345,7 +345,7 @@ struct ReReloop final : public Pass {
relooper->Calculate(entry);
// render
{
- auto temp = builder->addVar(function, i32);
+ auto temp = builder->addVar(function, Type::i32);
CFG::RelooperBuilder builder(*module, temp);
function->body = relooper->Render(builder);
// if the function has a result, and the relooper emitted
diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp
index eebd97ae1..d758440f2 100644
--- a/src/passes/RemoveNonJSOps.cpp
+++ b/src/passes/RemoveNonJSOps.cpp
@@ -158,12 +158,12 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> {
// can actually implement) and then use reinterpretation to get the float
// back out.
switch (curr->type) {
- case f32:
- curr->type = i32;
+ case Type::f32:
+ curr->type = Type::i32;
replaceCurrent(builder->makeUnary(ReinterpretInt32, curr));
break;
- case f64:
- curr->type = i64;
+ case Type::f64:
+ curr->type = Type::i64;
replaceCurrent(builder->makeUnary(ReinterpretInt64, curr));
break;
default:
@@ -180,12 +180,12 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> {
// we can actually implement) and then use reinterpretation to store the
// right value.
switch (curr->valueType) {
- case f32:
- curr->valueType = i32;
+ case Type::f32:
+ curr->valueType = Type::i32;
curr->value = builder->makeUnary(ReinterpretFloat32, curr->value);
break;
- case f64:
- curr->valueType = i64;
+ case Type::f64:
+ curr->valueType = Type::i64;
curr->value = builder->makeUnary(ReinterpretFloat64, curr->value);
break;
default:
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index e0174934a..786fcaf67 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -37,7 +37,7 @@ static bool canTurnIfIntoBrIf(Expression* ifCondition,
Expression* brValue,
PassOptions& options) {
// if the if isn't even reached, this is all dead code anyhow
- if (ifCondition->type == unreachable) {
+ if (ifCondition->type == Type::unreachable) {
return false;
}
if (!brValue) {
@@ -104,7 +104,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
flows.push_back(currp);
} else if (curr->is<If>()) {
auto* iff = curr->cast<If>();
- if (iff->condition->type == unreachable) {
+ if (iff->condition->type == Type::unreachable) {
// avoid trying to optimize this, we never reach it anyhow
self->stopFlow();
return;
@@ -118,7 +118,8 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// there is no way to emit a proper type for one arm being
// none and the other flowing a value; and there is no way
// to flow a value from a none.
- if (iff->ifTrue->type == none || iff->ifFalse->type == none) {
+ if (iff->ifTrue->type == Type::none ||
+ iff->ifFalse->type == Type::none) {
self->removeValueFlow(ifTrueFlows);
self->stopValueFlow();
}
@@ -166,7 +167,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// invalid to represent as such.
auto size = list.size();
for (Index i = 0; i < size; i++) {
- if (i != size - 1 && list[i]->type == unreachable) {
+ if (i != size - 1 && list[i]->type == Type::unreachable) {
// No value flows out of this block.
self->stopValueFlow();
break;
@@ -283,17 +284,18 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
// great, we are in that case, optimize
Builder builder(*getModule());
- auto temp = builder.addVar(getFunction(), i32);
+ auto temp = builder.addVar(getFunction(), Type::i32);
Expression* z;
replaceCurrent(
z = builder.makeIf(
- builder.makeLocalTee(temp, curr->condition, i32),
- builder.makeIf(builder.makeBinary(EqInt32,
- builder.makeLocalGet(temp, i32),
- builder.makeConst(Literal(int32_t(
- curr->targets.size() - 1)))),
- builder.makeBreak(curr->targets.back()),
- builder.makeBreak(curr->default_)),
+ builder.makeLocalTee(temp, curr->condition, Type::i32),
+ builder.makeIf(
+ builder.makeBinary(
+ EqInt32,
+ builder.makeLocalGet(temp, Type::i32),
+ builder.makeConst(Literal(int32_t(curr->targets.size() - 1)))),
+ builder.makeBreak(curr->targets.back()),
+ builder.makeBreak(curr->default_)),
builder.makeBreak(curr->targets.front())));
}
}
@@ -318,7 +320,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// avoid one branch.
// If running the br's condition unconditionally is too expensive,
// give up.
- auto* zero = LiteralUtils::makeZero(i32, *getModule());
+ auto* zero = LiteralUtils::makeZero(Type::i32, *getModule());
if (tooCostlyToRunUnconditionally(
getPassOptions(), br->condition, zero)) {
return;
@@ -353,7 +355,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
auto* iff = (*currp)->dynCast<If>();
if (iff) {
- if (iff->condition->type == unreachable) {
+ if (iff->condition->type == Type::unreachable) {
// avoid trying to optimize this, we never reach it anyhow
return;
}
@@ -424,7 +426,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (!iff->ifFalse) {
// we need the ifTrue to break, so it cannot reach the code we want to
// move
- if (iff->ifTrue->type == unreachable) {
+ if (iff->ifTrue->type == Type::unreachable) {
iff->ifFalse = builder.stealSlice(block, i + 1, list.size());
iff->finalize();
block->finalize();
@@ -468,13 +470,13 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
return block;
};
- if (iff->ifTrue->type == unreachable) {
+ if (iff->ifTrue->type == Type::unreachable) {
iff->ifFalse = blockifyMerge(
iff->ifFalse, builder.stealSlice(block, i + 1, list.size()));
iff->finalize();
block->finalize();
return true;
- } else if (iff->ifFalse->type == unreachable) {
+ } else if (iff->ifFalse->type == Type::unreachable) {
iff->ifTrue = blockifyMerge(
iff->ifTrue, builder.stealSlice(block, i + 1, list.size()));
iff->finalize();
@@ -781,7 +783,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
auto* br1 = list[i]->dynCast<Break>();
// avoid unreachable brs, as they are dead code anyhow, and after
// merging them the outer scope could need type changes
- if (!br1 || !br1->condition || br1->type == unreachable) {
+ if (!br1 || !br1->condition || br1->type == Type::unreachable) {
continue;
}
assert(!br1->value);
@@ -792,7 +794,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
assert(!br2->value); // same target as previous, which has no value
// a br_if and then a br[_if] with the same target right after it
if (br2->condition) {
- if (shrink && br2->type != unreachable) {
+ if (shrink && br2->type != Type::unreachable) {
// Join adjacent br_ifs to the same target, making one br_if
// with a "selectified" condition that executes both.
if (!EffectAnalyzer(passOptions, br2->condition)
@@ -872,7 +874,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// type is unreachable that means it is not actually reached, which we
// can ignore.
if (br && br->condition && br->name == curr->name &&
- br->type != unreachable) {
+ br->type != Type::unreachable) {
if (BranchUtils::BranchSeeker::count(curr, curr->name) == 1) {
// no other breaks to that name, so we can do this
if (!drop) {
@@ -977,7 +979,8 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
auto tryToOptimize =
[&](Expression* one, Expression* two, bool flipCondition) {
- if (one->type == unreachable && two->type != unreachable) {
+ if (one->type == Type::unreachable &&
+ two->type != Type::unreachable) {
if (auto* br = one->dynCast<Break>()) {
if (ExpressionAnalyzer::isSimple(br)) {
// Wonderful, do it!
@@ -1130,7 +1133,7 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
if (!br->condition || br->value) {
return nullptr;
}
- if (br->type != none) {
+ if (br->type != Type::none) {
// no value, so can be unreachable or none. ignore unreachable ones,
// dce will clean it up
return nullptr;
diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp
index fc6706f3e..a9ad62820 100644
--- a/src/passes/SafeHeap.cpp
+++ b/src/passes/SafeHeap.cpp
@@ -71,7 +71,7 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> {
AccessInstrumenter* create() override { return new AccessInstrumenter; }
void visitLoad(Load* curr) {
- if (curr->type == unreachable) {
+ if (curr->type == Type::unreachable) {
return;
}
Builder builder(*getModule());
@@ -85,7 +85,7 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> {
}
void visitStore(Store* curr) {
- if (curr->type == unreachable) {
+ if (curr->type == Type::unreachable) {
return;
}
Builder builder(*getModule());
@@ -96,7 +96,7 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> {
builder.makeConst(Literal(int32_t(curr->offset))),
curr->value,
},
- none));
+ Type::none));
}
};
@@ -169,15 +169,16 @@ struct SafeHeap : public Pass {
void addGlobals(Module* module, FeatureSet features) {
// load funcs
Load load;
- for (auto type : {i32, i64, f32, f64, v128}) {
- if (type == v128 && !features.hasSIMD()) {
+ for (Type type : {Type::i32, Type::i64, Type::f32, Type::f64, Type::v128}) {
+ if (type == Type::v128 && !features.hasSIMD()) {
continue;
}
load.type = type;
for (Index bytes : {1, 2, 4, 8, 16}) {
load.bytes = bytes;
- if (bytes > type.getByteSize() || (type == f32 && bytes != 4) ||
- (type == f64 && bytes != 8) || (type == v128 && bytes != 16)) {
+ if (bytes > type.getByteSize() || (type == Type::f32 && bytes != 4) ||
+ (type == Type::f64 && bytes != 8) ||
+ (type == Type::v128 && bytes != 16)) {
continue;
}
for (auto signed_ : {true, false}) {
@@ -204,18 +205,19 @@ struct SafeHeap : public Pass {
}
// store funcs
Store store;
- for (auto valueType : {i32, i64, f32, f64, v128}) {
- if (valueType == v128 && !features.hasSIMD()) {
+ for (Type valueType :
+ {Type::i32, Type::i64, Type::f32, Type::f64, Type::v128}) {
+ if (valueType == Type::v128 && !features.hasSIMD()) {
continue;
}
store.valueType = valueType;
- store.type = none;
+ store.type = Type::none;
for (Index bytes : {1, 2, 4, 8, 16}) {
store.bytes = bytes;
if (bytes > valueType.getByteSize() ||
- (valueType == f32 && bytes != 4) ||
- (valueType == f64 && bytes != 8) ||
- (valueType == v128 && bytes != 16)) {
+ (valueType == Type::f32 && bytes != 4) ||
+ (valueType == Type::f64 && bytes != 8) ||
+ (valueType == Type::v128 && bytes != 16)) {
continue;
}
for (Index align : {1, 2, 4, 8, 16}) {
@@ -246,13 +248,14 @@ struct SafeHeap : public Pass {
func->name = name;
// pointer, offset
func->sig = Signature({Type::i32, Type::i32}, style.type);
- func->vars.push_back(i32); // pointer + offset
+ func->vars.push_back(Type::i32); // pointer + offset
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
2,
- builder.makeBinary(
- AddInt32, builder.makeLocalGet(0, i32), builder.makeLocalGet(1, i32))));
+ builder.makeBinary(AddInt32,
+ builder.makeLocalGet(0, Type::i32),
+ builder.makeLocalGet(1, Type::i32))));
// check for reading past valid memory: if pointer + offset + bytes
block->list.push_back(makeBoundsCheck(style.type, builder, 2, style.bytes));
// check proper alignment
@@ -262,7 +265,7 @@ struct SafeHeap : public Pass {
// do the load
auto* load = module->allocator.alloc<Load>();
*load = style; // basically the same as the template we are given!
- load->ptr = builder.makeLocalGet(2, i32);
+ load->ptr = builder.makeLocalGet(2, Type::i32);
Expression* last = load;
if (load->isAtomic && load->signed_) {
// atomic loads cannot be signed, manually sign it
@@ -285,13 +288,14 @@ struct SafeHeap : public Pass {
func->name = name;
// pointer, offset, value
func->sig = Signature({Type::i32, Type::i32, style.valueType}, Type::none);
- func->vars.push_back(i32); // pointer + offset
+ func->vars.push_back(Type::i32); // pointer + offset
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
3,
- builder.makeBinary(
- AddInt32, builder.makeLocalGet(0, i32), builder.makeLocalGet(1, i32))));
+ builder.makeBinary(AddInt32,
+ builder.makeLocalGet(0, Type::i32),
+ builder.makeLocalGet(1, Type::i32))));
// check for reading past valid memory: if pointer + offset + bytes
block->list.push_back(
makeBoundsCheck(style.valueType, builder, 3, style.bytes));
@@ -302,10 +306,10 @@ struct SafeHeap : public Pass {
// do the store
auto* store = module->allocator.alloc<Store>();
*store = style; // basically the same as the template we are given!
- store->ptr = builder.makeLocalGet(3, i32);
+ store->ptr = builder.makeLocalGet(3, Type::i32);
store->value = builder.makeLocalGet(2, style.valueType);
block->list.push_back(store);
- block->finalize(none);
+ block->finalize(Type::none);
func->body = block;
module->addFunction(func);
}
@@ -313,9 +317,9 @@ struct SafeHeap : public Pass {
Expression* makeAlignCheck(Address align, Builder& builder, Index local) {
return builder.makeIf(
builder.makeBinary(AndInt32,
- builder.makeLocalGet(local, i32),
+ builder.makeLocalGet(local, Type::i32),
builder.makeConst(Literal(int32_t(align - 1)))),
- builder.makeCall(alignfault, {}, none));
+ builder.makeCall(alignfault, {}, Type::none));
}
Expression*
@@ -324,30 +328,30 @@ struct SafeHeap : public Pass {
auto upperBound = options.lowMemoryUnused ? PassOptions::LowMemoryBound : 0;
Expression* brkLocation;
if (sbrk.is()) {
- brkLocation =
- builder.makeCall(sbrk, {builder.makeConst(Literal(int32_t(0)))}, i32);
+ brkLocation = builder.makeCall(
+ sbrk, {builder.makeConst(Literal(int32_t(0)))}, Type::i32);
} else {
Expression* sbrkPtr;
if (dynamicTopPtr.is()) {
- sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, i32);
+ sbrkPtr = builder.makeGlobalGet(dynamicTopPtr, Type::i32);
} else {
- sbrkPtr = builder.makeCall(getSbrkPtr, {}, i32);
+ sbrkPtr = builder.makeCall(getSbrkPtr, {}, Type::i32);
}
- brkLocation = builder.makeLoad(4, false, 0, 4, sbrkPtr, i32);
+ brkLocation = builder.makeLoad(4, false, 0, 4, sbrkPtr, Type::i32);
}
return builder.makeIf(
builder.makeBinary(
OrInt32,
builder.makeBinary(upperOp,
- builder.makeLocalGet(local, i32),
+ builder.makeLocalGet(local, Type::i32),
builder.makeConst(Literal(int32_t(upperBound)))),
builder.makeBinary(
GtUInt32,
builder.makeBinary(AddInt32,
- builder.makeLocalGet(local, i32),
+ builder.makeLocalGet(local, Type::i32),
builder.makeConst(Literal(int32_t(bytes)))),
brkLocation)),
- builder.makeCall(segfault, {}, none));
+ builder.makeCall(segfault, {}, Type::none));
}
};
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp
index a952f8a38..f7558aa83 100644
--- a/src/passes/SimplifyLocals.cpp
+++ b/src/passes/SimplifyLocals.cpp
@@ -421,7 +421,7 @@ struct SimplifyLocals
void optimizeLoopReturn(Loop* loop) {
// If there is a sinkable thing in an eligible loop, we can optimize
// it in a trivial way to the outside of the loop.
- if (loop->type != none) {
+ if (loop->type != Type::none) {
return;
}
if (sinkables.empty()) {
@@ -442,7 +442,7 @@ struct SimplifyLocals
block->list[block->list.size() - 1] = set->value;
*item = builder.makeNop();
block->finalize();
- assert(block->type != none);
+ assert(block->type != Type::none);
loop->finalize();
set->value = loop;
set->finalize();
@@ -584,7 +584,7 @@ struct SimplifyLocals
assert(iff->ifFalse);
// if this if already has a result, or is unreachable code, we have
// nothing to do
- if (iff->type != none) {
+ if (iff->type != Type::none) {
return;
}
// We now have the sinkables from both sides of the if, and can look
@@ -606,14 +606,16 @@ struct SimplifyLocals
Sinkables& ifFalse = sinkables;
Index goodIndex = -1;
bool found = false;
- if (iff->ifTrue->type == unreachable) {
- assert(iff->ifFalse->type != unreachable); // since the if type is none
+ if (iff->ifTrue->type == Type::unreachable) {
+ // since the if type is none
+ assert(iff->ifFalse->type != Type::unreachable);
if (!ifFalse.empty()) {
goodIndex = ifFalse.begin()->first;
found = true;
}
- } else if (iff->ifFalse->type == unreachable) {
- assert(iff->ifTrue->type != unreachable); // since the if type is none
+ } else if (iff->ifFalse->type == Type::unreachable) {
+ // since the if type is none
+ assert(iff->ifTrue->type != Type::unreachable);
if (!ifTrue.empty()) {
goodIndex = ifTrue.begin()->first;
found = true;
@@ -636,7 +638,7 @@ struct SimplifyLocals
// ensure we have a place to write the return values for, if not, we
// need another cycle
auto* ifTrueBlock = iff->ifTrue->dynCast<Block>();
- if (iff->ifTrue->type != unreachable) {
+ if (iff->ifTrue->type != Type::unreachable) {
if (!ifTrueBlock || ifTrueBlock->name.is() ||
ifTrueBlock->list.size() == 0 ||
!ifTrueBlock->list.back()->is<Nop>()) {
@@ -645,7 +647,7 @@ struct SimplifyLocals
}
}
auto* ifFalseBlock = iff->ifFalse->dynCast<Block>();
- if (iff->ifFalse->type != unreachable) {
+ if (iff->ifFalse->type != Type::unreachable) {
if (!ifFalseBlock || ifFalseBlock->name.is() ||
ifFalseBlock->list.size() == 0 ||
!ifFalseBlock->list.back()->is<Nop>()) {
@@ -654,24 +656,24 @@ struct SimplifyLocals
}
}
// all set, go
- if (iff->ifTrue->type != unreachable) {
+ if (iff->ifTrue->type != Type::unreachable) {
auto* ifTrueItem = ifTrue.at(goodIndex).item;
ifTrueBlock->list[ifTrueBlock->list.size() - 1] =
(*ifTrueItem)->template cast<LocalSet>()->value;
ExpressionManipulator::nop(*ifTrueItem);
ifTrueBlock->finalize();
- assert(ifTrueBlock->type != none);
+ assert(ifTrueBlock->type != Type::none);
}
- if (iff->ifFalse->type != unreachable) {
+ if (iff->ifFalse->type != Type::unreachable) {
auto* ifFalseItem = ifFalse.at(goodIndex).item;
ifFalseBlock->list[ifFalseBlock->list.size() - 1] =
(*ifFalseItem)->template cast<LocalSet>()->value;
ExpressionManipulator::nop(*ifFalseItem);
ifFalseBlock->finalize();
- assert(ifFalseBlock->type != none);
+ assert(ifFalseBlock->type != Type::none);
}
iff->finalize(); // update type
- assert(iff->type != none);
+ assert(iff->type != Type::none);
// finally, create a local.set on the iff itself
auto* newLocalSet =
Builder(*this->getModule()).makeLocalSet(goodIndex, iff);
@@ -703,7 +705,7 @@ struct SimplifyLocals
// arm into a one-sided if.
void optimizeIfReturn(If* iff, Expression** currp) {
// If this if is unreachable code, we have nothing to do.
- if (iff->type != none || iff->ifTrue->type != none) {
+ if (iff->type != Type::none || iff->ifTrue->type != Type::none) {
return;
}
// Anything sinkable is good for us.
@@ -726,14 +728,14 @@ struct SimplifyLocals
ifTrueBlock->list[ifTrueBlock->list.size() - 1] = set->value;
*item = builder.makeNop();
ifTrueBlock->finalize();
- assert(ifTrueBlock->type != none);
+ assert(ifTrueBlock->type != Type::none);
// Update the ifFalse side.
iff->ifFalse = builder.makeLocalGet(
set->index, this->getFunction()->getLocalType(set->index));
iff->finalize(); // update type
// Update the get count.
getCounter.num[set->index]++;
- assert(iff->type != none);
+ assert(iff->type != Type::none);
// Finally, reuse the local.set on the iff itself.
set->value = iff;
set->finalize();
diff --git a/src/passes/SpillPointers.cpp b/src/passes/SpillPointers.cpp
index 7458f5fbd..453510592 100644
--- a/src/passes/SpillPointers.cpp
+++ b/src/passes/SpillPointers.cpp
@@ -155,7 +155,7 @@ struct SpillPointers
Function* func,
Module* module) {
auto* call = *origin;
- if (call->type == unreachable) {
+ if (call->type == Type::unreachable) {
return; // the call is never reached anyhow, ignore
}
Builder builder(*module);
diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp
index e4aa55d68..a628468fb 100644
--- a/src/passes/StackIR.cpp
+++ b/src/passes/StackIR.cpp
@@ -88,7 +88,7 @@ private:
// We can remove this.
removeAt(i);
}
- } else if (inst->type == unreachable) {
+ } else if (inst->type == Type::unreachable) {
inUnreachableCode = true;
}
}
@@ -221,7 +221,7 @@ private:
// This is an actual regular value on the value stack.
values.push_back(null);
}
- } else if (inst->origin->is<LocalSet>() && inst->type == none) {
+ } else if (inst->origin->is<LocalSet>() && inst->type == Type::none) {
// This set is potentially optimizable later, add to stack.
values.push_back(i);
}
diff --git a/src/passes/TrapMode.cpp b/src/passes/TrapMode.cpp
index 9c855d8c1..f3cf3c63c 100644
--- a/src/passes/TrapMode.cpp
+++ b/src/passes/TrapMode.cpp
@@ -99,7 +99,7 @@ bool isTruncOpSigned(UnaryOp op) {
Function* generateBinaryFunc(Module& wasm, Binary* curr) {
BinaryOp op = curr->op;
Type type = curr->type;
- bool isI64 = type == i64;
+ bool isI64 = type == Type::i64;
Builder builder(wasm);
Expression* result = builder.makeBinary(
op, builder.makeLocalGet(0, type), builder.makeLocalGet(1, type));
@@ -145,7 +145,7 @@ Function* generateUnaryFunc(Module& wasm, Unary* curr) {
Type type = curr->value->type;
Type retType = curr->type;
UnaryOp truncOp = curr->op;
- bool isF64 = type == f64;
+ bool isF64 = type == Type::f64;
Builder builder(wasm);
@@ -276,12 +276,12 @@ Expression* makeTrappingUnary(Unary* curr,
// slow ffi If i64, there is no "JS" way to handle this, as no i64s in JS, so
// always clamp if we don't allow traps asm.js doesn't have unsigned
// f64-to-int, so just use the signed one.
- if (curr->type != i64 && mode == TrapMode::JS) {
+ if (curr->type != Type::i64 && mode == TrapMode::JS) {
// WebAssembly traps on float-to-int overflows, but asm.js wouldn't, so we
// must emulate that
ensureF64ToI64JSImport(trappingFunctions);
Expression* f64Value = ensureDouble(curr->value, wasm.allocator);
- return builder.makeCall(F64_TO_INT, {f64Value}, i32);
+ return builder.makeCall(F64_TO_INT, {f64Value}, Type::i32);
}
ensureUnaryFunc(curr, wasm, trappingFunctions);
diff --git a/src/passes/Untee.cpp b/src/passes/Untee.cpp
index 6e5fb489b..848e88a65 100644
--- a/src/passes/Untee.cpp
+++ b/src/passes/Untee.cpp
@@ -35,7 +35,7 @@ struct Untee : public WalkerPass<PostWalker<Untee>> {
void visitLocalSet(LocalSet* curr) {
if (curr->isTee()) {
- if (curr->value->type == unreachable) {
+ if (curr->value->type == Type::unreachable) {
// we don't reach the tee, just remove it
replaceCurrent(curr->value);
} else {
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 48a55ed89..a222b0159 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -56,7 +56,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
Expression* optimize(Expression* curr, bool resultUsed, bool typeMatters) {
auto type = curr->type;
// An unreachable node must not be changed.
- if (type == unreachable) {
+ if (type == Type::unreachable) {
return curr;
}
// We iterate on possible replacements. If a replacement changes the type,
@@ -226,7 +226,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
// example, code-folding can merge out identical zeros at the end of
// if arms).
optimized = LiteralUtils::makeZero(child->type, *getModule());
- } else if (child->type == unreachable) {
+ } else if (child->type == Type::unreachable) {
// Don't try to optimize out an unreachable child (dce can do that
// properly).
optimized = child;
@@ -245,7 +245,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
list[z] = nullptr;
}
// if this is unreachable, the rest is dead code
- if (list[z - skip]->type == unreachable && z < size - 1) {
+ if (list[z - skip]->type == Type::unreachable && z < size - 1) {
for (Index i = z - skip + 1; i < list.size(); i++) {
auto* remove = list[i];
if (remove) {
@@ -292,7 +292,7 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
return;
}
// if the condition is unreachable, just return it
- if (curr->condition->type == unreachable) {
+ if (curr->condition->type == Type::unreachable) {
typeUpdater.noteRecursiveRemoval(curr->ifTrue);
if (curr->ifFalse) {
typeUpdater.noteRecursiveRemoval(curr->ifFalse);
@@ -366,14 +366,14 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
BranchUtils::BranchSeeker seeker(block->name);
Expression* temp = block;
seeker.walk(temp);
- if (seeker.found && seeker.valueType != none) {
+ if (seeker.found && seeker.valueType != Type::none) {
canPop = false;
}
}
if (canPop) {
block->list.back() = last;
block->list.pop_back();
- block->type = none;
+ block->type = Type::none;
// we don't need the drop anymore, let's see what we have left in
// the block
if (block->list.size() > 1) {
@@ -394,16 +394,17 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
auto* iff = curr->value->dynCast<If>();
if (iff && iff->ifFalse && iff->type.isConcrete()) {
// reuse the drop in both cases
- if (iff->ifTrue->type == unreachable && iff->ifFalse->type.isConcrete()) {
+ if (iff->ifTrue->type == Type::unreachable &&
+ iff->ifFalse->type.isConcrete()) {
curr->value = iff->ifFalse;
iff->ifFalse = curr;
- iff->type = none;
+ iff->type = Type::none;
replaceCurrent(iff);
- } else if (iff->ifFalse->type == unreachable &&
+ } else if (iff->ifFalse->type == Type::unreachable &&
iff->ifTrue->type.isConcrete()) {
curr->value = iff->ifTrue;
iff->ifTrue = curr;
- iff->type = none;
+ iff->type = Type::none;
replaceCurrent(iff);
}
}