diff options
Diffstat (limited to 'src')
31 files changed, 256 insertions, 188 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index ef19c32ff..97c079a34 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -734,7 +734,8 @@ private: return 2; case 8: return 3; - default: {} + default: { + } } abort(); return -1; // avoid warning @@ -1515,7 +1516,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { assert(params[i] == Type::f64 || curr->operands[i]->type == Type::unreachable); // overloaded, upgrade to f64 - switch (curr->operands[i]->type.getSingle()) { + switch (curr->operands[i]->type.getBasic()) { case Type::i32: curr->operands[i] = parent->builder.makeUnary( ConvertSInt32ToFloat64, curr->operands[i]); @@ -1524,7 +1525,9 @@ void Asm2WasmBuilder::processAsm(Ref ast) { curr->operands[i] = parent->builder.makeUnary(PromoteFloat32, curr->operands[i]); break; - default: {} // f64, unreachable, etc., are all good + default: { + // f64, unreachable, etc., are all good + } } } } @@ -1536,7 +1539,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) { if (importResults == Type::f64) { // we use a JS f64 value which is the most general, and convert to // it - switch (old.getSingle()) { + switch (old.getBasic()) { case Type::i32: { Unary* trunc = parent->builder.makeUnary(TruncSFloat64ToInt32, curr); diff --git a/src/asmjs/asm_v_wasm.cpp b/src/asmjs/asm_v_wasm.cpp index 98a6be046..75fc0506b 100644 --- a/src/asmjs/asm_v_wasm.cpp +++ b/src/asmjs/asm_v_wasm.cpp @@ -42,7 +42,8 @@ Type asmToWasmType(AsmType asmType) { } AsmType wasmToAsmType(Type type) { - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: return ASM_INT; case Type::f32: @@ -67,7 +68,8 @@ AsmType wasmToAsmType(Type type) { } char getSig(Type type) { - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: return 'i'; case Type::i64: diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 517ed42a6..2201f97bd 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -51,7 +51,8 @@ static_assert(sizeof(BinaryenLiteral) == sizeof(Literal), BinaryenLiteral toBinaryenLiteral(Literal x) { BinaryenLiteral ret; ret.type = x.type.getID(); - switch (x.type.getSingle()) { + TODO_SINGLE_COMPOUND(x.type); + switch (x.type.getBasic()) { case Type::i32: ret.i32 = x.geti32(); break; @@ -151,7 +152,7 @@ uint32_t BinaryenTypeArity(BinaryenType t) { return Type(t).size(); } void BinaryenTypeExpand(BinaryenType t, BinaryenType* buf) { const std::vector<Type>& types = Type(t).expand(); for (size_t i = 0; i < types.size(); ++i) { - buf[i] = types[i].getSingle(); + buf[i] = types[i].getID(); } } diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 41bca48d4..822fc5808 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -186,7 +186,7 @@ void ReFinalize::replaceUntaken(Expression* value, Expression* condition) { condition = builder.makeDrop(condition); } replacement = builder.makeSequence(value, condition); - assert(replacement->type.getSingle()); + assert(replacement->type.isBasic() && "Basic type expected"); } replaceCurrent(replacement); } diff --git a/src/ir/abstract.h b/src/ir/abstract.h index 687412455..f706e9972 100644 --- a/src/ir/abstract.h +++ b/src/ir/abstract.h @@ -61,7 +61,7 @@ enum Op { // you can provide i32 and Add and receive the specific opcode for a 32-bit // addition, AddInt32. If the op does not exist, it returns Invalid. inline UnaryOp getUnary(Type type, Op op) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { switch (op) { case EqZ: @@ -114,7 +114,7 @@ inline UnaryOp getUnary(Type type, Op op) { } inline BinaryOp getBinary(Type type, Op op) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { switch (op) { case Add: diff --git a/src/ir/bits.h b/src/ir/bits.h index e0bca8d87..20d97f13f 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -129,7 +129,7 @@ template<typename LocalInfoProvider = DummyLocalInfoProvider> Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider = nullptr) { if (auto* const_ = curr->dynCast<Const>()) { - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: return 32 - const_->value.countLeadingZeroes().geti32(); case Type::i64: @@ -256,7 +256,7 @@ Index getMaxBits(Expression* curr, return 8 * load->bytes; } } - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: return 32; case Type::i64: diff --git a/src/literal.h b/src/literal.h index c58dbb35c..5c72bf96c 100644 --- a/src/literal.h +++ b/src/literal.h @@ -81,33 +81,23 @@ public: bool isNone() const { return type == Type::none; } static Literal makeFromInt32(int32_t x, Type type) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(int32_t(x)); - break; case Type::i64: return Literal(int64_t(x)); - break; case Type::f32: return Literal(float(x)); - break; case Type::f64: return Literal(double(x)); - break; case Type::v128: return Literal(std::array<Literal, 4>{{Literal(x), Literal(int32_t(0)), Literal(int32_t(0)), Literal(int32_t(0))}}); - case Type::funcref: - case Type::externref: - case Type::nullref: - case Type::exnref: - case Type::none: - case Type::unreachable: + default: WASM_UNREACHABLE("unexpected type"); } - WASM_UNREACHABLE("unexpected type"); } static Literals makeZero(Type type); @@ -551,7 +541,8 @@ template<> struct less<wasm::Literal> { if (b.type < a.type) { return false; } - switch (a.type.getSingle()) { + TODO_SINGLE_COMPOUND(a.type); + switch (a.type.getBasic()) { case wasm::Type::i32: return a.geti32() < b.geti32(); case wasm::Type::f32: diff --git a/src/parsing.h b/src/parsing.h index fe2889a26..a3eab1af3 100644 --- a/src/parsing.h +++ b/src/parsing.h @@ -84,7 +84,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { ret->type = type; if (type.isFloat()) { if (s == _INFINITY) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: ret->value = Literal(std::numeric_limits<float>::infinity()); break; @@ -98,7 +98,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { return ret; } if (s == NEG_INFINITY) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: ret->value = Literal(-std::numeric_limits<float>::infinity()); break; @@ -112,7 +112,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { return ret; } if (s == _NAN) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: ret->value = Literal(float(std::nan(""))); break; @@ -137,7 +137,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { if (!(modifier ? positive[4] == '0' && positive[5] == 'x' : 1)) { throw ParseException("bad nan input"); } - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: { uint32_t pattern; if (modifier) { @@ -187,7 +187,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { return ret; } if (s == NEG_NAN) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: ret->value = Literal(float(-std::nan(""))); break; @@ -201,7 +201,7 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { return ret; } } - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { if ((str[0] == '0' && str[1] == 'x') || (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { diff --git a/src/passes/AlignmentLowering.cpp b/src/passes/AlignmentLowering.cpp index 26815b389..b12e49c4f 100644 --- a/src/passes/AlignmentLowering.cpp +++ b/src/passes/AlignmentLowering.cpp @@ -232,7 +232,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> { return; } Builder builder(*getModule()); - auto type = curr->type.getSingle(); + auto type = curr->type.getBasic(); Expression* replacement; switch (type) { default: @@ -303,7 +303,7 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> { // the operation is unaligned. return; } - auto type = curr->value->type.getSingle(); + auto type = curr->value->type.getBasic(); Expression* replacement; switch (type) { default: diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index 5009cd364..3cef0773c 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -77,7 +77,8 @@ private: } // measure the size of the constant Index size = 0; - switch (value.type.getSingle()) { + TODO_SINGLE_COMPOUND(value.type); + switch (value.type.getBasic()) { case Type::i32: { size = getWrittenSize(S32LEB(value.geti32())); break; diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 8ae0db839..9e455b0c8 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -44,7 +44,7 @@ static const int NUM_PARAMS = 16; // Converts a value to the ABI type of i64. static Expression* toABI(Expression* value, Module* module) { Builder builder(*module); - switch (value->type.getSingle()) { + switch (value->type.getBasic()) { case Type::i32: { value = builder.makeUnary(ExtendUInt32, value); break; @@ -88,7 +88,7 @@ static Expression* toABI(Expression* value, Module* module) { // Converts a value from the ABI type of i64 to the expected type static Expression* fromABI(Expression* value, Type type, Module* module) { Builder builder(*module); - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { value = builder.makeUnary(WrapInt64, value); break; diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index dfd0878f8..f66af87cc 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -84,7 +84,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { private: void freeIdx() { - auto& freeList = pass.freeTemps[ty.getSingle()]; + auto& freeList = pass.freeTemps[ty.getBasic()]; assert(std::find(freeList.begin(), freeList.end(), idx) == freeList.end()); freeList.push_back(idx); @@ -1525,7 +1525,7 @@ private: TempVar getTemp(Type ty = Type::i32) { Index ret; - auto& freeList = freeTemps[ty.getSingle()]; + auto& freeList = freeTemps[ty.getBasic()]; if (freeList.size() > 0) { ret = freeList.back(); freeList.pop_back(); diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp index 0bf22d29b..f95d169e9 100644 --- a/src/passes/InstrumentLocals.cpp +++ b/src/passes/InstrumentLocals.cpp @@ -76,7 +76,8 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { void visitLocalGet(LocalGet* curr) { Builder builder(*getModule()); Name import; - switch (curr->type.getSingle()) { + TODO_SINGLE_COMPOUND(curr->type); + switch (curr->type.getBasic()) { case Type::i32: import = get_i32; break; @@ -124,7 +125,8 @@ struct InstrumentLocals : public WalkerPass<PostWalker<InstrumentLocals>> { Builder builder(*getModule()); Name import; - switch (curr->value->type.getSingle()) { + TODO_SINGLE_COMPOUND(curr->value->type); + switch (curr->value->type.getBasic()) { case Type::i32: import = set_i32; break; diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp index 10574350b..fca3ff510 100644 --- a/src/passes/InstrumentMemory.cpp +++ b/src/passes/InstrumentMemory.cpp @@ -85,7 +85,7 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> { curr->ptr}, Type::i32); Name target; - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: target = load_val_i32; break; @@ -115,7 +115,7 @@ struct InstrumentMemory : public WalkerPass<PostWalker<InstrumentMemory>> { curr->ptr}, Type::i32); Name target; - switch (curr->value->type.getSingle()) { + switch (curr->value->type.getBasic()) { case Type::i32: target = store_val_i32; break; diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 7f66ca7ee..ad111433d 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -120,7 +120,8 @@ struct LocalScanner : PostWalker<LocalScanner> { Index getMaxBitsForLocal(LocalGet* get) { return getBitsForType(get->type); } Index getBitsForType(Type type) { - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: return 32; case Type::i64: @@ -1083,7 +1084,8 @@ private: } break; } - default: {} + default: { + } } } } diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp index 14b4f7a77..e2054a5d2 100644 --- a/src/passes/RemoveNonJSOps.cpp +++ b/src/passes/RemoveNonJSOps.cpp @@ -169,7 +169,7 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> { // Switch unaligned loads of floats to unaligned loads of integers (which we // can actually implement) and then use reinterpretation to get the float // back out. - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::f32: curr->type = Type::i32; replaceCurrent(builder->makeUnary(ReinterpretInt32, curr)); @@ -191,7 +191,7 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> { // Switch unaligned stores of floats to unaligned stores of integers (which // we can actually implement) and then use reinterpretation to store the // right value. - switch (curr->valueType.getSingle()) { + switch (curr->valueType.getBasic()) { case Type::f32: curr->valueType = Type::i32; curr->value = builder->makeUnary(ReinterpretFloat32, curr->value); diff --git a/src/shell-interface.h b/src/shell-interface.h index b4de73c6f..963832fed 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -99,7 +99,8 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { // add spectest globals ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) { if (import->module == SPECTEST && import->base.startsWith(GLOBAL)) { - switch (import->type.getSingle()) { + TODO_SINGLE_COMPOUND(import->type); + switch (import->type.getBasic()) { case Type::i32: globals[import->name] = {Literal(int32_t(666))}; break; diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index 95ccf2613..7fef9c208 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -315,7 +315,8 @@ private: } SmallVector<Type, 2> options; options.push_back(type); // includes itself - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::externref: if (wasm.features.hasExceptionHandling()) { options.push_back(Type::exnref); @@ -1315,7 +1316,7 @@ private: Expression* makeNonAtomicLoad(Type type) { auto offset = logify(get()); auto ptr = makePointer(); - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { bool signed_ = get() & 1; switch (upTo(3)) { @@ -1421,7 +1422,7 @@ private: auto offset = logify(get()); auto ptr = makePointer(); auto value = make(type); - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { switch (upTo(3)) { case 0: @@ -1581,7 +1582,7 @@ private: switch (upTo(4)) { case 0: { // totally random, entire range - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(get32()); case Type::i64: @@ -1626,7 +1627,7 @@ private: default: WASM_UNREACHABLE("invalid value"); } - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(int32_t(small)); case Type::i64: @@ -1649,7 +1650,7 @@ private: case 2: { // special values Literal value; - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: value = Literal(pick<int32_t>(0, @@ -1717,7 +1718,7 @@ private: case 3: { // powers of 2 Literal value; - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: value = Literal(int32_t(1) << upTo(32)); break; @@ -1794,9 +1795,11 @@ private: return makeTrivial(type); } - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { - switch (getSingleConcreteType().getSingle()) { + auto singleConcreteType = getSingleConcreteType(); + TODO_SINGLE_COMPOUND(singleConcreteType); + switch (singleConcreteType.getBasic()) { case Type::i32: { auto op = pick( FeatureOptions<UnaryOp>() @@ -2015,7 +2018,7 @@ private: return makeTrivial(type); } - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { switch (upTo(4)) { case 0: @@ -2319,7 +2322,7 @@ private: } } Index bytes; - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: { switch (upTo(3)) { case 0: @@ -2410,7 +2413,7 @@ private: Expression* makeSIMDExtract(Type type) { auto op = static_cast<SIMDExtractOp>(0); - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: op = pick(ExtractLaneSVecI8x16, ExtractLaneUVecI8x16, diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index a77dfc43f..3a674e495 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -32,7 +32,8 @@ static std::string generateSpecWrapper(Module& wasm) { exp->name.str + "\" "; for (Type param : func->sig.params.expand()) { // zeros in arguments TODO more? - switch (param.getSingle()) { + TODO_SINGLE_COMPOUND(param); + switch (param.getBasic()) { case Type::i32: ret += "(i32.const 0)"; break; diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 029b9092d..e0491c0db 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -578,9 +578,11 @@ struct Reducer continue; // no conversion } Expression* fixed = nullptr; - switch (curr->type.getSingle()) { + TODO_SINGLE_COMPOUND(curr->type); + switch (curr->type.getBasic()) { case Type::i32: { - switch (child->type.getSingle()) { + TODO_SINGLE_COMPOUND(child->type); + switch (child->type.getBasic()) { case Type::i32: WASM_UNREACHABLE("invalid type"); case Type::i64: @@ -605,7 +607,8 @@ struct Reducer break; } case Type::i64: { - switch (child->type.getSingle()) { + TODO_SINGLE_COMPOUND(child->type); + switch (child->type.getBasic()) { case Type::i32: fixed = builder->makeUnary(ExtendSInt32, child); break; @@ -630,7 +633,8 @@ struct Reducer break; } case Type::f32: { - switch (child->type.getSingle()) { + TODO_SINGLE_COMPOUND(child->type); + switch (child->type.getBasic()) { case Type::i32: fixed = builder->makeUnary(ConvertSInt32ToFloat32, child); break; @@ -655,7 +659,8 @@ struct Reducer break; } case Type::f64: { - switch (child->type.getSingle()) { + TODO_SINGLE_COMPOUND(child->type); + switch (child->type.getBasic()) { case Type::i32: fixed = builder->makeUnary(ConvertSInt32ToFloat64, child); break; diff --git a/src/tools/wasm2c-wrapper.h b/src/tools/wasm2c-wrapper.h index b3205c6fe..eae92ad60 100644 --- a/src/tools/wasm2c-wrapper.h +++ b/src/tools/wasm2c-wrapper.h @@ -123,7 +123,8 @@ int main(int argc, char** argv) { if (result != Type::none) { ret += std::string("printf(\"[fuzz-exec] note result: ") + exp->name.str + " => "; - switch (result.getSingle()) { + TODO_SINGLE_COMPOUND(result); + switch (result.getBasic()) { case Type::i32: ret += "%d\\n\", "; break; @@ -146,7 +147,8 @@ int main(int argc, char** argv) { auto params = func->sig.params.expand(); auto wasm2cSignature = [](Type type) { - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::none: return 'v'; case Type::i32: diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 24e4037e7..fb78336d0 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -18,13 +18,13 @@ // wasm2js console tool // +#include "wasm2js.h" #include "optimization-options.h" #include "pass.h" #include "support/colors.h" #include "support/command-line.h" #include "support/file.h" #include "wasm-s-parser.h" -#include "wasm2js.h" using namespace cashew; using namespace wasm; @@ -123,7 +123,8 @@ static void traversePrePost(Ref node, } static void traversePost(Ref node, std::function<void(Ref)> visit) { - traversePrePost(node, [](Ref node) {}, visit); + traversePrePost( + node, [](Ref node) {}, visit); } static void replaceInPlace(Ref target, Ref value) { @@ -604,7 +605,8 @@ Ref AssertionEmitter::emitAssertReturnFunc(Builder& wasmBuilder, Expression* expected = sexpBuilder.parseExpression(e[2]); Type resType = expected->type; actual->type = resType; - switch (resType.getSingle()) { + TODO_SINGLE_COMPOUND(resType); + switch (resType.getBasic()) { case Type::i32: body = wasmBuilder.makeBinary(EqInt32, actual, expected); break; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ba3b4038a..ab9ee5152 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -941,7 +941,8 @@ enum FeaturePrefix { inline S32LEB binaryType(Type type) { int ret = 0; - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { // None only used for block signatures. TODO: Separate out? case Type::none: ret = BinaryConsts::EncodedType::Empty; diff --git a/src/wasm-builder.h b/src/wasm-builder.h index e41bd769c..9ee98949a 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -622,7 +622,8 @@ public: // Make a constant expression. This might be a wasm Const, or something // else of constant value like ref.null. Expression* makeConstantExpression(Literal value) { - switch (value.type.getSingle()) { + TODO_SINGLE_COMPOUND(value.type); + switch (value.type.getBasic()) { case Type::nullref: return makeRefNull(); case Type::funcref: @@ -799,7 +800,8 @@ public: } Literal value; // TODO: reuse node conditionally when possible for literals - switch (curr->type.getSingle()) { + TODO_SINGLE_COMPOUND(curr->type); + switch (curr->type.getBasic()) { case Type::i32: value = Literal(int32_t(0)); break; diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index a61f549c7..4f0d22e58 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -1602,7 +1602,7 @@ public: // the default impls for load and store switch on the sizes. you can either // customize load/store, or the sub-functions which they call virtual Literal load(Load* load, Address addr) { - switch (load->type.getSingle()) { + switch (load->type.getBasic()) { case Type::i32: { switch (load->bytes) { case 1: @@ -1653,7 +1653,7 @@ public: WASM_UNREACHABLE("invalid type"); } virtual void store(Store* store, Address addr, Literal value) { - switch (store->valueType.getSingle()) { + switch (store->valueType.getBasic()) { case Type::i32: { switch (store->bytes) { case 1: diff --git a/src/wasm-type.h b/src/wasm-type.h index b0cfa4094..31c915620 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -21,6 +21,14 @@ #include <ostream> #include <vector> +// TODO: At various code locations we were assuming that single types are basic +// types, but this is going to change with the introduction of the compound +// Signature, Struct and Array types that will be single but not basic. To +// prepare for this change, the following macro marks affected code locations. +#define TODO_SINGLE_COMPOUND(type) \ + assert(!type.isMulti() && "Unexpected multi-value type"); \ + assert(!type.isCompound() && "TODO: handle compound types"); + namespace wasm { class Type { @@ -64,16 +72,47 @@ public: const std::vector<Type>& expand() const; // Predicates + // Compound Concrete + // Type Basic │ Single│ + // ╒═════════════╦═│═╤═│═╤═│═╤═│═╤═══════╕ + // │ none ║ x │ │ │ │ │ + // │ unreachable ║ x │ │ │ │ │ + // ├─────────────╫───┼───┼───┼───┤───────┤ + // │ i32 ║ x │ │ x │ x │ I │ ┐ Number + // │ i64 ║ x │ │ x │ x │ I │ │ I_nteger + // │ f32 ║ x │ │ x │ x │ F │ │ F_loat + // │ f64 ║ x │ │ x │ x │ F │ │ V_ector + // │ v128 ║ x │ │ x │ x │ V │ ┘ + // ├─────────────╫───┼───┼───┼───┤───────┤ + // │ funcref ║ x │ │ x │ x │ f │ ┐ Ref + // │ externref ║ x │ │ x │ x │ │ │ f_unc + // │ nullref ║ x │ │ x │ x │ │ │ + // │ exnref ║ x │ │ x │ x │ │ │ + // ├─────────────╫───┼───┼───┼───┤───────┤ │ + // │ Signature ║ │ x │ x │ x │ f │ │ ┐ + // │ Struct ║ │ x │ x │ x │ │ │ │ TODO (GC) + // │ Array ║ │ x │ x │ x │ │ ┘ ┘ + // │ Multi ║ │ x │ │ x │ │ + // └─────────────╨───┴───┴───┴───┴───────┘ + constexpr bool isBasic() const { return id <= _last_value_type; } + constexpr bool isCompound() const { return id > _last_value_type; } constexpr bool isSingle() const { + // TODO: Compound types Signature, Struct and Array are single return id >= i32 && id <= _last_value_type; } - constexpr bool isMulti() const { return id > _last_value_type; } + constexpr bool isMulti() const { + // TODO: Compound types Signature, Struct and Array are not multi + return id > _last_value_type; + } constexpr bool isConcrete() const { return id >= i32; } constexpr bool isInteger() const { return id == i32 || id == i64; } constexpr bool isFloat() const { return id == f32 || id == f64; } constexpr bool isVector() const { return id == v128; }; constexpr bool isNumber() const { return id >= i32 && id <= v128; } - constexpr bool isRef() const { return id >= funcref && id <= exnref; } + constexpr bool isRef() const { + // TODO: Compound types Signature, Struct and Array are ref + return id >= funcref && id <= exnref; + } private: template<bool (Type::*pred)() const> bool hasPredicate() { @@ -90,8 +129,8 @@ public: bool hasRef() { return hasPredicate<&Type::isRef>(); } constexpr uint64_t getID() const { return id; } - constexpr ValueType getSingle() const { - assert(!isMulti() && "Unexpected multivalue type"); + constexpr ValueType getBasic() const { + assert(isBasic() && "Basic type expected"); return static_cast<ValueType>(id); } diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index f0a065c45..699d3ea63 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -37,8 +37,8 @@ Literal::Literal(const Literal& other) { *this = other; } Literal& Literal::operator=(const Literal& other) { type = other.type; - assert(!type.isMulti()); - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: case Type::f32: i32 = other.i32; @@ -153,7 +153,7 @@ Literal Literal::castToI64() { } int64_t Literal::getInteger() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return i32; case Type::i64: @@ -164,7 +164,7 @@ int64_t Literal::getInteger() const { } double Literal::getFloat() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return getf32(); case Type::f64: @@ -176,7 +176,8 @@ double Literal::getFloat() const { void Literal::getBits(uint8_t (&buf)[16]) const { memset(buf, 0, 16); - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: case Type::f32: memcpy(buf, &i32, sizeof(i32)); @@ -317,7 +318,8 @@ void Literal::printVec128(std::ostream& o, const std::array<uint8_t, 16>& v) { std::ostream& operator<<(std::ostream& o, Literal literal) { prepareMinorColor(o); - switch (literal.type.getSingle()) { + TODO_SINGLE_COMPOUND(literal.type); + switch (literal.type.getBasic()) { case Type::none: o << "?"; break; @@ -558,7 +560,7 @@ Literal Literal::truncSatToUI64() const { } Literal Literal::eqz() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return eq(Literal(int32_t(0))); case Type::i64: @@ -580,7 +582,7 @@ Literal Literal::eqz() const { } Literal Literal::neg() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(-uint32_t(i32)); case Type::i64: @@ -602,7 +604,7 @@ Literal Literal::neg() const { } Literal Literal::abs() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(std::abs(i32)); case Type::i64: @@ -624,7 +626,7 @@ Literal Literal::abs() const { } Literal Literal::ceil() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(std::ceil(getf32())); case Type::f64: @@ -635,7 +637,7 @@ Literal Literal::ceil() const { } Literal Literal::floor() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(std::floor(getf32())); case Type::f64: @@ -646,7 +648,7 @@ Literal Literal::floor() const { } Literal Literal::trunc() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(std::trunc(getf32())); case Type::f64: @@ -657,7 +659,7 @@ Literal Literal::trunc() const { } Literal Literal::nearbyint() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(std::nearbyint(getf32())); case Type::f64: @@ -668,7 +670,7 @@ Literal Literal::nearbyint() const { } Literal Literal::sqrt() const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(std::sqrt(getf32())); case Type::f64: @@ -707,7 +709,7 @@ Literal Literal::demote() const { } Literal Literal::add(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) + uint32_t(other.i32)); case Type::i64: @@ -729,7 +731,7 @@ Literal Literal::add(const Literal& other) const { } Literal Literal::sub(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) - uint32_t(other.i32)); case Type::i64: @@ -822,7 +824,7 @@ Literal Literal::subSatUI16(const Literal& other) const { } Literal Literal::mul(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) * uint32_t(other.i32)); case Type::i64: @@ -844,7 +846,7 @@ Literal Literal::mul(const Literal& other) const { } Literal Literal::div(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: { float lhs = getf32(), rhs = other.getf32(); float sign = std::signbit(lhs) == std::signbit(rhs) ? 0.f : -0.f; @@ -923,7 +925,7 @@ Literal Literal::div(const Literal& other) const { } Literal Literal::divS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 / other.i32); case Type::i64: @@ -934,7 +936,7 @@ Literal Literal::divS(const Literal& other) const { } Literal Literal::divU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) / uint32_t(other.i32)); case Type::i64: @@ -945,7 +947,7 @@ Literal Literal::divU(const Literal& other) const { } Literal Literal::remS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 % other.i32); case Type::i64: @@ -956,7 +958,7 @@ Literal Literal::remS(const Literal& other) const { } Literal Literal::remU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) % uint32_t(other.i32)); case Type::i64: @@ -984,7 +986,7 @@ Literal Literal::avgrUInt(const Literal& other) const { } Literal Literal::and_(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 & other.i32); case Type::i64: @@ -995,7 +997,7 @@ Literal Literal::and_(const Literal& other) const { } Literal Literal::or_(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 | other.i32); case Type::i64: @@ -1006,7 +1008,7 @@ Literal Literal::or_(const Literal& other) const { } Literal Literal::xor_(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 ^ other.i32); case Type::i64: @@ -1017,7 +1019,7 @@ Literal Literal::xor_(const Literal& other) const { } Literal Literal::shl(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) << Bits::getEffectiveShifts(other.i32, Type::i32)); @@ -1030,7 +1032,7 @@ Literal Literal::shl(const Literal& other) const { } Literal Literal::shrS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 >> Bits::getEffectiveShifts(other.i32, Type::i32)); case Type::i64: @@ -1041,7 +1043,7 @@ Literal Literal::shrS(const Literal& other) const { } Literal Literal::shrU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) >> Bits::getEffectiveShifts(other.i32, Type::i32)); @@ -1054,7 +1056,7 @@ Literal Literal::shrU(const Literal& other) const { } Literal Literal::rotL(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(RotateLeft(uint32_t(i32), uint32_t(other.i32))); case Type::i64: @@ -1065,7 +1067,7 @@ Literal Literal::rotL(const Literal& other) const { } Literal Literal::rotR(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(RotateRight(uint32_t(i32), uint32_t(other.i32))); case Type::i64: @@ -1076,7 +1078,7 @@ Literal Literal::rotR(const Literal& other) const { } Literal Literal::eq(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 == other.i32); case Type::i64: @@ -1098,7 +1100,7 @@ Literal Literal::eq(const Literal& other) const { } Literal Literal::ne(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 != other.i32); case Type::i64: @@ -1120,7 +1122,7 @@ Literal Literal::ne(const Literal& other) const { } Literal Literal::ltS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 < other.i32); case Type::i64: @@ -1131,7 +1133,7 @@ Literal Literal::ltS(const Literal& other) const { } Literal Literal::ltU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) < uint32_t(other.i32)); case Type::i64: @@ -1142,7 +1144,7 @@ Literal Literal::ltU(const Literal& other) const { } Literal Literal::lt(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(getf32() < other.getf32()); case Type::f64: @@ -1153,7 +1155,7 @@ Literal Literal::lt(const Literal& other) const { } Literal Literal::leS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 <= other.i32); case Type::i64: @@ -1164,7 +1166,7 @@ Literal Literal::leS(const Literal& other) const { } Literal Literal::leU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) <= uint32_t(other.i32)); case Type::i64: @@ -1175,7 +1177,7 @@ Literal Literal::leU(const Literal& other) const { } Literal Literal::le(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(getf32() <= other.getf32()); case Type::f64: @@ -1186,7 +1188,7 @@ Literal Literal::le(const Literal& other) const { } Literal Literal::gtS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 > other.i32); case Type::i64: @@ -1197,7 +1199,7 @@ Literal Literal::gtS(const Literal& other) const { } Literal Literal::gtU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) > uint32_t(other.i32)); case Type::i64: @@ -1208,7 +1210,7 @@ Literal Literal::gtU(const Literal& other) const { } Literal Literal::gt(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(getf32() > other.getf32()); case Type::f64: @@ -1219,7 +1221,7 @@ Literal Literal::gt(const Literal& other) const { } Literal Literal::geS(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(i32 >= other.i32); case Type::i64: @@ -1230,7 +1232,7 @@ Literal Literal::geS(const Literal& other) const { } Literal Literal::geU(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: return Literal(uint32_t(i32) >= uint32_t(other.i32)); case Type::i64: @@ -1241,7 +1243,7 @@ Literal Literal::geU(const Literal& other) const { } Literal Literal::ge(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal(getf32() >= other.getf32()); case Type::f64: @@ -1252,7 +1254,7 @@ Literal Literal::ge(const Literal& other) const { } Literal Literal::min(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: { auto l = getf32(), r = other.getf32(); if (l == r && l == 0) { @@ -1295,7 +1297,7 @@ Literal Literal::min(const Literal& other) const { } Literal Literal::max(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: { auto l = getf32(), r = other.getf32(); if (l == r && l == 0) { @@ -1338,7 +1340,7 @@ Literal Literal::max(const Literal& other) const { } Literal Literal::pmin(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: case Type::f64: return other.lt(*this).geti32() ? other : *this; @@ -1348,7 +1350,7 @@ Literal Literal::pmin(const Literal& other) const { } Literal Literal::pmax(const Literal& other) const { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: case Type::f64: return this->lt(other).geti32() ? other : *this; @@ -1359,7 +1361,7 @@ Literal Literal::pmax(const Literal& other) const { Literal Literal::copysign(const Literal& other) const { // operate on bits directly, to avoid signalling bit being set on a float - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::f32: return Literal((i32 & 0x7fffffff) | (other.i32 & 0x80000000)).castToF32(); break; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 90113bb7f..19a4590e3 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -134,7 +134,7 @@ void BinaryInstWriter::visitGlobalSet(GlobalSet* curr) { void BinaryInstWriter::visitLoad(Load* curr) { if (!curr->isAtomic) { - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -197,7 +197,7 @@ void BinaryInstWriter::visitLoad(Load* curr) { } } else { o << int8_t(BinaryConsts::AtomicPrefix); - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -244,7 +244,7 @@ void BinaryInstWriter::visitLoad(Load* curr) { void BinaryInstWriter::visitStore(Store* curr) { if (!curr->isAtomic) { - switch (curr->valueType.getSingle()) { + switch (curr->valueType.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -300,7 +300,7 @@ void BinaryInstWriter::visitStore(Store* curr) { } } else { o << int8_t(BinaryConsts::AtomicPrefix); - switch (curr->valueType.getSingle()) { + switch (curr->valueType.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -348,7 +348,7 @@ void BinaryInstWriter::visitAtomicRMW(AtomicRMW* curr) { #define CASE_FOR_OP(Op) \ case Op: \ - switch (curr->type.getSingle()) { \ + switch (curr->type.getBasic()) { \ case Type::i32: \ switch (curr->bytes) { \ case 1: \ @@ -404,7 +404,7 @@ void BinaryInstWriter::visitAtomicRMW(AtomicRMW* curr) { void BinaryInstWriter::visitAtomicCmpxchg(AtomicCmpxchg* curr) { o << int8_t(BinaryConsts::AtomicPrefix); - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: switch (curr->bytes) { case 1: @@ -446,7 +446,7 @@ void BinaryInstWriter::visitAtomicCmpxchg(AtomicCmpxchg* curr) { void BinaryInstWriter::visitAtomicWait(AtomicWait* curr) { o << int8_t(BinaryConsts::AtomicPrefix); - switch (curr->expectedType.getSingle()) { + switch (curr->expectedType.getBasic()) { case Type::i32: { o << int8_t(BinaryConsts::I32AtomicWait); emitMemoryAccess(4, 4, curr->offset); @@ -668,7 +668,7 @@ void BinaryInstWriter::visitMemoryFill(MemoryFill* curr) { } void BinaryInstWriter::visitConst(Const* curr) { - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { o << int8_t(BinaryConsts::I32Const) << S32LEB(curr->value.geti32()); break; diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index c8d8a94c5..5db04b40d 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -92,7 +92,7 @@ std::unordered_map<std::vector<Type>, uintptr_t> indices = { void Type::init(const std::vector<Type>& types) { #ifndef NDEBUG for (Type t : types) { - assert(t.isSingle() && t.isConcrete()); + assert(!t.isMulti() && t.isConcrete()); } #endif @@ -136,18 +136,21 @@ const std::vector<Type>& Type::expand() const { bool Type::operator<(const Type& other) const { const std::vector<Type>& these = expand(); const std::vector<Type>& others = other.expand(); - return std::lexicographical_compare( - these.begin(), - these.end(), - others.begin(), - others.end(), - [](const Type& a, const Type& b) { return a.getSingle() < b.getSingle(); }); + return std::lexicographical_compare(these.begin(), + these.end(), + others.begin(), + others.end(), + [](const Type& a, const Type& b) { + TODO_SINGLE_COMPOUND(a); + TODO_SINGLE_COMPOUND(b); + return a.getBasic() < b.getBasic(); + }); } unsigned Type::getByteSize() const { // TODO: alignment? auto getSingleByteSize = [](Type t) { - switch (t.getSingle()) { + switch (t.getBasic()) { case Type::i32: case Type::f32: return 4; @@ -167,21 +170,19 @@ unsigned Type::getByteSize() const { WASM_UNREACHABLE("invalid type"); }; - if (isSingle()) { - return getSingleByteSize(*this); - } - - unsigned size = 0; - for (auto t : expand()) { - size += getSingleByteSize(t); + if (isMulti()) { + unsigned size = 0; + for (auto t : expand()) { + size += getSingleByteSize(t); + } + return size; } - return size; + return getSingleByteSize(*this); } Type Type::reinterpret() const { - assert(isSingle() && "reinterpretType only works with single types"); Type singleType = *expand().begin(); - switch (singleType.getSingle()) { + switch (singleType.getBasic()) { case Type::i32: return f32; case Type::i64: @@ -204,7 +205,8 @@ Type Type::reinterpret() const { FeatureSet Type::getFeatures() const { auto getSingleFeatures = [](Type t) -> FeatureSet { - switch (t.getSingle()) { + TODO_SINGLE_COMPOUND(t); + switch (t.getBasic()) { case Type::v128: return FeatureSet::SIMD; case Type::funcref: @@ -218,15 +220,14 @@ FeatureSet Type::getFeatures() const { } }; - if (isSingle()) { - return getSingleFeatures(*this); - } - - FeatureSet feats = FeatureSet::Multivalue; - for (Type t : expand()) { - feats |= getSingleFeatures(t); + if (isMulti()) { + FeatureSet feats = FeatureSet::Multivalue; + for (Type t : expand()) { + feats |= getSingleFeatures(t); + } + return feats; } - return feats; + return getSingleFeatures(*this); } Type Type::get(unsigned byteSize, bool float_) { @@ -355,7 +356,8 @@ std::ostream& operator<<(std::ostream& os, Type type) { } os << ')'; } else { - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::none: os << "none"; break; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 5f37560e7..4921dafdd 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -172,7 +172,7 @@ struct ValidationInfo { Expression* curr, const char* text, Function* func = nullptr) { - switch (ty.getSingle()) { + switch (ty.getBasic()) { case Type::i32: case Type::i64: case Type::unreachable: { @@ -1236,7 +1236,7 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) { void FunctionValidator::validateMemBytes(uint8_t bytes, Type type, Expression* curr) { - switch (type.getSingle()) { + switch (type.getBasic()) { case Type::i32: shouldBeTrue(bytes == 1 || bytes == 2 || bytes == 4, curr, @@ -1770,12 +1770,12 @@ void FunctionValidator::visitSelect(Select* curr) { curr, "select condition must be valid"); if (curr->ifTrue->type != Type::unreachable) { - shouldBeTrue( - curr->ifTrue->type.isSingle(), curr, "select value may not be a tuple"); + shouldBeFalse( + curr->ifTrue->type.isMulti(), curr, "select value may not be a tuple"); } if (curr->ifFalse->type != Type::unreachable) { - shouldBeTrue( - curr->ifFalse->type.isSingle(), curr, "select value may not be a tuple"); + shouldBeFalse( + curr->ifFalse->type.isMulti(), curr, "select value may not be a tuple"); } if (curr->type != Type::unreachable) { shouldBeTrue(Type::isSubType(curr->ifTrue->type, curr->type), @@ -2055,7 +2055,8 @@ void FunctionValidator::validateAlignment( } } shouldBeTrue(align <= bytes, curr, "alignment must not exceed natural"); - switch (type.getSingle()) { + TODO_SINGLE_COMPOUND(type); + switch (type.getBasic()) { case Type::i32: case Type::f32: { shouldBeTrue(align <= 4, curr, "alignment must not exceed natural"); @@ -2159,8 +2160,8 @@ static void validateImports(Module& module, ValidationInfo& info) { info.shouldBeFalse( curr->mutable_, curr->name, "Imported global cannot be mutable"); } - info.shouldBeTrue( - curr->type.isSingle(), curr->name, "Imported global cannot be tuple"); + info.shouldBeFalse( + curr->type.isMulti(), curr->name, "Imported global cannot be tuple"); }); } @@ -2189,8 +2190,8 @@ static void validateExports(Module& module, ValidationInfo& info) { info.shouldBeFalse( g->mutable_, g->name, "Exported global cannot be mutable"); } - info.shouldBeTrue( - g->type.isSingle(), g->name, "Exported global cannot be tuple"); + info.shouldBeFalse( + g->type.isMulti(), g->name, "Exported global cannot be tuple"); } } } diff --git a/src/wasm2js.h b/src/wasm2js.h index 8d233eb95..c06d90180 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -151,11 +151,12 @@ public: // Get a temp var. IString getTemp(Type type, Function* func) { IString ret; - if (frees[type.getSingle()].size() > 0) { - ret = frees[type.getSingle()].back(); - frees[type.getSingle()].pop_back(); + TODO_SINGLE_COMPOUND(type); + if (frees[type.getBasic()].size() > 0) { + ret = frees[type.getBasic()].back(); + frees[type.getBasic()].pop_back(); } else { - size_t index = temps[type.getSingle()]++; + size_t index = temps[type.getBasic()]++; ret = IString((std::string("wasm2js_") + type.toString() + "$" + std::to_string(index)) .c_str(), @@ -169,7 +170,8 @@ public: // Free a temp var. void freeTemp(Type type, IString temp) { - frees[type.getSingle()].push_back(temp); + TODO_SINGLE_COMPOUND(type); + frees[type.getBasic()].push_back(temp); } // Generates a mangled name from `name` within the specified scope. @@ -639,7 +641,8 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) { void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) { if (auto* const_ = global->init->dynCast<Const>()) { Ref theValue; - switch (const_->type.getSingle()) { + TODO_SINGLE_COMPOUND(const_->type); + switch (const_->type.getBasic()) { case Type::i32: { theValue = ValueBuilder::makeInt(const_->value.geti32()); break; @@ -656,7 +659,9 @@ void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) { ValueBuilder::makeDouble(const_->value.getf64()), ASM_DOUBLE); break; } - default: { assert(false && "Top const type not supported"); } + default: { + assert(false && "Top const type not supported"); + } } Ref theVar = ValueBuilder::makeVar(); ast->push_back(theVar); @@ -1240,7 +1245,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, // normal load Ref ptr = makePointer(curr->ptr, curr->offset); Ref ret; - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -1343,7 +1348,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Ref ptr = makePointer(curr->ptr, curr->offset); Ref value = visit(curr->value, EXPRESSION_RESULT); Ref ret; - switch (curr->valueType.getSingle()) { + switch (curr->valueType.getBasic()) { case Type::i32: { switch (curr->bytes) { case 1: @@ -1391,7 +1396,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Ref visitDrop(Drop* curr) { return visit(curr->value, NO_RESULT); } Ref visitConst(Const* curr) { - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: return ValueBuilder::makeInt(curr->value.geti32()); // An i64 argument translates to two actual arguments to asm.js @@ -1431,7 +1436,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Ref visitUnary(Unary* curr) { // normal unary - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { switch (curr->op) { case ClzInt32: { @@ -1612,7 +1617,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Ref left = visit(curr->left, EXPRESSION_RESULT); Ref right = visit(curr->right, EXPRESSION_RESULT); Ref ret; - switch (curr->type.getSingle()) { + switch (curr->type.getBasic()) { case Type::i32: { switch (curr->op) { case AddInt32: |