diff options
Diffstat (limited to 'src/passes')
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); } } |