summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xauto_update_tests.py37
-rw-r--r--src/asm2wasm.h12
-rw-r--r--src/binaryen-c.cpp34
-rw-r--r--src/binaryen-c.h44
-rw-r--r--src/passes/Print.cpp30
-rw-r--r--src/passes/Vacuum.cpp2
-rw-r--r--src/s2wasm.h22
-rw-r--r--src/wasm-binary.h70
-rw-r--r--src/wasm-builder.h62
-rw-r--r--src/wasm-interpreter.h32
-rw-r--r--src/wasm-s-parser.h10
-rw-r--r--src/wasm-validator.h30
-rw-r--r--src/wasm.h10
-rw-r--r--src/wasm2asm.h6
-rw-r--r--test/example/c-api-kitchen-sink.c72
-rw-r--r--test/example/c-api-kitchen-sink.txt32
16 files changed, 325 insertions, 180 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py
index e0ae3a7a7..bd9e5f695 100755
--- a/auto_update_tests.py
+++ b/auto_update_tests.py
@@ -95,17 +95,30 @@ for wast in sorted(os.listdir('test')):
print '\n[ checking example testcases... ]\n'
-cmd = [os.environ.get('CXX') or 'g++', '-std=c++11',
- os.path.join('test', 'example', 'find_div0s.cpp'),
- os.path.join('src', 'pass.cpp'),
- os.path.join('src', 'passes', 'Print.cpp'),
- '-Isrc', '-g', '-lsupport', '-Llib/.']
-if os.environ.get('COMPILER_FLAGS'):
- for f in os.environ.get('COMPILER_FLAGS').split(' '):
- cmd.append(f)
-print ' '.join(cmd)
-subprocess.check_call(cmd)
-actual = subprocess.Popen(['./a.out'], stdout=subprocess.PIPE).communicate()[0]
-open(os.path.join('test', 'example', 'find_div0s.txt'), 'w').write(actual)
+for t in sorted(os.listdir(os.path.join('test', 'example'))):
+ cmd = ['-Isrc', '-g', '-lasmjs', '-lsupport', '-Llib/.', '-pthread']
+ if t.endswith('.cpp'):
+ cmd = [os.path.join('test', 'example', t),
+ os.path.join('src', 'pass.cpp'),
+ os.path.join('src', 'wasm.cpp'),
+ os.path.join('src', 'passes', 'Print.cpp')] + cmd
+ elif t.endswith('.c'):
+ # build the C file separately
+ extra = [os.environ.get('CC') or 'gcc',
+ os.path.join('test', 'example', t), '-c', '-o', 'example.o',
+ '-Isrc', '-g', '-lasmjs', '-lsupport', '-Llib/.', '-pthread']
+ print ' '.join(extra)
+ subprocess.check_call(extra)
+ cmd = ['example.o', '-lbinaryen-c'] + cmd
+ else:
+ continue
+ if os.environ.get('COMPILER_FLAGS'):
+ for f in os.environ.get('COMPILER_FLAGS').split(' '):
+ cmd.append(f)
+ cmd = [os.environ.get('CXX') or 'g++', '-std=c++11'] + cmd
+ print ' '.join(cmd)
+ subprocess.check_call(cmd)
+ actual = subprocess.Popen(['./a.out'], stdout=subprocess.PIPE).communicate()[0]
+ open(os.path.join('test', 'example', '.'.join(t.split('.')[:-1]) + '.txt'), 'w').write(actual)
print '\n[ success! ]'
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();
}
diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c
index f7dc5c341..bfcb1ddea 100644
--- a/test/example/c-api-kitchen-sink.c
+++ b/test/example/c-api-kitchen-sink.c
@@ -10,11 +10,11 @@
// helpers
-BinaryenExpressionRef makeUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenType inputType, BinaryenType outputType) {
- if (inputType == BinaryenInt32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)), outputType);
- if (inputType == BinaryenInt64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)), outputType);
- if (inputType == BinaryenFloat32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612)), outputType);
- if (inputType == BinaryenFloat64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)), outputType);
+BinaryenExpressionRef makeUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenType inputType) {
+ if (inputType == BinaryenInt32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt32(-10)));
+ if (inputType == BinaryenInt64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralInt64(-22)));
+ if (inputType == BinaryenFloat32()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat32(-33.612)));
+ if (inputType == BinaryenFloat64()) return BinaryenUnary(module, op, BinaryenConst(module, BinaryenLiteralFloat64(-9005.841)));
abort();
}
@@ -81,32 +81,42 @@ int main() {
BinaryenExpressionRef bodyList[] = {
// Unary
- makeUnary(module, BinaryenClz(), 1, 1),
- makeUnary(module, BinaryenCtz(), 2, 2),
- makeUnary(module, BinaryenPopcnt(), 1, 1),
- makeUnary(module, BinaryenNeg(), 3, 3),
- makeUnary(module, BinaryenAbs(), 4, 3),
- makeUnary(module, BinaryenCeil(), 3, 3),
- makeUnary(module, BinaryenFloor(), 4, 4),
- makeUnary(module, BinaryenTrunc(), 3, 3),
- makeUnary(module, BinaryenNearest(), 3, 3),
- makeUnary(module, BinaryenSqrt(), 4, 4),
- makeUnary(module, BinaryenEqZ(), 1, 1),
- makeUnary(module, BinaryenExtendSInt32(), 1, 2),
- makeUnary(module, BinaryenExtentUInt32(), 1, 2),
- makeUnary(module, BinaryenWrapInt64(), 2, 1),
- makeUnary(module, BinaryenTruncSFloat32(), 3, 1),
- makeUnary(module, BinaryenTruncUFloat32(), 3, 2),
- makeUnary(module, BinaryenTruncSFloat64(), 4, 2),
- makeUnary(module, BinaryenTruncUFloat64(), 4, 1),
- makeUnary(module, BinaryenReinterpretFloat(), 3, 1),
- makeUnary(module, BinaryenConvertSInt32(), 1, 3),
- makeUnary(module, BinaryenConvertUInt32(), 1, 4),
- makeUnary(module, BinaryenConvertSInt64(), 2, 3),
- makeUnary(module, BinaryenConvertUInt64(), 2, 4),
- makeUnary(module, BinaryenPromoteFloat32(), 3, 4),
- makeUnary(module, BinaryenDemoteFloat64(), 4, 3),
- makeUnary(module, BinaryenReinterpretInt(), 1, 3),
+ makeUnary(module, BinaryenClz(), 1),
+ makeUnary(module, BinaryenCtz(), 2),
+ makeUnary(module, BinaryenPopcnt(), 1),
+ makeUnary(module, BinaryenNeg(), 3),
+ makeUnary(module, BinaryenAbs(), 4),
+ makeUnary(module, BinaryenCeil(), 3),
+ makeUnary(module, BinaryenFloor(), 4),
+ makeUnary(module, BinaryenTrunc(), 3),
+ makeUnary(module, BinaryenNearest(), 3),
+ makeUnary(module, BinaryenSqrt(), 4),
+ makeUnary(module, BinaryenEqZ(), 1),
+ makeUnary(module, BinaryenExtendSInt32(), 1),
+ makeUnary(module, BinaryenExtentUInt32(), 1),
+ makeUnary(module, BinaryenWrapInt64(), 2),
+ makeUnary(module, BinaryenTruncSFloat32ToInt32(), 3),
+ makeUnary(module, BinaryenTruncSFloat32ToInt64(), 3),
+ makeUnary(module, BinaryenTruncUFloat32ToInt32(), 3),
+ makeUnary(module, BinaryenTruncUFloat32ToInt64(), 3),
+ makeUnary(module, BinaryenTruncSFloat64ToInt32(), 4),
+ makeUnary(module, BinaryenTruncSFloat64ToInt64(), 4),
+ makeUnary(module, BinaryenTruncUFloat64ToInt32(), 4),
+ makeUnary(module, BinaryenTruncUFloat64ToInt64(), 4),
+ makeUnary(module, BinaryenReinterpretFloat32(), 3),
+ makeUnary(module, BinaryenReinterpretFloat64(), 4),
+ makeUnary(module, BinaryenConvertSInt32ToFloat32(), 1),
+ makeUnary(module, BinaryenConvertSInt32ToFloat64(), 1),
+ makeUnary(module, BinaryenConvertUInt32ToFloat32(), 1),
+ makeUnary(module, BinaryenConvertUInt32ToFloat64(), 1),
+ makeUnary(module, BinaryenConvertSInt64ToFloat32(), 2),
+ makeUnary(module, BinaryenConvertSInt64ToFloat64(), 2),
+ makeUnary(module, BinaryenConvertUInt64ToFloat32(), 2),
+ makeUnary(module, BinaryenConvertUInt64ToFloat64(), 2),
+ makeUnary(module, BinaryenPromoteFloat32(), 3),
+ makeUnary(module, BinaryenDemoteFloat64(), 4),
+ makeUnary(module, BinaryenReinterpretInt32(), 1),
+ makeUnary(module, BinaryenReinterpretInt64(), 1),
// Binary
makeBinary(module, BinaryenAdd(), 1),
makeBinary(module, BinaryenSub(), 4),
diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt
index 2c80d8706..573d159ed 100644
--- a/test/example/c-api-kitchen-sink.txt
+++ b/test/example/c-api-kitchen-sink.txt
@@ -29,7 +29,7 @@ BinaryenFloat64: 4
(f32.neg
(f32.const -33.61199951171875)
)
- (f32.abs
+ (f64.abs
(f64.const -9005.841)
)
(f32.ceil
@@ -62,27 +62,54 @@ BinaryenFloat64: 4
(i32.trunc_s/f32
(f32.const -33.61199951171875)
)
+ (i64.trunc_s/f32
+ (f32.const -33.61199951171875)
+ )
+ (i32.trunc_u/f32
+ (f32.const -33.61199951171875)
+ )
(i64.trunc_u/f32
(f32.const -33.61199951171875)
)
+ (i32.trunc_s/f64
+ (f64.const -9005.841)
+ )
(i64.trunc_s/f64
(f64.const -9005.841)
)
(i32.trunc_u/f64
(f64.const -9005.841)
)
+ (i64.trunc_u/f64
+ (f64.const -9005.841)
+ )
(i32.reinterpret/f32
(f32.const -33.61199951171875)
)
+ (i64.reinterpret/f64
+ (f64.const -9005.841)
+ )
(f32.convert_s/i32
(i32.const -10)
)
+ (f64.convert_s/i32
+ (i32.const -10)
+ )
+ (f32.convert_u/i32
+ (i32.const -10)
+ )
(f64.convert_u/i32
(i32.const -10)
)
(f32.convert_s/i64
(i64.const -22)
)
+ (f64.convert_s/i64
+ (i64.const -22)
+ )
+ (f32.convert_u/i64
+ (i64.const -22)
+ )
(f64.convert_u/i64
(i64.const -22)
)
@@ -95,6 +122,9 @@ BinaryenFloat64: 4
(f32.reinterpret/i32
(i32.const -10)
)
+ (f64.reinterpret/i64
+ (i32.const -10)
+ )
(i32.add
(i32.const -10)
(i32.const -11)