Bug 1244571 - BaldrMonkey: Implement parsing, encoding, and decoding for the conversion operators. r=luke

This commit is contained in:
Dan Gohman 2016-02-02 12:30:55 -08:00
Родитель 2924fd6106
Коммит 15c58eb3b3
6 изменённых файлов: 216 добавлений и 52 удалений

Просмотреть файл

@ -4564,15 +4564,15 @@ CheckFloatCoercionArg(FunctionValidator& f, ParseNode* inputNode, Type inputType
size_t opcodeAt) size_t opcodeAt)
{ {
if (inputType.isMaybeDouble()) { if (inputType.isMaybeDouble()) {
f.patchOp(opcodeAt, Expr::F32FromF64); f.patchOp(opcodeAt, Expr::F32DemoteF64);
return true; return true;
} }
if (inputType.isSigned()) { if (inputType.isSigned()) {
f.patchOp(opcodeAt, Expr::F32FromS32); f.patchOp(opcodeAt, Expr::F32ConvertSI32);
return true; return true;
} }
if (inputType.isUnsigned()) { if (inputType.isUnsigned()) {
f.patchOp(opcodeAt, Expr::F32FromU32); f.patchOp(opcodeAt, Expr::F32ConvertUI32);
return true; return true;
} }
if (inputType.isFloatish()) { if (inputType.isFloatish()) {
@ -4820,7 +4820,7 @@ class CheckSimdScalarArgs
// We emitted a double literal and actually want a float32. // We emitted a double literal and actually want a float32.
MOZ_ASSERT(patchAt != size_t(-1)); MOZ_ASSERT(patchAt != size_t(-1));
f.patchOp(patchAt, Expr::F32FromF64); f.patchOp(patchAt, Expr::F32DemoteF64);
return true; return true;
} }
@ -5411,11 +5411,11 @@ CoerceResult(FunctionValidator& f, ParseNode* expr, ExprType expected, Type actu
if (actual.isMaybeDouble()) if (actual.isMaybeDouble())
f.patchOp(patchAt, Expr::Id); f.patchOp(patchAt, Expr::Id);
else if (actual.isMaybeFloat()) else if (actual.isMaybeFloat())
f.patchOp(patchAt, Expr::F64FromF32); f.patchOp(patchAt, Expr::F64PromoteF32);
else if (actual.isSigned()) else if (actual.isSigned())
f.patchOp(patchAt, Expr::F64FromS32); f.patchOp(patchAt, Expr::F64ConvertSI32);
else if (actual.isUnsigned()) else if (actual.isUnsigned())
f.patchOp(patchAt, Expr::F64FromU32); f.patchOp(patchAt, Expr::F64ConvertUI32);
else else
return f.failf(expr, "%s is not a subtype of double?, float?, signed or unsigned", actual.toChars()); return f.failf(expr, "%s is not a subtype of double?, float?, signed or unsigned", actual.toChars());
break; break;
@ -5631,7 +5631,7 @@ CheckCoerceToInt(FunctionValidator& f, ParseNode* expr, Type* type)
return false; return false;
if (operandType.isMaybeDouble() || operandType.isMaybeFloat()) { if (operandType.isMaybeDouble() || operandType.isMaybeFloat()) {
Expr opcode = operandType.isMaybeDouble() ? Expr::I32SConvertF64 : Expr::I32SConvertF32; Expr opcode = operandType.isMaybeDouble() ? Expr::I32TruncSF64 : Expr::I32TruncSF32;
f.patchOp(opcodeAt, opcode); f.patchOp(opcodeAt, opcode);
*type = Type::Signed; *type = Type::Signed;
return true; return true;

Просмотреть файл

@ -289,6 +289,14 @@ DecodeComparisonOperator(FunctionDecoder& f, ExprType expected, ExprType type)
DecodeExpr(f, type); DecodeExpr(f, type);
} }
static bool
DecodeConversionOperator(FunctionDecoder& f, ExprType expected,
ExprType dstType, ExprType srcType)
{
return CheckType(f, dstType, expected) &&
DecodeExpr(f, srcType);
}
static bool static bool
DecodeExpr(FunctionDecoder& f, ExprType expected) DecodeExpr(FunctionDecoder& f, ExprType expected)
{ {
@ -386,6 +394,24 @@ DecodeExpr(FunctionDecoder& f, ExprType expected)
case Expr::F64Gt: case Expr::F64Gt:
case Expr::F64Ge: case Expr::F64Ge:
return DecodeComparisonOperator(f, expected, ExprType::F64); return DecodeComparisonOperator(f, expected, ExprType::F64);
case Expr::I32TruncSF32:
case Expr::I32TruncUF32:
case Expr::I32ReinterpretF32:
return DecodeConversionOperator(f, expected, ExprType::I32, ExprType::F32);
case Expr::I32TruncSF64:
case Expr::I32TruncUF64:
return DecodeConversionOperator(f, expected, ExprType::I32, ExprType::F64);
case Expr::F32ConvertSI32:
case Expr::F32ConvertUI32:
case Expr::F32ReinterpretI32:
return DecodeConversionOperator(f, expected, ExprType::F32, ExprType::I32);
case Expr::F32DemoteF64:
return DecodeConversionOperator(f, expected, ExprType::F32, ExprType::F64);
case Expr::F64ConvertSI32:
case Expr::F64ConvertUI32:
return DecodeConversionOperator(f, expected, ExprType::F64, ExprType::I32);
case Expr::F64PromoteF32:
return DecodeConversionOperator(f, expected, ExprType::F64, ExprType::F32);
default: default:
break; break;
} }

Просмотреть файл

@ -154,17 +154,31 @@ enum class Expr : uint16_t
F64Ge, F64Ge,
// Conversions // Conversions
I32SConvertF32, I32WrapI64,
I32SConvertF64, I64ExtendSI32,
I32UConvertF32, I64ExtendUI32,
I32UConvertF64, I32TruncSF32,
I32ConvertI64, I32TruncSF64,
I64SConvertF32, I32TruncUF32,
I64SConvertF64, I32TruncUF64,
I64UConvertF32, I64TruncSF32,
I64UConvertF64, I64TruncSF64,
I64SConvertI32, I64TruncUF32,
I64UConvertI32, I64TruncUF64,
F32ConvertSI32,
F32ConvertUI32,
F64ConvertSI32,
F64ConvertUI32,
F32ConvertSI64,
F32ConvertUI64,
F64ConvertSI64,
F64ConvertUI64,
F32DemoteF64,
F64PromoteF32,
I32ReinterpretF32,
F32ReinterpretI32,
I64ReinterpretF64,
F64ReinterpretI64,
// Load/store operations // Load/store operations
I32LoadMem8S, I32LoadMem8S,
@ -251,10 +265,6 @@ enum class Expr : uint16_t
I32Abs, I32Abs,
// F32 asm.js opcodes // F32 asm.js opcodes
F32FromF64,
F32FromS32,
F32FromU32,
F32StoreMemF64, F32StoreMemF64,
// F64 asm.js opcodes // F64 asm.js opcodes
@ -271,10 +281,6 @@ enum class Expr : uint16_t
F64Pow, F64Pow,
F64Atan2, F64Atan2,
F64FromF32,
F64FromS32,
F64FromU32,
F64StoreMemF32, F64StoreMemF32,
Limit Limit

Просмотреть файл

@ -2726,9 +2726,11 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
return EmitMathMinMax(f, ExprType::I32, IsMax(true), def); return EmitMathMinMax(f, ExprType::I32, IsMax(true), def);
case Expr::I32Not: case Expr::I32Not:
return EmitUnary<MNot>(f, ExprType::I32, def); return EmitUnary<MNot>(f, ExprType::I32, def);
case Expr::I32SConvertF32: case Expr::I32TruncSF32:
case Expr::I32TruncUF32:
return EmitUnary<MTruncateToInt32>(f, ExprType::F32, def); return EmitUnary<MTruncateToInt32>(f, ExprType::F32, def);
case Expr::I32SConvertF64: case Expr::I32TruncSF64:
case Expr::I32TruncUF64:
return EmitUnary<MTruncateToInt32>(f, ExprType::F64, def); return EmitUnary<MTruncateToInt32>(f, ExprType::F64, def);
case Expr::I32Clz: case Expr::I32Clz:
return EmitUnary<MClz>(f, ExprType::I32, def); return EmitUnary<MClz>(f, ExprType::I32, def);
@ -2823,11 +2825,11 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
case Expr::F32Ceil: case Expr::F32Ceil:
case Expr::F32Floor: case Expr::F32Floor:
return EmitF32MathBuiltinCall(f, op, def); return EmitF32MathBuiltinCall(f, op, def);
case Expr::F32FromF64: case Expr::F32DemoteF64:
return EmitUnary<MToFloat32>(f, ExprType::F64, def); return EmitUnary<MToFloat32>(f, ExprType::F64, def);
case Expr::F32FromS32: case Expr::F32ConvertSI32:
return EmitUnary<MToFloat32>(f, ExprType::I32, def); return EmitUnary<MToFloat32>(f, ExprType::I32, def);
case Expr::F32FromU32: case Expr::F32ConvertUI32:
return EmitUnary<MAsmJSUnsignedToFloat32>(f, ExprType::I32, def); return EmitUnary<MAsmJSUnsignedToFloat32>(f, ExprType::I32, def);
case Expr::F32LoadMem: case Expr::F32LoadMem:
return EmitLoadArray(f, Scalar::Float32, def); return EmitLoadArray(f, Scalar::Float32, def);
@ -2871,11 +2873,11 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
case Expr::F64Pow: case Expr::F64Pow:
case Expr::F64Atan2: case Expr::F64Atan2:
return EmitF64MathBuiltinCall(f, op, def); return EmitF64MathBuiltinCall(f, op, def);
case Expr::F64FromF32: case Expr::F64PromoteF32:
return EmitUnary<MToDouble>(f, ExprType::F32, def); return EmitUnary<MToDouble>(f, ExprType::F32, def);
case Expr::F64FromS32: case Expr::F64ConvertSI32:
return EmitUnary<MToDouble>(f, ExprType::I32, def); return EmitUnary<MToDouble>(f, ExprType::I32, def);
case Expr::F64FromU32: case Expr::F64ConvertUI32:
return EmitUnary<MAsmJSUnsignedToDouble>(f, ExprType::I32, def); return EmitUnary<MAsmJSUnsignedToDouble>(f, ExprType::I32, def);
case Expr::F64LoadMem: case Expr::F64LoadMem:
return EmitLoadArray(f, Scalar::Float64, def); return EmitLoadArray(f, Scalar::Float64, def);
@ -2920,16 +2922,22 @@ EmitExpr(FunctionCompiler& f, ExprType type, MDefinition** def, LabelVector* may
case Expr::F64CopySign: case Expr::F64CopySign:
case Expr::F64Nearest: case Expr::F64Nearest:
case Expr::F64Trunc: case Expr::F64Trunc:
case Expr::I32UConvertF32: case Expr::I32WrapI64:
case Expr::I32UConvertF64:
case Expr::I32ConvertI64:
case Expr::I64Const: case Expr::I64Const:
case Expr::I64SConvertI32: case Expr::I64ExtendSI32:
case Expr::I64UConvertI32: case Expr::I64ExtendUI32:
case Expr::I64SConvertF32: case Expr::I64TruncSF32:
case Expr::I64SConvertF64: case Expr::I64TruncSF64:
case Expr::I64UConvertF32: case Expr::I64TruncUF32:
case Expr::I64UConvertF64: case Expr::I64TruncUF64:
case Expr::F32ConvertSI64:
case Expr::F32ConvertUI64:
case Expr::F64ConvertSI64:
case Expr::F64ConvertUI64:
case Expr::I64ReinterpretF64:
case Expr::F64ReinterpretI64:
case Expr::I32ReinterpretF32:
case Expr::F32ReinterpretI32:
case Expr::I64LoadMem8S: case Expr::I64LoadMem8S:
case Expr::I64LoadMem16S: case Expr::I64LoadMem16S:
case Expr::I64LoadMem32S: case Expr::I64LoadMem32S:

Просмотреть файл

@ -98,6 +98,7 @@ enum class WasmAstExprKind
Call, Call,
ComparisonOperator, ComparisonOperator,
Const, Const,
ConversionOperator,
GetLocal, GetLocal,
Nop, Nop,
SetLocal, SetLocal,
@ -366,6 +367,22 @@ class WasmAstComparisonOperator final : public WasmAstExpr
WasmAstExpr* rhs() const { return rhs_; } WasmAstExpr* rhs() const { return rhs_; }
}; };
class WasmAstConversionOperator final : public WasmAstExpr
{
Expr expr_;
WasmAstExpr* op_;
public:
static const WasmAstExprKind Kind = WasmAstExprKind::ConversionOperator;
explicit WasmAstConversionOperator(Expr expr, WasmAstExpr* op)
: WasmAstExpr(Kind),
expr_(expr), op_(op)
{}
Expr expr() const { return expr_; }
WasmAstExpr* op() const { return op_; }
};
/*****************************************************************************/ /*****************************************************************************/
// wasm text token stream // wasm text token stream
@ -381,6 +398,7 @@ class WasmToken
CloseParen, CloseParen,
ComparisonOpcode, ComparisonOpcode,
Const, Const,
ConversionOpcode,
EndOfFile, EndOfFile,
Error, Error,
Export, Export,
@ -442,7 +460,8 @@ class WasmToken
end_(end) end_(end)
{ {
MOZ_ASSERT(begin != end); MOZ_ASSERT(begin != end);
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode); MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode ||
kind_ == ConversionOpcode);
u.expr_ = expr; u.expr_ = expr;
} }
explicit WasmToken(const char16_t* begin) explicit WasmToken(const char16_t* begin)
@ -475,7 +494,8 @@ class WasmToken
return u.valueType_; return u.valueType_;
} }
Expr expr() const { Expr expr() const {
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode); MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode || kind_ == ComparisonOpcode ||
kind_ == ConversionOpcode);
return u.expr_; return u.expr_;
} }
}; };
@ -626,10 +646,19 @@ class WasmTokenStream
return WasmToken(WasmToken::UnaryOpcode, Expr::F32Ceil, begin, cur_); return WasmToken(WasmToken::UnaryOpcode, Expr::F32Ceil, begin, cur_);
if (consume(MOZ_UTF16("const"))) if (consume(MOZ_UTF16("const")))
return WasmToken(WasmToken::Const, ValType::F32, begin, cur_); return WasmToken(WasmToken::Const, ValType::F32, begin, cur_);
if (consume(MOZ_UTF16("convert_s/i32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertSI32,
begin, cur_);
if (consume(MOZ_UTF16("convert_u/i32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F32ConvertUI32,
begin, cur_);
if (consume(MOZ_UTF16("copysign"))) if (consume(MOZ_UTF16("copysign")))
return WasmToken(WasmToken::BinaryOpcode, Expr::F32CopySign, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::F32CopySign, begin, cur_);
break; break;
case 'd': case 'd':
if (consume(MOZ_UTF16("demote/f64")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F32DemoteF64,
begin, cur_);
if (consume(MOZ_UTF16("div"))) if (consume(MOZ_UTF16("div")))
return WasmToken(WasmToken::BinaryOpcode, Expr::F32Div, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::F32Div, begin, cur_);
break; break;
@ -669,6 +698,11 @@ class WasmTokenStream
if (consume(MOZ_UTF16("ne"))) if (consume(MOZ_UTF16("ne")))
return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Ne, begin, cur_); return WasmToken(WasmToken::ComparisonOpcode, Expr::F32Ne, begin, cur_);
break; break;
case 'r':
if (consume(MOZ_UTF16("reinterpret/i32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F32ReinterpretI32,
begin, cur_);
break;
case 's': case 's':
if (consume(MOZ_UTF16("sqrt"))) if (consume(MOZ_UTF16("sqrt")))
return WasmToken(WasmToken::UnaryOpcode, Expr::F32Sqrt, begin, cur_); return WasmToken(WasmToken::UnaryOpcode, Expr::F32Sqrt, begin, cur_);
@ -698,6 +732,12 @@ class WasmTokenStream
return WasmToken(WasmToken::UnaryOpcode, Expr::F64Ceil, begin, cur_); return WasmToken(WasmToken::UnaryOpcode, Expr::F64Ceil, begin, cur_);
if (consume(MOZ_UTF16("const"))) if (consume(MOZ_UTF16("const")))
return WasmToken(WasmToken::Const, ValType::F64, begin, cur_); return WasmToken(WasmToken::Const, ValType::F64, begin, cur_);
if (consume(MOZ_UTF16("convert_s/i32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertSI32,
begin, cur_);
if (consume(MOZ_UTF16("convert_u/i32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F64ConvertUI32,
begin, cur_);
if (consume(MOZ_UTF16("copysign"))) if (consume(MOZ_UTF16("copysign")))
return WasmToken(WasmToken::BinaryOpcode, Expr::F64CopySign, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::F64CopySign, begin, cur_);
break; break;
@ -741,6 +781,11 @@ class WasmTokenStream
if (consume(MOZ_UTF16("ne"))) if (consume(MOZ_UTF16("ne")))
return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Ne, begin, cur_); return WasmToken(WasmToken::ComparisonOpcode, Expr::F64Ne, begin, cur_);
break; break;
case 'p':
if (consume(MOZ_UTF16("promote/f32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::F64PromoteF32,
begin, cur_);
break;
case 's': case 's':
if (consume(MOZ_UTF16("sqrt"))) if (consume(MOZ_UTF16("sqrt")))
return WasmToken(WasmToken::UnaryOpcode, Expr::F64Sqrt, begin, cur_); return WasmToken(WasmToken::UnaryOpcode, Expr::F64Sqrt, begin, cur_);
@ -822,16 +867,19 @@ class WasmTokenStream
if (consume(MOZ_UTF16("or"))) if (consume(MOZ_UTF16("or")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32Or, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32Or, begin, cur_);
break; break;
case 'p':
if (consume(MOZ_UTF16("popcnt")))
return WasmToken(WasmToken::UnaryOpcode, Expr::I32Popcnt, begin, cur_);
break;
case 'r': case 'r':
if (consume(MOZ_UTF16("reinterpret/f32")))
return WasmToken(WasmToken::UnaryOpcode, Expr::I32ReinterpretF32,
begin, cur_);
if (consume(MOZ_UTF16("rem_s"))) if (consume(MOZ_UTF16("rem_s")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemS, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemS, begin, cur_);
if (consume(MOZ_UTF16("rem_u"))) if (consume(MOZ_UTF16("rem_u")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemU, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32RemU, begin, cur_);
break; break;
case 'p':
if (consume(MOZ_UTF16("popcnt")))
return WasmToken(WasmToken::UnaryOpcode, Expr::I32Popcnt, begin, cur_);
break;
case 's': case 's':
if (consume(MOZ_UTF16("sub"))) if (consume(MOZ_UTF16("sub")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32Sub, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32Sub, begin, cur_);
@ -842,6 +890,20 @@ class WasmTokenStream
if (consume(MOZ_UTF16("shr_u"))) if (consume(MOZ_UTF16("shr_u")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32ShrU, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32ShrU, begin, cur_);
break; break;
case 't':
if (consume(MOZ_UTF16("trunc_s/f32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncSF32,
begin, cur_);
if (consume(MOZ_UTF16("trunc_s/f64")))
return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncSF64,
begin, cur_);
if (consume(MOZ_UTF16("trunc_u/f32")))
return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncUF32,
begin, cur_);
if (consume(MOZ_UTF16("trunc_u/f64")))
return WasmToken(WasmToken::ConversionOpcode, Expr::I32TruncUF64,
begin, cur_);
break;
case 'x': case 'x':
if (consume(MOZ_UTF16("xor"))) if (consume(MOZ_UTF16("xor")))
return WasmToken(WasmToken::BinaryOpcode, Expr::I32Xor, begin, cur_); return WasmToken(WasmToken::BinaryOpcode, Expr::I32Xor, begin, cur_);
@ -1110,6 +1172,16 @@ ParseComparisonOperator(WasmParseContext& c, Expr expr)
return new(c.lifo) WasmAstComparisonOperator(expr, lhs, rhs); return new(c.lifo) WasmAstComparisonOperator(expr, lhs, rhs);
} }
static WasmAstConversionOperator*
ParseConversionOperator(WasmParseContext& c, Expr expr)
{
WasmAstExpr* op = ParseExpr(c);
if (!op)
return nullptr;
return new(c.lifo) WasmAstConversionOperator(expr, op);
}
static WasmAstExpr* static WasmAstExpr*
ParseExprInsideParens(WasmParseContext& c) ParseExprInsideParens(WasmParseContext& c)
{ {
@ -1126,10 +1198,12 @@ ParseExprInsideParens(WasmParseContext& c)
return ParseCall(c, Expr::Call); return ParseCall(c, Expr::Call);
case WasmToken::CallImport: case WasmToken::CallImport:
return ParseCall(c, Expr::CallImport); return ParseCall(c, Expr::CallImport);
case WasmToken::Const:
return ParseConst(c, token);
case WasmToken::ComparisonOpcode: case WasmToken::ComparisonOpcode:
return ParseComparisonOperator(c, token.expr()); return ParseComparisonOperator(c, token.expr());
case WasmToken::Const:
return ParseConst(c, token);
case WasmToken::ConversionOpcode:
return ParseConversionOperator(c, token.expr());
case WasmToken::GetLocal: case WasmToken::GetLocal:
return ParseGetLocal(c); return ParseGetLocal(c);
case WasmToken::SetLocal: case WasmToken::SetLocal:
@ -1406,6 +1480,13 @@ EncodeComparisonOperator(Encoder& e, WasmAstComparisonOperator& b)
EncodeExpr(e, *b.rhs()); EncodeExpr(e, *b.rhs());
} }
static bool
EncodeConversionOperator(Encoder& e, WasmAstConversionOperator& b)
{
return e.writeExpr(b.expr()) &&
EncodeExpr(e, *b.op());
}
static bool static bool
EncodeExpr(Encoder& e, WasmAstExpr& expr) EncodeExpr(Encoder& e, WasmAstExpr& expr)
{ {
@ -1422,6 +1503,8 @@ EncodeExpr(Encoder& e, WasmAstExpr& expr)
return EncodeComparisonOperator(e, expr.as<WasmAstComparisonOperator>()); return EncodeComparisonOperator(e, expr.as<WasmAstComparisonOperator>());
case WasmAstExprKind::Const: case WasmAstExprKind::Const:
return EncodeConst(e, expr.as<WasmAstConst>()); return EncodeConst(e, expr.as<WasmAstConst>());
case WasmAstExprKind::ConversionOperator:
return EncodeConversionOperator(e, expr.as<WasmAstConversionOperator>());
case WasmAstExprKind::GetLocal: case WasmAstExprKind::GetLocal:
return EncodeGetLocal(e, expr.as<WasmAstGetLocal>()); return EncodeGetLocal(e, expr.as<WasmAstGetLocal>());
case WasmAstExprKind::SetLocal: case WasmAstExprKind::SetLocal:

Просмотреть файл

@ -0,0 +1,41 @@
load(libdir + "wasm.js");
if (!wasmIsSupported())
quit();
function mismatchError(actual, expect) {
var str = "type mismatch: expression has type " + actual + " but expected " + expect;
return RegExp(str);
}
function testConversion(resultType, opcode, paramType, op, expect) {
assertEq(wasmEvalText('(module (func (param ' + paramType + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))) (export "" 0))')(op), expect);
for (var bad of ['i32', 'f32', 'f64']) {
if (bad != resultType)
assertErrorMessage(() => wasmEvalText('(module (func (param ' + paramType + ') (result ' + bad + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
TypeError,
mismatchError(resultType, bad)
);
if (bad != paramType)
assertErrorMessage(() => wasmEvalText('(module (func (param ' + bad + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
TypeError,
mismatchError(bad, paramType)
);
}
}
testConversion('i32', 'trunc_s', 'f32', 40.1, 40);
testConversion('i32', 'trunc_u', 'f32', 40.1, 40);
testConversion('i32', 'trunc_s', 'f64', 40.1, 40);
testConversion('i32', 'trunc_u', 'f64', 40.1, 40);
//testConversion('i32', 'reinterpret', 'f32', 40.1, 1109419622); // TODO: NYI
testConversion('f32', 'convert_s', 'i32', 40, 40);
testConversion('f32', 'convert_u', 'i32', 40, 40);
testConversion('f32', 'demote', 'f64', 40.1, 40.099998474121094);
//testConversion('f32', 'reinterpret', 'i32', 40, 5.605193857299268e-44); // TODO: NYI
testConversion('f64', 'convert_s', 'i32', 40, 40);
testConversion('f64', 'convert_u', 'i32', 40, 40);
testConversion('f64', 'promote', 'f32', 40.1, 40.099998474121094);