diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-05-03 22:01:14 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-05-03 22:01:14 -0700 |
commit | c7d7083920ddd9ff7d1a44577287b8ecc048a221 (patch) | |
tree | 1eb9e0cd2e50566b62f65171ccc35b29f8ca5c4d /src | |
parent | 5b2adeb4b2a66dfcda7667ce7a4c27ec49c62b1b (diff) | |
download | binaryen-c7d7083920ddd9ff7d1a44577287b8ecc048a221.tar.gz binaryen-c7d7083920ddd9ff7d1a44577287b8ecc048a221.tar.bz2 binaryen-c7d7083920ddd9ff7d1a44577287b8ecc048a221.zip |
Harmonize the internal opcodes with the binary format (#433)
* harmonize the internal opcodes with the binary format, so they clearly parallel, and also this helps us avoid needing the type to disambiguate
* comment on GetLocal in C API
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm.h | 12 | ||||
-rw-r--r-- | src/binaryen-c.cpp | 34 | ||||
-rw-r--r-- | src/binaryen-c.h | 44 | ||||
-rw-r--r-- | src/passes/Print.cpp | 30 | ||||
-rw-r--r-- | src/passes/Vacuum.cpp | 2 | ||||
-rw-r--r-- | src/s2wasm.h | 22 | ||||
-rw-r--r-- | src/wasm-binary.h | 70 | ||||
-rw-r--r-- | src/wasm-builder.h | 62 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 32 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 10 | ||||
-rw-r--r-- | src/wasm-validator.h | 30 | ||||
-rw-r--r-- | src/wasm.h | 10 | ||||
-rw-r--r-- | src/wasm2asm.h | 6 |
13 files changed, 228 insertions, 136 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h index 974a06bf3..fa35211a4 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1101,7 +1101,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { auto ret = process(ast[2]); // we are a +() coercion if (ret->type == i32) { auto conv = allocator.alloc<Unary>(); - conv->op = isUnsignedCoercion(ast[2]) ? ConvertUInt32 : ConvertSInt32; + conv->op = isUnsignedCoercion(ast[2]) ? ConvertUInt32ToFloat64 : ConvertSInt32ToFloat64; conv->value = ret; conv->type = WasmType::f64; return conv; @@ -1149,7 +1149,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { if (imprecise) { auto ret = allocator.alloc<Unary>(); ret->value = process(ast[2][2]); - ret->op = ret->value->type == f64 ? TruncSFloat64 : TruncSFloat32; // imprecise, because this wasm thing might trap, while asm.js never would + ret->op = ret->value->type == f64 ? TruncSFloat64ToInt32 : TruncSFloat32ToInt32; // imprecise, because this wasm thing might trap, while asm.js never would ret->type = WasmType::i32; return ret; } else { @@ -1233,7 +1233,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { if (ret->value->type == f64) { ret->op = DemoteFloat64; } else if (ret->value->type == i32) { - ret->op = ConvertSInt32; + ret->op = ConvertSInt32ToFloat32; } else if (ret->value->type == f32) { return ret->value; } else if (ret->value->type == none) { // call, etc. @@ -1564,7 +1564,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { Ref writtenValue = ast[1][3]; if (writeType == ASM_INT && (readType == ASM_FLOAT || readType == ASM_DOUBLE)) { auto conv = allocator.alloc<Unary>(); - conv->op = ReinterpretInt; + conv->op = ReinterpretInt32; conv->value = process(writtenValue); conv->type = WasmType::f32; if (readType == ASM_DOUBLE) { @@ -1577,11 +1577,11 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { return conv; } else if (writeType == ASM_FLOAT && readType == ASM_INT) { auto conv = allocator.alloc<Unary>(); - conv->op = ReinterpretFloat; + conv->op = ReinterpretFloat32; conv->value = process(writtenValue); if (conv->value->type == f64) { // this has an implicit f64->f32 in the write to memory - conv->value = builder.makeUnary(DemoteFloat64, conv->value, f32); + conv->value = builder.makeUnary(DemoteFloat64, conv->value); } conv->type = WasmType::i32; return conv; diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f80c2be50..35baa8c35 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -108,18 +108,28 @@ BinaryenOp BinaryenEqZ(void) { return EqZ; } BinaryenOp BinaryenExtendSInt32(void) { return ExtendSInt32; } BinaryenOp BinaryenExtentUInt32(void) { return ExtendUInt32; } BinaryenOp BinaryenWrapInt64(void) { return WrapInt64; } -BinaryenOp BinaryenTruncSFloat32(void) { return TruncSFloat32; } -BinaryenOp BinaryenTruncUFloat32(void) { return TruncUFloat32; } -BinaryenOp BinaryenTruncSFloat64(void) { return TruncSFloat64; } -BinaryenOp BinaryenTruncUFloat64(void) { return TruncUFloat64; } -BinaryenOp BinaryenReinterpretFloat(void) { return ReinterpretFloat; } -BinaryenOp BinaryenConvertSInt32(void) { return ConvertSInt32; } -BinaryenOp BinaryenConvertUInt32(void) { return ConvertUInt32; } -BinaryenOp BinaryenConvertSInt64(void) { return ConvertSInt64; } -BinaryenOp BinaryenConvertUInt64(void) { return ConvertUInt64; } +BinaryenOp BinaryenTruncSFloat32ToInt32(void) { return TruncSFloat32ToInt32; } +BinaryenOp BinaryenTruncSFloat32ToInt64(void) { return TruncSFloat32ToInt64; } +BinaryenOp BinaryenTruncUFloat32ToInt32(void) { return TruncUFloat32ToInt32; } +BinaryenOp BinaryenTruncUFloat32ToInt64(void) { return TruncUFloat32ToInt64; } +BinaryenOp BinaryenTruncSFloat64ToInt32(void) { return TruncSFloat64ToInt32; } +BinaryenOp BinaryenTruncSFloat64ToInt64(void) { return TruncSFloat64ToInt64; } +BinaryenOp BinaryenTruncUFloat64ToInt32(void) { return TruncUFloat64ToInt32; } +BinaryenOp BinaryenTruncUFloat64ToInt64(void) { return TruncUFloat64ToInt64; } +BinaryenOp BinaryenReinterpretFloat32(void) { return ReinterpretFloat32; } +BinaryenOp BinaryenReinterpretFloat64(void) { return ReinterpretFloat64; } +BinaryenOp BinaryenConvertSInt32ToFloat32(void) { return ConvertSInt32ToFloat32; } +BinaryenOp BinaryenConvertSInt32ToFloat64(void) { return ConvertSInt32ToFloat64; } +BinaryenOp BinaryenConvertUInt32ToFloat32(void) { return ConvertUInt32ToFloat32; } +BinaryenOp BinaryenConvertUInt32ToFloat64(void) { return ConvertUInt32ToFloat64; } +BinaryenOp BinaryenConvertSInt64ToFloat32(void) { return ConvertSInt64ToFloat32; } +BinaryenOp BinaryenConvertSInt64ToFloat64(void) { return ConvertSInt64ToFloat64; } +BinaryenOp BinaryenConvertUInt64ToFloat32(void) { return ConvertUInt64ToFloat32; } +BinaryenOp BinaryenConvertUInt64ToFloat64(void) { return ConvertUInt64ToFloat64; } BinaryenOp BinaryenPromoteFloat32(void) { return PromoteFloat32; } BinaryenOp BinaryenDemoteFloat64(void) { return DemoteFloat64; } -BinaryenOp BinaryenReinterpretInt(void) { return ReinterpretInt; } +BinaryenOp BinaryenReinterpretInt32(void) { return ReinterpretInt32; } +BinaryenOp BinaryenReinterpretInt64(void) { return ReinterpretInt64; } BinaryenOp BinaryenAdd(void) { return Add; } BinaryenOp BinaryenSub(void) { return Sub; } BinaryenOp BinaryenMul(void) { return Mul; } @@ -261,8 +271,8 @@ BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, ui BinaryenExpressionRef BinaryenConst(BinaryenModuleRef module, BinaryenLiteral value) { return Builder(*((Module*)module)).makeConst(fromBinaryenLiteral(value)); } -BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value, BinaryenType type) { - return Builder(*((Module*)module)).makeUnary(UnaryOp(op), (Expression*)value, WasmType(type)); +BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value) { + return Builder(*((Module*)module)).makeUnary(UnaryOp(op), (Expression*)value); } BinaryenExpressionRef BinaryenBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef left, BinaryenExpressionRef right) { return Builder(*((Module*)module)).makeBinary(BinaryOp(op), (Expression*)left, (Expression*)right); diff --git a/src/binaryen-c.h b/src/binaryen-c.h index 475c65613..09eda1458 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -104,6 +104,8 @@ struct BinaryenLiteral BinaryenLiteralFloat64Bits(int64_t x); // // Some expressions have optional parameters, like Return may not // return a value. You can supply a NULL pointer in those cases. +// +// For more information, see wasm.h typedef int32_t BinaryenOp; @@ -121,18 +123,28 @@ BinaryenOp BinaryenEqZ(void); BinaryenOp BinaryenExtendSInt32(void); BinaryenOp BinaryenExtentUInt32(void); BinaryenOp BinaryenWrapInt64(void); -BinaryenOp BinaryenTruncSFloat32(void); -BinaryenOp BinaryenTruncUFloat32(void); -BinaryenOp BinaryenTruncSFloat64(void); -BinaryenOp BinaryenTruncUFloat64(void); -BinaryenOp BinaryenReinterpretFloat(void); -BinaryenOp BinaryenConvertSInt32(void); -BinaryenOp BinaryenConvertUInt32(void); -BinaryenOp BinaryenConvertSInt64(void); -BinaryenOp BinaryenConvertUInt64(void); +BinaryenOp BinaryenTruncSFloat32ToInt32(void); +BinaryenOp BinaryenTruncSFloat32ToInt64(void); +BinaryenOp BinaryenTruncUFloat32ToInt32(void); +BinaryenOp BinaryenTruncUFloat32ToInt64(void); +BinaryenOp BinaryenTruncSFloat64ToInt32(void); +BinaryenOp BinaryenTruncSFloat64ToInt64(void); +BinaryenOp BinaryenTruncUFloat64ToInt32(void); +BinaryenOp BinaryenTruncUFloat64ToInt64(void); +BinaryenOp BinaryenReinterpretFloat32(void); +BinaryenOp BinaryenReinterpretFloat64(void); +BinaryenOp BinaryenConvertSInt32ToFloat32(void); +BinaryenOp BinaryenConvertSInt32ToFloat64(void); +BinaryenOp BinaryenConvertUInt32ToFloat32(void); +BinaryenOp BinaryenConvertUInt32ToFloat64(void); +BinaryenOp BinaryenConvertSInt64ToFloat32(void); +BinaryenOp BinaryenConvertSInt64ToFloat64(void); +BinaryenOp BinaryenConvertUInt64ToFloat32(void); +BinaryenOp BinaryenConvertUInt64ToFloat64(void); BinaryenOp BinaryenPromoteFloat32(void); BinaryenOp BinaryenDemoteFloat64(void); -BinaryenOp BinaryenReinterpretInt(void); +BinaryenOp BinaryenReinterpretInt32(void); +BinaryenOp BinaryenReinterpretInt64(void); BinaryenOp BinaryenAdd(void); BinaryenOp BinaryenSub(void); BinaryenOp BinaryenMul(void); @@ -186,12 +198,22 @@ BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, const char **name BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands); BinaryenExpressionRef BinaryenCallImport(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands); BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenFunctionTypeRef type); +// GetLocal: Note the 'type' parameter. It might seem redundant, since the +// local at that index must have a type. However, this API lets you +// build code "top-down": create a node, then its parents, and so +// on, and finally create the function at the end. (Note that in fact +// you do not mention a function when creating ExpressionRefs, only +// a module.) And since GetLocal is a leaf node, we need to be told +// its type. (Other nodes detect their type either from their +// type or their opcode, or failing that, their children. But +// GetLocal has no children, it is where a "stream" of type info +// begins.) BinaryenExpressionRef BinaryenGetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenType type); BinaryenExpressionRef BinaryenSetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value); BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenType type, BinaryenExpressionRef ptr); BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr, BinaryenExpressionRef value); BinaryenExpressionRef BinaryenConst(BinaryenModuleRef module, struct BinaryenLiteral value); -BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value, BinaryenType type); +BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value); BinaryenExpressionRef BinaryenBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef left, BinaryenExpressionRef right); BinaryenExpressionRef BinaryenSelect(BinaryenModuleRef module, BinaryenExpressionRef condition, BinaryenExpressionRef ifTrue, BinaryenExpressionRef ifFalse); // Return: value can be NULL diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 1a62de4f3..85ecd9724 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -299,18 +299,28 @@ struct PrintSExpression : public Visitor<PrintSExpression> { case ExtendSInt32: o << "extend_s/i32"; break; case ExtendUInt32: o << "extend_u/i32"; break; case WrapInt64: o << "wrap/i64"; break; - case TruncSFloat32: o << "trunc_s/f32"; break; - case TruncUFloat32: o << "trunc_u/f32"; break; - case TruncSFloat64: o << "trunc_s/f64"; break; - case TruncUFloat64: o << "trunc_u/f64"; break; - case ReinterpretFloat: o << "reinterpret/" << (curr->type == i64 ? "f64" : "f32"); break; - case ConvertUInt32: o << "convert_u/i32"; break; - case ConvertSInt32: o << "convert_s/i32"; break; - case ConvertUInt64: o << "convert_u/i64"; break; - case ConvertSInt64: o << "convert_s/i64"; break; + case TruncSFloat32ToInt32: + case TruncSFloat32ToInt64: o << "trunc_s/f32"; break; + case TruncUFloat32ToInt32: + case TruncUFloat32ToInt64: o << "trunc_u/f32"; break; + case TruncSFloat64ToInt32: + case TruncSFloat64ToInt64: o << "trunc_s/f64"; break; + case TruncUFloat64ToInt32: + case TruncUFloat64ToInt64: o << "trunc_u/f64"; break; + case ReinterpretFloat32: + case ReinterpretFloat64: o << "reinterpret/" << (curr->type == i64 ? "f64" : "f32"); break; + case ConvertUInt32ToFloat32: + case ConvertUInt32ToFloat64: o << "convert_u/i32"; break; + case ConvertSInt32ToFloat32: + case ConvertSInt32ToFloat64: o << "convert_s/i32"; break; + case ConvertUInt64ToFloat32: + case ConvertUInt64ToFloat64: o << "convert_u/i64"; break; + case ConvertSInt64ToFloat32: + case ConvertSInt64ToFloat64: o << "convert_s/i64"; break; case PromoteFloat32: o << "promote/f32"; break; case DemoteFloat64: o << "demote/f64"; break; - case ReinterpretInt: o << "reinterpret/" << (curr->type == f64 ? "i64" : "i32"); break; + case ReinterpretInt32: + case ReinterpretInt64: o << "reinterpret/" << (curr->type == f64 ? "i64" : "i32"); break; default: abort(); } incIndent(); diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp index dd88fa0eb..f9aba7051 100644 --- a/src/passes/Vacuum.cpp +++ b/src/passes/Vacuum.cpp @@ -71,7 +71,7 @@ struct Vacuum : public WalkerPass<PostWalker<Vacuum, Visitor<Vacuum>>> { } else if (curr->ifTrue->is<Nop>()) { curr->ifTrue = curr->ifFalse; curr->ifFalse = nullptr; - curr->condition = Builder(*getModule()).makeUnary(EqZ, curr->condition, curr->condition->type); + curr->condition = Builder(*getModule()).makeUnary(EqZ, curr->condition); } } if (!curr->ifFalse) { diff --git a/src/s2wasm.h b/src/s2wasm.h index 56d96dde2..941779ae5 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -757,10 +757,10 @@ class S2WasmBuilder { } } else if (match("call")) makeCall(type); - else if (match("convert_s/i32")) makeUnary(UnaryOp::ConvertSInt32, type); - else if (match("convert_u/i32")) makeUnary(UnaryOp::ConvertUInt32, type); - else if (match("convert_s/i64")) makeUnary(UnaryOp::ConvertSInt64, type); - else if (match("convert_u/i64")) makeUnary(UnaryOp::ConvertUInt64, type); + else if (match("convert_s/i32")) makeUnary(type == f32 ? UnaryOp::ConvertSInt32ToFloat32 : UnaryOp::ConvertSInt32ToFloat64, type); + else if (match("convert_u/i32")) makeUnary(type == f32 ? UnaryOp::ConvertUInt32ToFloat32 : UnaryOp::ConvertUInt32ToFloat64, type); + else if (match("convert_s/i64")) makeUnary(type == f32 ? UnaryOp::ConvertSInt64ToFloat32 : UnaryOp::ConvertSInt64ToFloat64, type); + else if (match("convert_u/i64")) makeUnary(type == f32 ? UnaryOp::ConvertUInt64ToFloat32 : UnaryOp::ConvertUInt64ToFloat64, type); else if (match("clz")) makeUnary(UnaryOp::Clz, type); else if (match("ctz")) makeUnary(UnaryOp::Ctz, type); else if (match("copysign")) makeBinary(BinaryOp::CopySign, type); @@ -838,8 +838,10 @@ class S2WasmBuilder { case 'r': { if (match("rem_s")) makeBinary(BinaryOp::RemS, type); else if (match("rem_u")) makeBinary(BinaryOp::RemU, type); - else if (match("reinterpret/i32") || match("reinterpret/i64")) makeUnary(UnaryOp::ReinterpretInt, type); - else if (match("reinterpret/f32") || match("reinterpret/f64")) makeUnary(UnaryOp::ReinterpretFloat, type); + else if (match("reinterpret/i32")) makeUnary(UnaryOp::ReinterpretInt32, type); + else if (match("reinterpret/i64")) makeUnary(UnaryOp::ReinterpretInt64, type); + else if (match("reinterpret/f32")) makeUnary(UnaryOp::ReinterpretFloat32, type); + else if (match("reinterpret/f64")) makeUnary(UnaryOp::ReinterpretFloat64, type); else if (match("rotl")) makeBinary(BinaryOp::RotL, type); else if (match("rotr")) makeBinary(BinaryOp::RotR, type); else abort_on("type.r"); @@ -857,10 +859,10 @@ class S2WasmBuilder { break; } case 't': { - if (match("trunc_s/f32")) makeUnary(UnaryOp::TruncSFloat32, type); - else if (match("trunc_u/f32")) makeUnary(UnaryOp::TruncUFloat32, type); - else if (match("trunc_s/f64")) makeUnary(UnaryOp::TruncSFloat64, type); - else if (match("trunc_u/f64")) makeUnary(UnaryOp::TruncUFloat64, type); + if (match("trunc_s/f32")) makeUnary(type == i32 ? UnaryOp::TruncSFloat32ToInt32 : UnaryOp::TruncSFloat32ToInt64, type); + else if (match("trunc_u/f32")) makeUnary(type == i32 ? UnaryOp::TruncUFloat32ToInt32 : UnaryOp::TruncUFloat32ToInt64, type); + else if (match("trunc_s/f64")) makeUnary(type == i32 ? UnaryOp::TruncSFloat64ToInt32 : UnaryOp::TruncSFloat64ToInt64, type); + else if (match("trunc_u/f64")) makeUnary(type == i32 ? UnaryOp::TruncUFloat64ToInt32 : UnaryOp::TruncUFloat64ToInt64, type); else if (match("trunc")) makeUnary(UnaryOp::Trunc, type); else abort_on("type.t"); break; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 53afb6028..c889f1418 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1025,18 +1025,28 @@ public: case ExtendSInt32: o << int8_t(BinaryConsts::I64STruncI32); break; case ExtendUInt32: o << int8_t(BinaryConsts::I64UTruncI32); break; case WrapInt64: o << int8_t(BinaryConsts::I32ConvertI64); break; - case TruncUFloat32: o << int8_t(curr->type == i32 ? BinaryConsts::I32UTruncF32 : BinaryConsts::I64UTruncF32); break; - case TruncSFloat32: o << int8_t(curr->type == i32 ? BinaryConsts::I32STruncF32 : BinaryConsts::I64STruncF32); break; - case TruncUFloat64: o << int8_t(curr->type == i32 ? BinaryConsts::I32UTruncF64 : BinaryConsts::I64UTruncF64); break; - case TruncSFloat64: o << int8_t(curr->type == i32 ? BinaryConsts::I32STruncF64 : BinaryConsts::I64STruncF64); break; - case ConvertUInt32: o << int8_t(curr->type == f32 ? BinaryConsts::F32UConvertI32 : BinaryConsts::F64UConvertI32); break; - case ConvertSInt32: o << int8_t(curr->type == f32 ? BinaryConsts::F32SConvertI32 : BinaryConsts::F64SConvertI32); break; - case ConvertUInt64: o << int8_t(curr->type == f32 ? BinaryConsts::F32UConvertI64 : BinaryConsts::F64UConvertI64); break; - case ConvertSInt64: o << int8_t(curr->type == f32 ? BinaryConsts::F32SConvertI64 : BinaryConsts::F64SConvertI64); break; + case TruncUFloat32ToInt32: o << int8_t(BinaryConsts::I32UTruncF32); break; + case TruncUFloat32ToInt64: o << int8_t(BinaryConsts::I64UTruncF32); break; + case TruncSFloat32ToInt32: o << int8_t(BinaryConsts::I32STruncF32); break; + case TruncSFloat32ToInt64: o << int8_t(BinaryConsts::I64STruncF32); break; + case TruncUFloat64ToInt32: o << int8_t(BinaryConsts::I32UTruncF64); break; + case TruncUFloat64ToInt64: o << int8_t(BinaryConsts::I64UTruncF64); break; + case TruncSFloat64ToInt32: o << int8_t(BinaryConsts::I32STruncF64); break; + case TruncSFloat64ToInt64: o << int8_t(BinaryConsts::I64STruncF64); break; + case ConvertUInt32ToFloat32: o << int8_t(BinaryConsts::F32UConvertI32); break; + case ConvertUInt32ToFloat64: o << int8_t(BinaryConsts::F64UConvertI32); break; + case ConvertSInt32ToFloat32: o << int8_t(BinaryConsts::F32SConvertI32); break; + case ConvertSInt32ToFloat64: o << int8_t(BinaryConsts::F64SConvertI32); break; + case ConvertUInt64ToFloat32: o << int8_t(BinaryConsts::F32UConvertI64); break; + case ConvertUInt64ToFloat64: o << int8_t(BinaryConsts::F64UConvertI64); break; + case ConvertSInt64ToFloat32: o << int8_t(BinaryConsts::F32SConvertI64); break; + case ConvertSInt64ToFloat64: o << int8_t(BinaryConsts::F64SConvertI64); break; case DemoteFloat64: o << int8_t(BinaryConsts::F32ConvertF64); break; case PromoteFloat32: o << int8_t(BinaryConsts::F64ConvertF32); break; - case ReinterpretFloat: o << int8_t(curr->type == i32 ? BinaryConsts::I32ReinterpretF32 : BinaryConsts::I64ReinterpretF64); break; - case ReinterpretInt: o << int8_t(curr->type == f32 ? BinaryConsts::F32ReinterpretI32 : BinaryConsts::F64ReinterpretI64); break; + case ReinterpretFloat32: o << int8_t(BinaryConsts::I32ReinterpretF32); break; + case ReinterpretFloat64: o << int8_t(BinaryConsts::I64ReinterpretF64); break; + case ReinterpretInt32: o << int8_t(BinaryConsts::F32ReinterpretI32); break; + case ReinterpretInt64: o << int8_t(BinaryConsts::F64ReinterpretI64); break; default: abort(); } } @@ -1906,37 +1916,37 @@ public: case BinaryConsts::F64NearestInt: curr = allocator.alloc<Unary>(); curr->op = Nearest; curr->type = f64; break; case BinaryConsts::F32Sqrt: curr = allocator.alloc<Unary>(); curr->op = Sqrt; curr->type = f32; break; case BinaryConsts::F64Sqrt: curr = allocator.alloc<Unary>(); curr->op = Sqrt; curr->type = f64; break; - case BinaryConsts::F32UConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt32; curr->type = f32; break; - case BinaryConsts::F64UConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt32; curr->type = f64; break; - case BinaryConsts::F32SConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt32; curr->type = f32; break; - case BinaryConsts::F64SConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt32; curr->type = f64; break; - case BinaryConsts::F32UConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt64; curr->type = f32; break; - case BinaryConsts::F64UConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt64; curr->type = f64; break; - case BinaryConsts::F32SConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt64; curr->type = f32; break; - case BinaryConsts::F64SConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt64; curr->type = f64; break; + case BinaryConsts::F32UConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt32ToFloat32; curr->type = f32; break; + case BinaryConsts::F64UConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt32ToFloat64; curr->type = f64; break; + case BinaryConsts::F32SConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt32ToFloat32; curr->type = f32; break; + case BinaryConsts::F64SConvertI32: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt32ToFloat64; curr->type = f64; break; + case BinaryConsts::F32UConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt64ToFloat32; curr->type = f32; break; + case BinaryConsts::F64UConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertUInt64ToFloat64; curr->type = f64; break; + case BinaryConsts::F32SConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt64ToFloat32; curr->type = f32; break; + case BinaryConsts::F64SConvertI64: curr = allocator.alloc<Unary>(); curr->op = ConvertSInt64ToFloat64; curr->type = f64; break; case BinaryConsts::I64STruncI32: curr = allocator.alloc<Unary>(); curr->op = ExtendSInt32; curr->type = i64; break; case BinaryConsts::I64UTruncI32: curr = allocator.alloc<Unary>(); curr->op = ExtendUInt32; curr->type = i64; break; case BinaryConsts::I32ConvertI64: curr = allocator.alloc<Unary>(); curr->op = WrapInt64; curr->type = i32; break; - case BinaryConsts::I32UTruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat32; curr->type = i32; break; - case BinaryConsts::I32UTruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat64; curr->type = i32; break; - case BinaryConsts::I32STruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat32; curr->type = i32; break; - case BinaryConsts::I32STruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat64; curr->type = i32; break; - case BinaryConsts::I64UTruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat32; curr->type = i64; break; - case BinaryConsts::I64UTruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat64; curr->type = i64; break; - case BinaryConsts::I64STruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat32; curr->type = i64; break; - case BinaryConsts::I64STruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat64; curr->type = i64; break; + case BinaryConsts::I32UTruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat32ToInt32; curr->type = i32; break; + case BinaryConsts::I32UTruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat64ToInt64; curr->type = i32; break; + case BinaryConsts::I32STruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat32ToInt32; curr->type = i32; break; + case BinaryConsts::I32STruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat64ToInt64; curr->type = i32; break; + case BinaryConsts::I64UTruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat32ToInt32; curr->type = i64; break; + case BinaryConsts::I64UTruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncUFloat64ToInt64; curr->type = i64; break; + case BinaryConsts::I64STruncF32: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat32ToInt32; curr->type = i64; break; + case BinaryConsts::I64STruncF64: curr = allocator.alloc<Unary>(); curr->op = TruncSFloat64ToInt64; curr->type = i64; break; case BinaryConsts::F32Trunc: curr = allocator.alloc<Unary>(); curr->op = Trunc; curr->type = f32; break; case BinaryConsts::F64Trunc: curr = allocator.alloc<Unary>(); curr->op = Trunc; curr->type = f64; break; case BinaryConsts::F32ConvertF64: curr = allocator.alloc<Unary>(); curr->op = DemoteFloat64; curr->type = f32; break; case BinaryConsts::F64ConvertF32: curr = allocator.alloc<Unary>(); curr->op = PromoteFloat32; curr->type = f64; break; - case BinaryConsts::I32ReinterpretF32: curr = allocator.alloc<Unary>(); curr->op = ReinterpretFloat; curr->type = i32; break; - case BinaryConsts::I64ReinterpretF64: curr = allocator.alloc<Unary>(); curr->op = ReinterpretFloat; curr->type = i64; break; - case BinaryConsts::F64ReinterpretI64: curr = allocator.alloc<Unary>(); curr->op = ReinterpretInt; curr->type = f64; break; - case BinaryConsts::F32ReinterpretI32: curr = allocator.alloc<Unary>(); curr->op = ReinterpretInt; curr->type = f32; break; + case BinaryConsts::I32ReinterpretF32: curr = allocator.alloc<Unary>(); curr->op = ReinterpretFloat32; curr->type = i32; break; + case BinaryConsts::I64ReinterpretF64: curr = allocator.alloc<Unary>(); curr->op = ReinterpretFloat64; curr->type = i64; break; + case BinaryConsts::F64ReinterpretI64: curr = allocator.alloc<Unary>(); curr->op = ReinterpretInt32; curr->type = f64; break; + case BinaryConsts::F32ReinterpretI32: curr = allocator.alloc<Unary>(); curr->op = ReinterpretInt64; curr->type = f32; break; default: return false; } diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 0dc3e41b1..8f0d4838a 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -131,32 +131,46 @@ public: ret->type = value.type; return ret; } - Unary* makeUnary(UnaryOp op, Expression *value, WasmType type=none) { + Unary* makeUnary(UnaryOp op, Expression *value) { auto* ret = allocator.alloc<Unary>(); ret->op = op; ret->value = value; - if (type != none) { - ret->type = type; // some opcodes have more than one type, user must provide it - } else { - switch (op) { - case Clz: - case Ctz: - case Popcnt: - case Neg: - case Abs: - case Ceil: - case Floor: - case Trunc: - case Nearest: - case Sqrt: ret->type = value->type; break; - case EqZ: ret->type = i32; break; - case ExtendSInt32: case ExtendUInt32: ret->type = i64; break; - case WrapInt64: ret->type = i32; break; - case PromoteFloat32: ret->type = f64; break; - case DemoteFloat64: ret->type = f32; break; - case TruncSFloat32: case TruncUFloat32: case TruncSFloat64: case TruncUFloat64: case ReinterpretFloat: - case ConvertSInt32: case ConvertUInt32: case ConvertSInt64: case ConvertUInt64: case ReinterpretInt: abort(); // user needs to say the type - default: abort(); - } + switch (op) { + case Clz: + case Ctz: + case Popcnt: + case Neg: + case Abs: + case Ceil: + case Floor: + case Trunc: + case Nearest: + case Sqrt: ret->type = value->type; break; + case EqZ: ret->type = i32; break; + case ExtendSInt32: case ExtendUInt32: ret->type = i64; break; + case WrapInt64: ret->type = i32; break; + case PromoteFloat32: ret->type = f64; break; + case DemoteFloat64: ret->type = f32; break; + case TruncSFloat32ToInt32: + case TruncUFloat32ToInt32: + case TruncSFloat64ToInt32: + case TruncUFloat64ToInt32: + case ReinterpretFloat32: ret->type = i32; break; + case TruncSFloat32ToInt64: + case TruncUFloat32ToInt64: + case TruncSFloat64ToInt64: + case TruncUFloat64ToInt64: + case ReinterpretFloat64: ret->type = i64; break; + case ReinterpretInt32: + case ConvertSInt32ToFloat32: + case ConvertUInt32ToFloat32: + case ConvertSInt64ToFloat32: + case ConvertUInt64ToFloat32: ret->type = f32; break; + case ReinterpretInt64: + case ConvertSInt32ToFloat64: + case ConvertUInt32ToFloat64: + case ConvertSInt64ToFloat64: + case ConvertUInt64ToFloat64: ret->type = f64; break; + default: abort(); } return ret; } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 5e3011282..584e4cab4 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -406,11 +406,13 @@ private: case Ctz: return value.countTrailingZeroes(); case Popcnt: return value.popCount(); case EqZ: return Literal(int32_t(value == Literal(int32_t(0)))); - case ReinterpretInt: return value.castToF32(); + case ReinterpretInt32: return value.castToF32(); case ExtendSInt32: return value.extendToSI64(); case ExtendUInt32: return value.extendToUI64(); - case ConvertUInt32: return curr->type == f32 ? value.convertUToF32() : value.convertUToF64(); - case ConvertSInt32: return curr->type == f32 ? value.convertSToF32() : value.convertSToF64(); + case ConvertUInt32ToFloat32: return value.convertUToF32(); + case ConvertUInt32ToFloat64: return value.convertUToF64(); + case ConvertSInt32ToFloat32: return value.convertSToF32(); + case ConvertSInt32ToFloat64: return value.convertSToF64(); default: abort(); } } @@ -421,9 +423,11 @@ private: case Popcnt: return value.popCount(); case EqZ: return Literal(int32_t(value == Literal(int64_t(0)))); case WrapInt64: return value.truncateToI32(); - case ReinterpretInt: return value.castToF64(); - case ConvertUInt64: return curr->type == f32 ? value.convertUToF32() : value.convertUToF64(); - case ConvertSInt64: return curr->type == f32 ? value.convertSToF32() : value.convertSToF64(); + case ReinterpretInt64: return value.castToF64(); + case ConvertUInt64ToFloat32: return value.convertUToF32(); + case ConvertUInt64ToFloat64: return value.convertUToF64(); + case ConvertSInt64ToFloat32: return value.convertSToF32(); + case ConvertSInt64ToFloat64: return value.convertSToF64(); default: abort(); } } @@ -436,9 +440,11 @@ private: case Trunc: return value.trunc(); case Nearest: return value.nearbyint(); case Sqrt: return value.sqrt(); - case TruncSFloat32: return truncSFloat(curr, value); - case TruncUFloat32: return truncUFloat(curr, value); - case ReinterpretFloat: return value.castToI32(); + case TruncSFloat32ToInt32: + case TruncSFloat32ToInt64: return truncSFloat(curr, value); + case TruncUFloat32ToInt32: + case TruncUFloat32ToInt64: return truncUFloat(curr, value); + case ReinterpretFloat32: return value.castToI32(); case PromoteFloat32: return value.extendToF64(); default: abort(); } @@ -452,9 +458,11 @@ private: case Trunc: return value.trunc(); case Nearest: return value.nearbyint(); case Sqrt: return value.sqrt(); - case TruncSFloat64: return truncSFloat(curr, value); - case TruncUFloat64: return truncUFloat(curr, value); - case ReinterpretFloat: return value.castToI64(); + case TruncSFloat64ToInt32: + case TruncSFloat64ToInt64: return truncSFloat(curr, value); + case TruncUFloat64ToInt32: + case TruncUFloat64ToInt64: return truncUFloat(curr, value); + case ReinterpretFloat64: return value.castToI64(); case DemoteFloat64: { double val = value.getFloat(); if (std::isnan(val)) return Literal(float(val)); diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index af50a684c..2c81b8a27 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -493,8 +493,8 @@ public: if (op[2] == 'p') return makeBinary(s, BinaryOp::CopySign, type); if (op[2] == 'n') { if (op[3] == 'v') { - if (op[8] == 's') return makeUnary(s, op[11] == '3' ? UnaryOp::ConvertSInt32 : UnaryOp::ConvertSInt64, type); - if (op[8] == 'u') return makeUnary(s, op[11] == '3' ? UnaryOp::ConvertUInt32 : UnaryOp::ConvertUInt64, type); + if (op[8] == 's') return makeUnary(s, op[11] == '3' ? (type == f32 ? UnaryOp::ConvertSInt32ToFloat32 : UnaryOp::ConvertSInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertSInt64ToFloat32 : UnaryOp::ConvertSInt64ToFloat64), type); + if (op[8] == 'u') return makeUnary(s, op[11] == '3' ? (type == f32 ? UnaryOp::ConvertUInt32ToFloat32 : UnaryOp::ConvertUInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertUInt64ToFloat32 : UnaryOp::ConvertUInt64ToFloat64), type); } if (op[3] == 's') return makeConst(s, type); } @@ -571,7 +571,7 @@ public: case 'r': { if (op[1] == 'e') { if (op[2] == 'm') return makeBinary(s, op[4] == 'u' ? BinaryOp::RemU : BinaryOp::RemS, type); - if (op[2] == 'i') return makeUnary(s, isWasmTypeFloat(type) ? UnaryOp::ReinterpretInt : UnaryOp::ReinterpretFloat, type); + if (op[2] == 'i') return makeUnary(s, isWasmTypeFloat(type) ? (type == f32 ? UnaryOp::ReinterpretInt32 : UnaryOp::ReinterpretInt64) : (type == i32 ? UnaryOp::ReinterpretFloat32 : UnaryOp::ReinterpretFloat64), type); } if (op[1] == 'o' && op[2] == 't') { return makeBinary(s, op[3] == 'l' ? BinaryOp::RotL : BinaryOp::RotR, type); @@ -590,8 +590,8 @@ public: } case 't': { if (op[1] == 'r') { - if (op[6] == 's') return makeUnary(s, op[9] == '3' ? UnaryOp::TruncSFloat32 : UnaryOp::TruncSFloat64, type); - if (op[6] == 'u') return makeUnary(s, op[9] == '3' ? UnaryOp::TruncUFloat32 : UnaryOp::TruncUFloat64, type); + if (op[6] == 's') return makeUnary(s, op[9] == '3' ? (type == i32 ? UnaryOp::TruncSFloat32ToInt32 : UnaryOp::TruncSFloat32ToInt64) : (type == i32 ? UnaryOp::TruncSFloat64ToInt32 : UnaryOp::TruncSFloat64ToInt64), type); + if (op[6] == 'u') return makeUnary(s, op[9] == '3' ? (type == i32 ? UnaryOp::TruncUFloat32ToInt32 : UnaryOp::TruncUFloat32ToInt64) : (type == i32 ? UnaryOp::TruncUFloat64ToInt32 : UnaryOp::TruncUFloat64ToInt64), type); if (op[2] == 'u') return makeUnary(s, UnaryOp::Trunc, type); } abort_on(op); diff --git a/src/wasm-validator.h b/src/wasm-validator.h index d71a3413a..a31f6ae15 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -123,18 +123,28 @@ public: case ExtendSInt32: case ExtendUInt32: case WrapInt64: - case TruncSFloat32: - case TruncUFloat32: - case TruncSFloat64: - case TruncUFloat64: - case ReinterpretFloat: - case ConvertUInt32: - case ConvertSInt32: - case ConvertUInt64: - case ConvertSInt64: + case TruncSFloat32ToInt32: + case TruncSFloat32ToInt64: + case TruncUFloat32ToInt32: + case TruncUFloat32ToInt64: + case TruncSFloat64ToInt32: + case TruncSFloat64ToInt64: + case TruncUFloat64ToInt32: + case TruncUFloat64ToInt64: + case ReinterpretFloat32: + case ReinterpretFloat64: + case ConvertUInt32ToFloat32: + case ConvertUInt32ToFloat64: + case ConvertSInt32ToFloat32: + case ConvertSInt32ToFloat64: + case ConvertUInt64ToFloat32: + case ConvertUInt64ToFloat64: + case ConvertSInt64ToFloat32: + case ConvertSInt64ToFloat64: case PromoteFloat32: case DemoteFloat64: - case ReinterpretInt: { + case ReinterpretInt32: + case ReinterpretInt64: { //if (curr->value->type != unreachable) { shouldBeUnequal(curr->value->type, curr->type, curr, "conversion unaries must not return the same type"); //} diff --git a/src/wasm.h b/src/wasm.h index e3c8ea7d9..843b4bc6c 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -732,8 +732,14 @@ enum UnaryOp { // relational EqZ, // conversions - ExtendSInt32, ExtendUInt32, WrapInt64, TruncSFloat32, TruncUFloat32, TruncSFloat64, TruncUFloat64, ReinterpretFloat, // int - ConvertSInt32, ConvertUInt32, ConvertSInt64, ConvertUInt64, PromoteFloat32, DemoteFloat64, ReinterpretInt // float + ExtendSInt32, ExtendUInt32, // extend i32 to i64 + WrapInt64, // i64 to i32 + TruncSFloat32ToInt32, TruncSFloat32ToInt64, TruncUFloat32ToInt32, TruncUFloat32ToInt64, TruncSFloat64ToInt32, TruncSFloat64ToInt64, TruncUFloat64ToInt32, TruncUFloat64ToInt64, // float to int + ReinterpretFloat32, ReinterpretFloat64, // reintepret bits to int + ConvertSInt32ToFloat32, ConvertSInt32ToFloat64, ConvertUInt32ToFloat32, ConvertUInt32ToFloat64, ConvertSInt64ToFloat32, ConvertSInt64ToFloat64, ConvertUInt64ToFloat32, ConvertUInt64ToFloat64, // int to float + PromoteFloat32, // f32 to f64 + DemoteFloat64, // f64 to f32 + ReinterpretInt32, ReinterpretInt64 // reinterpret bits to float }; enum BinaryOp { diff --git a/src/wasm2asm.h b/src/wasm2asm.h index e0b071f9b..61a766e1a 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -967,10 +967,10 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { case Trunc: ret = ValueBuilder::makeCall(MATH_TRUNC, value); break; case Nearest: ret = ValueBuilder::makeCall(MATH_NEAREST, value); break; case Sqrt: ret = ValueBuilder::makeCall(MATH_SQRT, value); break; - case TruncSFloat32: ret = ValueBuilder::makePrefix(B_NOT, ValueBuilder::makePrefix(B_NOT, value)); break; + //case TruncSFloat32: ret = ValueBuilder::makePrefix(B_NOT, ValueBuilder::makePrefix(B_NOT, value)); break; case PromoteFloat32: - case ConvertSInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, OR, ValueBuilder::makeNum(0))); break; - case ConvertUInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, TRSHIFT, ValueBuilder::makeNum(0))); break; + //case ConvertSInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, OR, ValueBuilder::makeNum(0))); break; + //case ConvertUInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, TRSHIFT, ValueBuilder::makeNum(0))); break; case DemoteFloat64: ret = value; break; default: std::cerr << curr << '\n'; abort(); } |