summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm.h11
-rw-r--r--src/asmjs/asm_v_wasm.cpp6
-rw-r--r--src/binaryen-c.cpp5
-rw-r--r--src/ir/ReFinalize.cpp2
-rw-r--r--src/ir/abstract.h4
-rw-r--r--src/ir/bits.h4
-rw-r--r--src/literal.h17
-rw-r--r--src/parsing.h12
-rw-r--r--src/passes/AlignmentLowering.cpp4
-rw-r--r--src/passes/ConstHoisting.cpp3
-rw-r--r--src/passes/FuncCastEmulation.cpp4
-rw-r--r--src/passes/I64ToI32Lowering.cpp4
-rw-r--r--src/passes/InstrumentLocals.cpp6
-rw-r--r--src/passes/InstrumentMemory.cpp4
-rw-r--r--src/passes/OptimizeInstructions.cpp6
-rw-r--r--src/passes/RemoveNonJSOps.cpp4
-rw-r--r--src/shell-interface.h3
-rw-r--r--src/tools/fuzzing.h27
-rw-r--r--src/tools/spec-wrapper.h3
-rw-r--r--src/tools/wasm-reduce.cpp15
-rw-r--r--src/tools/wasm2c-wrapper.h6
-rw-r--r--src/tools/wasm2js.cpp8
-rw-r--r--src/wasm-binary.h3
-rw-r--r--src/wasm-builder.h6
-rw-r--r--src/wasm-interpreter.h4
-rw-r--r--src/wasm-type.h47
-rw-r--r--src/wasm/literal.cpp100
-rw-r--r--src/wasm/wasm-stack.cpp16
-rw-r--r--src/wasm/wasm-type.cpp58
-rw-r--r--src/wasm/wasm-validator.cpp23
-rw-r--r--src/wasm2js.h29
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: