[wasm] Implement the Extended Constants proposal
This proposal adds i32 and i64 addition, subtraction, and multiplication to the list of constant expressions. See https://github.com/WebAssembly/extended-const. Bug: v8:12089 Change-Id: I23a27a54a15fd37ee1d553992ab3b355eb9d317c Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3497665 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#79362}
This commit is contained in:
parent
6b565a04f2
commit
bf1565d708
@ -910,6 +910,8 @@ struct ControlBase : public PcForErrors<validate> {
|
||||
F(F32Const, Value* result, float value) \
|
||||
F(F64Const, Value* result, double value) \
|
||||
F(S128Const, Simd128Immediate<validate>& imm, Value* result) \
|
||||
F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
|
||||
Value* result) \
|
||||
F(RefNull, ValueType type, Value* result) \
|
||||
F(RefFunc, uint32_t function_index, Value* result) \
|
||||
F(GlobalGet, Value* result, const GlobalIndexImmediate<validate>& imm) \
|
||||
@ -935,8 +937,6 @@ struct ControlBase : public PcForErrors<validate> {
|
||||
F(PopControl, Control* block) \
|
||||
/* Instructions: */ \
|
||||
F(UnOp, WasmOpcode opcode, const Value& value, Value* result) \
|
||||
F(BinOp, WasmOpcode opcode, const Value& lhs, const Value& rhs, \
|
||||
Value* result) \
|
||||
F(RefAsNonNull, const Value& arg, Value* result) \
|
||||
F(Drop) \
|
||||
F(LocalGet, Value* result, const IndexImmediate<validate>& imm) \
|
||||
@ -2560,7 +2560,20 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
|
||||
#define BUILD_SIMPLE_OPCODE(op, _, sig) \
|
||||
DECODE(op) { return BuildSimpleOperator_##sig(kExpr##op); }
|
||||
FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
|
||||
FOREACH_SIMPLE_NON_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
|
||||
#undef BUILD_SIMPLE_OPCODE
|
||||
|
||||
#define BUILD_SIMPLE_OPCODE(op, _, sig) \
|
||||
DECODE(op) { \
|
||||
if (decoding_mode == kInitExpression) { \
|
||||
if (!VALIDATE(this->enabled_.has_extended_const())) { \
|
||||
NonConstError(this, kExpr##op); \
|
||||
return 0; \
|
||||
} \
|
||||
} \
|
||||
return BuildSimpleOperator_##sig(kExpr##op); \
|
||||
}
|
||||
FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
|
||||
#undef BUILD_SIMPLE_OPCODE
|
||||
|
||||
DECODE(Block) {
|
||||
@ -3501,8 +3514,11 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
|
||||
static constexpr OpcodeHandler GetOpcodeHandlerTableEntry(size_t idx) {
|
||||
DECODE_IMPL(Nop);
|
||||
#define BUILD_SIMPLE_OPCODE(op, _, sig) DECODE_IMPL(op);
|
||||
FOREACH_SIMPLE_OPCODE(BUILD_SIMPLE_OPCODE)
|
||||
FOREACH_SIMPLE_NON_CONST_OPCODE(BUILD_SIMPLE_OPCODE)
|
||||
#undef BUILD_SIMPLE_OPCODE
|
||||
#define BUILD_SIMPLE_EXTENDED_CONST_OPCODE(op, _, sig) DECODE_IMPL_CONST(op);
|
||||
FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(BUILD_SIMPLE_EXTENDED_CONST_OPCODE)
|
||||
#undef BUILD_SIMPLE_EXTENDED_CONST_OPCODE
|
||||
DECODE_IMPL(Block);
|
||||
DECODE_IMPL(Rethrow);
|
||||
DECODE_IMPL(Throw);
|
||||
|
@ -44,6 +44,40 @@ void InitExprInterface::S128Const(FullDecoder* decoder,
|
||||
result->runtime_value = WasmValue(imm.value, kWasmS128);
|
||||
}
|
||||
|
||||
void InitExprInterface::BinOp(FullDecoder* decoder, WasmOpcode opcode,
|
||||
const Value& lhs, const Value& rhs,
|
||||
Value* result) {
|
||||
if (!generate_result()) return;
|
||||
switch (opcode) {
|
||||
case kExprI32Add:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i32() + rhs.runtime_value.to_i32());
|
||||
break;
|
||||
case kExprI32Sub:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i32() - rhs.runtime_value.to_i32());
|
||||
break;
|
||||
case kExprI32Mul:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i32() * rhs.runtime_value.to_i32());
|
||||
break;
|
||||
case kExprI64Add:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i64() + rhs.runtime_value.to_i64());
|
||||
break;
|
||||
case kExprI64Sub:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i64() - rhs.runtime_value.to_i64());
|
||||
break;
|
||||
case kExprI64Mul:
|
||||
result->runtime_value =
|
||||
WasmValue(lhs.runtime_value.to_i64() * rhs.runtime_value.to_i64());
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void InitExprInterface::RefNull(FullDecoder* decoder, ValueType type,
|
||||
Value* result) {
|
||||
if (!generate_result()) return;
|
||||
|
@ -64,7 +64,12 @@
|
||||
/* Stack Switching proposal. */ \
|
||||
/* https://github.com/WebAssembly/stack-switching */ \
|
||||
/* V8 side owner: thibaudm, fgm */ \
|
||||
V(stack_switching, "stack switching", false)
|
||||
V(stack_switching, "stack switching", false) \
|
||||
\
|
||||
/* Extended Constant Expressions Proposal. */ \
|
||||
/* https://github.com/WebAssembly/extended-const */ \
|
||||
/* V8 side owner: manoskouk */ \
|
||||
V(extended_const, "extended constant expressions", false)
|
||||
|
||||
// #############################################################################
|
||||
// Staged features (disabled by default, but enabled via --wasm-staging (also
|
||||
|
@ -116,136 +116,145 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
|
||||
V(MemoryGrow, 0x40, i_i)
|
||||
|
||||
// Expressions with signatures.
|
||||
#define FOREACH_SIMPLE_OPCODE(V) \
|
||||
V(I32Eqz, 0x45, i_i) \
|
||||
V(I32Eq, 0x46, i_ii) \
|
||||
V(I32Ne, 0x47, i_ii) \
|
||||
V(I32LtS, 0x48, i_ii) \
|
||||
V(I32LtU, 0x49, i_ii) \
|
||||
V(I32GtS, 0x4a, i_ii) \
|
||||
V(I32GtU, 0x4b, i_ii) \
|
||||
V(I32LeS, 0x4c, i_ii) \
|
||||
V(I32LeU, 0x4d, i_ii) \
|
||||
V(I32GeS, 0x4e, i_ii) \
|
||||
V(I32GeU, 0x4f, i_ii) \
|
||||
V(I64Eqz, 0x50, i_l) \
|
||||
V(I64Eq, 0x51, i_ll) \
|
||||
V(I64Ne, 0x52, i_ll) \
|
||||
V(I64LtS, 0x53, i_ll) \
|
||||
V(I64LtU, 0x54, i_ll) \
|
||||
V(I64GtS, 0x55, i_ll) \
|
||||
V(I64GtU, 0x56, i_ll) \
|
||||
V(I64LeS, 0x57, i_ll) \
|
||||
V(I64LeU, 0x58, i_ll) \
|
||||
V(I64GeS, 0x59, i_ll) \
|
||||
V(I64GeU, 0x5a, i_ll) \
|
||||
V(F32Eq, 0x5b, i_ff) \
|
||||
V(F32Ne, 0x5c, i_ff) \
|
||||
V(F32Lt, 0x5d, i_ff) \
|
||||
V(F32Gt, 0x5e, i_ff) \
|
||||
V(F32Le, 0x5f, i_ff) \
|
||||
V(F32Ge, 0x60, i_ff) \
|
||||
V(F64Eq, 0x61, i_dd) \
|
||||
V(F64Ne, 0x62, i_dd) \
|
||||
V(F64Lt, 0x63, i_dd) \
|
||||
V(F64Gt, 0x64, i_dd) \
|
||||
V(F64Le, 0x65, i_dd) \
|
||||
V(F64Ge, 0x66, i_dd) \
|
||||
V(I32Clz, 0x67, i_i) \
|
||||
V(I32Ctz, 0x68, i_i) \
|
||||
V(I32Popcnt, 0x69, i_i) \
|
||||
V(I32Add, 0x6a, i_ii) \
|
||||
V(I32Sub, 0x6b, i_ii) \
|
||||
V(I32Mul, 0x6c, i_ii) \
|
||||
V(I32DivS, 0x6d, i_ii) \
|
||||
V(I32DivU, 0x6e, i_ii) \
|
||||
V(I32RemS, 0x6f, i_ii) \
|
||||
V(I32RemU, 0x70, i_ii) \
|
||||
V(I32And, 0x71, i_ii) \
|
||||
V(I32Ior, 0x72, i_ii) \
|
||||
V(I32Xor, 0x73, i_ii) \
|
||||
V(I32Shl, 0x74, i_ii) \
|
||||
V(I32ShrS, 0x75, i_ii) \
|
||||
V(I32ShrU, 0x76, i_ii) \
|
||||
V(I32Rol, 0x77, i_ii) \
|
||||
V(I32Ror, 0x78, i_ii) \
|
||||
V(I64Clz, 0x79, l_l) \
|
||||
V(I64Ctz, 0x7a, l_l) \
|
||||
V(I64Popcnt, 0x7b, l_l) \
|
||||
V(I64Add, 0x7c, l_ll) \
|
||||
V(I64Sub, 0x7d, l_ll) \
|
||||
V(I64Mul, 0x7e, l_ll) \
|
||||
V(I64DivS, 0x7f, l_ll) \
|
||||
V(I64DivU, 0x80, l_ll) \
|
||||
V(I64RemS, 0x81, l_ll) \
|
||||
V(I64RemU, 0x82, l_ll) \
|
||||
V(I64And, 0x83, l_ll) \
|
||||
V(I64Ior, 0x84, l_ll) \
|
||||
V(I64Xor, 0x85, l_ll) \
|
||||
V(I64Shl, 0x86, l_ll) \
|
||||
V(I64ShrS, 0x87, l_ll) \
|
||||
V(I64ShrU, 0x88, l_ll) \
|
||||
V(I64Rol, 0x89, l_ll) \
|
||||
V(I64Ror, 0x8a, l_ll) \
|
||||
V(F32Abs, 0x8b, f_f) \
|
||||
V(F32Neg, 0x8c, f_f) \
|
||||
V(F32Ceil, 0x8d, f_f) \
|
||||
V(F32Floor, 0x8e, f_f) \
|
||||
V(F32Trunc, 0x8f, f_f) \
|
||||
V(F32NearestInt, 0x90, f_f) \
|
||||
V(F32Sqrt, 0x91, f_f) \
|
||||
V(F32Add, 0x92, f_ff) \
|
||||
V(F32Sub, 0x93, f_ff) \
|
||||
V(F32Mul, 0x94, f_ff) \
|
||||
V(F32Div, 0x95, f_ff) \
|
||||
V(F32Min, 0x96, f_ff) \
|
||||
V(F32Max, 0x97, f_ff) \
|
||||
V(F32CopySign, 0x98, f_ff) \
|
||||
V(F64Abs, 0x99, d_d) \
|
||||
V(F64Neg, 0x9a, d_d) \
|
||||
V(F64Ceil, 0x9b, d_d) \
|
||||
V(F64Floor, 0x9c, d_d) \
|
||||
V(F64Trunc, 0x9d, d_d) \
|
||||
V(F64NearestInt, 0x9e, d_d) \
|
||||
V(F64Sqrt, 0x9f, d_d) \
|
||||
V(F64Add, 0xa0, d_dd) \
|
||||
V(F64Sub, 0xa1, d_dd) \
|
||||
V(F64Mul, 0xa2, d_dd) \
|
||||
V(F64Div, 0xa3, d_dd) \
|
||||
V(F64Min, 0xa4, d_dd) \
|
||||
V(F64Max, 0xa5, d_dd) \
|
||||
V(F64CopySign, 0xa6, d_dd) \
|
||||
V(I32ConvertI64, 0xa7, i_l) \
|
||||
V(I32SConvertF32, 0xa8, i_f) \
|
||||
V(I32UConvertF32, 0xa9, i_f) \
|
||||
V(I32SConvertF64, 0xaa, i_d) \
|
||||
V(I32UConvertF64, 0xab, i_d) \
|
||||
V(I64SConvertI32, 0xac, l_i) \
|
||||
V(I64UConvertI32, 0xad, l_i) \
|
||||
V(I64SConvertF32, 0xae, l_f) \
|
||||
V(I64UConvertF32, 0xaf, l_f) \
|
||||
V(I64SConvertF64, 0xb0, l_d) \
|
||||
V(I64UConvertF64, 0xb1, l_d) \
|
||||
V(F32SConvertI32, 0xb2, f_i) \
|
||||
V(F32UConvertI32, 0xb3, f_i) \
|
||||
V(F32SConvertI64, 0xb4, f_l) \
|
||||
V(F32UConvertI64, 0xb5, f_l) \
|
||||
V(F32ConvertF64, 0xb6, f_d) \
|
||||
V(F64SConvertI32, 0xb7, d_i) \
|
||||
V(F64UConvertI32, 0xb8, d_i) \
|
||||
V(F64SConvertI64, 0xb9, d_l) \
|
||||
V(F64UConvertI64, 0xba, d_l) \
|
||||
V(F64ConvertF32, 0xbb, d_f) \
|
||||
V(I32ReinterpretF32, 0xbc, i_f) \
|
||||
V(I64ReinterpretF64, 0xbd, l_d) \
|
||||
V(F32ReinterpretI32, 0xbe, f_i) \
|
||||
V(F64ReinterpretI64, 0xbf, d_l) \
|
||||
V(I32SExtendI8, 0xc0, i_i) \
|
||||
V(I32SExtendI16, 0xc1, i_i) \
|
||||
V(I64SExtendI8, 0xc2, l_l) \
|
||||
V(I64SExtendI16, 0xc3, l_l) \
|
||||
|
||||
// The following opcodes can be used as constant expressions under
|
||||
// --experimental-wasm-extended-const.
|
||||
#define FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(V) \
|
||||
V(I32Add, 0x6a, i_ii) \
|
||||
V(I32Sub, 0x6b, i_ii) \
|
||||
V(I32Mul, 0x6c, i_ii) \
|
||||
V(I64Add, 0x7c, l_ll) \
|
||||
V(I64Sub, 0x7d, l_ll) \
|
||||
V(I64Mul, 0x7e, l_ll)
|
||||
|
||||
#define FOREACH_SIMPLE_NON_CONST_OPCODE(V) \
|
||||
V(I32Eqz, 0x45, i_i) \
|
||||
V(I32Eq, 0x46, i_ii) \
|
||||
V(I32Ne, 0x47, i_ii) \
|
||||
V(I32LtS, 0x48, i_ii) \
|
||||
V(I32LtU, 0x49, i_ii) \
|
||||
V(I32GtS, 0x4a, i_ii) \
|
||||
V(I32GtU, 0x4b, i_ii) \
|
||||
V(I32LeS, 0x4c, i_ii) \
|
||||
V(I32LeU, 0x4d, i_ii) \
|
||||
V(I32GeS, 0x4e, i_ii) \
|
||||
V(I32GeU, 0x4f, i_ii) \
|
||||
V(I64Eqz, 0x50, i_l) \
|
||||
V(I64Eq, 0x51, i_ll) \
|
||||
V(I64Ne, 0x52, i_ll) \
|
||||
V(I64LtS, 0x53, i_ll) \
|
||||
V(I64LtU, 0x54, i_ll) \
|
||||
V(I64GtS, 0x55, i_ll) \
|
||||
V(I64GtU, 0x56, i_ll) \
|
||||
V(I64LeS, 0x57, i_ll) \
|
||||
V(I64LeU, 0x58, i_ll) \
|
||||
V(I64GeS, 0x59, i_ll) \
|
||||
V(I64GeU, 0x5a, i_ll) \
|
||||
V(F32Eq, 0x5b, i_ff) \
|
||||
V(F32Ne, 0x5c, i_ff) \
|
||||
V(F32Lt, 0x5d, i_ff) \
|
||||
V(F32Gt, 0x5e, i_ff) \
|
||||
V(F32Le, 0x5f, i_ff) \
|
||||
V(F32Ge, 0x60, i_ff) \
|
||||
V(F64Eq, 0x61, i_dd) \
|
||||
V(F64Ne, 0x62, i_dd) \
|
||||
V(F64Lt, 0x63, i_dd) \
|
||||
V(F64Gt, 0x64, i_dd) \
|
||||
V(F64Le, 0x65, i_dd) \
|
||||
V(F64Ge, 0x66, i_dd) \
|
||||
V(I32Clz, 0x67, i_i) \
|
||||
V(I32Ctz, 0x68, i_i) \
|
||||
V(I32Popcnt, 0x69, i_i) \
|
||||
V(I32DivS, 0x6d, i_ii) \
|
||||
V(I32DivU, 0x6e, i_ii) \
|
||||
V(I32RemS, 0x6f, i_ii) \
|
||||
V(I32RemU, 0x70, i_ii) \
|
||||
V(I32And, 0x71, i_ii) \
|
||||
V(I32Ior, 0x72, i_ii) \
|
||||
V(I32Xor, 0x73, i_ii) \
|
||||
V(I32Shl, 0x74, i_ii) \
|
||||
V(I32ShrS, 0x75, i_ii) \
|
||||
V(I32ShrU, 0x76, i_ii) \
|
||||
V(I32Rol, 0x77, i_ii) \
|
||||
V(I32Ror, 0x78, i_ii) \
|
||||
V(I64Clz, 0x79, l_l) \
|
||||
V(I64Ctz, 0x7a, l_l) \
|
||||
V(I64Popcnt, 0x7b, l_l) \
|
||||
V(I64DivS, 0x7f, l_ll) \
|
||||
V(I64DivU, 0x80, l_ll) \
|
||||
V(I64RemS, 0x81, l_ll) \
|
||||
V(I64RemU, 0x82, l_ll) \
|
||||
V(I64And, 0x83, l_ll) \
|
||||
V(I64Ior, 0x84, l_ll) \
|
||||
V(I64Xor, 0x85, l_ll) \
|
||||
V(I64Shl, 0x86, l_ll) \
|
||||
V(I64ShrS, 0x87, l_ll) \
|
||||
V(I64ShrU, 0x88, l_ll) \
|
||||
V(I64Rol, 0x89, l_ll) \
|
||||
V(I64Ror, 0x8a, l_ll) \
|
||||
V(F32Abs, 0x8b, f_f) \
|
||||
V(F32Neg, 0x8c, f_f) \
|
||||
V(F32Ceil, 0x8d, f_f) \
|
||||
V(F32Floor, 0x8e, f_f) \
|
||||
V(F32Trunc, 0x8f, f_f) \
|
||||
V(F32NearestInt, 0x90, f_f) \
|
||||
V(F32Sqrt, 0x91, f_f) \
|
||||
V(F32Add, 0x92, f_ff) \
|
||||
V(F32Sub, 0x93, f_ff) \
|
||||
V(F32Mul, 0x94, f_ff) \
|
||||
V(F32Div, 0x95, f_ff) \
|
||||
V(F32Min, 0x96, f_ff) \
|
||||
V(F32Max, 0x97, f_ff) \
|
||||
V(F32CopySign, 0x98, f_ff) \
|
||||
V(F64Abs, 0x99, d_d) \
|
||||
V(F64Neg, 0x9a, d_d) \
|
||||
V(F64Ceil, 0x9b, d_d) \
|
||||
V(F64Floor, 0x9c, d_d) \
|
||||
V(F64Trunc, 0x9d, d_d) \
|
||||
V(F64NearestInt, 0x9e, d_d) \
|
||||
V(F64Sqrt, 0x9f, d_d) \
|
||||
V(F64Add, 0xa0, d_dd) \
|
||||
V(F64Sub, 0xa1, d_dd) \
|
||||
V(F64Mul, 0xa2, d_dd) \
|
||||
V(F64Div, 0xa3, d_dd) \
|
||||
V(F64Min, 0xa4, d_dd) \
|
||||
V(F64Max, 0xa5, d_dd) \
|
||||
V(F64CopySign, 0xa6, d_dd) \
|
||||
V(I32ConvertI64, 0xa7, i_l) \
|
||||
V(I32SConvertF32, 0xa8, i_f) \
|
||||
V(I32UConvertF32, 0xa9, i_f) \
|
||||
V(I32SConvertF64, 0xaa, i_d) \
|
||||
V(I32UConvertF64, 0xab, i_d) \
|
||||
V(I64SConvertI32, 0xac, l_i) \
|
||||
V(I64UConvertI32, 0xad, l_i) \
|
||||
V(I64SConvertF32, 0xae, l_f) \
|
||||
V(I64UConvertF32, 0xaf, l_f) \
|
||||
V(I64SConvertF64, 0xb0, l_d) \
|
||||
V(I64UConvertF64, 0xb1, l_d) \
|
||||
V(F32SConvertI32, 0xb2, f_i) \
|
||||
V(F32UConvertI32, 0xb3, f_i) \
|
||||
V(F32SConvertI64, 0xb4, f_l) \
|
||||
V(F32UConvertI64, 0xb5, f_l) \
|
||||
V(F32ConvertF64, 0xb6, f_d) \
|
||||
V(F64SConvertI32, 0xb7, d_i) \
|
||||
V(F64UConvertI32, 0xb8, d_i) \
|
||||
V(F64SConvertI64, 0xb9, d_l) \
|
||||
V(F64UConvertI64, 0xba, d_l) \
|
||||
V(F64ConvertF32, 0xbb, d_f) \
|
||||
V(I32ReinterpretF32, 0xbc, i_f) \
|
||||
V(I64ReinterpretF64, 0xbd, l_d) \
|
||||
V(F32ReinterpretI32, 0xbe, f_i) \
|
||||
V(F64ReinterpretI64, 0xbf, d_l) \
|
||||
V(I32SExtendI8, 0xc0, i_i) \
|
||||
V(I32SExtendI16, 0xc1, i_i) \
|
||||
V(I64SExtendI8, 0xc2, l_l) \
|
||||
V(I64SExtendI16, 0xc3, l_l) \
|
||||
V(I64SExtendI32, 0xc4, l_l)
|
||||
|
||||
#define FOREACH_SIMPLE_OPCODE(V) \
|
||||
FOREACH_SIMPLE_EXTENDED_CONST_OPCODE(V) \
|
||||
FOREACH_SIMPLE_NON_CONST_OPCODE(V)
|
||||
|
||||
#define FOREACH_SIMPLE_PROTOTYPE_OPCODE(V) V(RefEq, 0xd5, i_qq)
|
||||
|
||||
// For compatibility with Asm.js.
|
||||
|
@ -339,6 +339,12 @@ class InitExprInterface {
|
||||
result->init_expr = WasmInitExpr(imm.value);
|
||||
}
|
||||
|
||||
void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
|
||||
const Value& rhs, Value* result) {
|
||||
// TODO(12089): Implement.
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
|
||||
result->init_expr = WasmInitExpr::RefNullConst(type.heap_representation());
|
||||
}
|
||||
|
74
test/mjsunit/wasm/extended-constants.js
Normal file
74
test/mjsunit/wasm/extended-constants.js
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --experimental-wasm-extended-const
|
||||
|
||||
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
|
||||
(function ExtendedConstantsTestI32() {
|
||||
print(arguments.callee.name);
|
||||
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let imported_global_0 = builder.addImportedGlobal("m", "g0", kWasmI32, false);
|
||||
let imported_global_1 = builder.addImportedGlobal("m", "g1", kWasmI32, false);
|
||||
|
||||
let defined_global = builder.addGlobal(
|
||||
kWasmI32, false,
|
||||
WasmInitExpr.I32Add(
|
||||
WasmInitExpr.GlobalGet(imported_global_0),
|
||||
WasmInitExpr.I32Mul(
|
||||
WasmInitExpr.GlobalGet(imported_global_1),
|
||||
WasmInitExpr.I32Sub(
|
||||
WasmInitExpr.GlobalGet(imported_global_0),
|
||||
WasmInitExpr.I32Const(1)))));
|
||||
|
||||
builder.addExportOfKind("global", kExternalGlobal, defined_global.index);
|
||||
|
||||
let value0 = 123;
|
||||
let value1 = -450;
|
||||
|
||||
let global_obj0 = new WebAssembly.Global({value: "i32", mutable: false},
|
||||
value0);
|
||||
let global_obj1 = new WebAssembly.Global({value: "i32", mutable: false},
|
||||
value1);
|
||||
|
||||
let instance = builder.instantiate({m : {g0: global_obj0, g1: global_obj1}});
|
||||
|
||||
assertEquals(value0 + (value1 * (value0 - 1)), instance.exports.global.value);
|
||||
})();
|
||||
|
||||
(function ExtendedConstantsTestI64() {
|
||||
print(arguments.callee.name);
|
||||
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
let imported_global_0 = builder.addImportedGlobal("m", "g0", kWasmI64, false);
|
||||
let imported_global_1 = builder.addImportedGlobal("m", "g1", kWasmI64, false);
|
||||
|
||||
let defined_global = builder.addGlobal(
|
||||
kWasmI64, false,
|
||||
WasmInitExpr.I64Add(
|
||||
WasmInitExpr.GlobalGet(imported_global_0),
|
||||
WasmInitExpr.I64Mul(
|
||||
WasmInitExpr.GlobalGet(imported_global_1),
|
||||
WasmInitExpr.I64Sub(
|
||||
WasmInitExpr.GlobalGet(imported_global_0),
|
||||
WasmInitExpr.I64Const(1)))));
|
||||
|
||||
builder.addExportOfKind("global", kExternalGlobal, defined_global.index);
|
||||
|
||||
let value0 = 123n;
|
||||
let value1 = -450n;
|
||||
|
||||
let global_obj0 = new WebAssembly.Global({value: "i64", mutable: false},
|
||||
value0);
|
||||
let global_obj1 = new WebAssembly.Global({value: "i64", mutable: false},
|
||||
value1);
|
||||
|
||||
let instance = builder.instantiate({m : {g0: global_obj0, g1: global_obj1}});
|
||||
|
||||
assertEquals(value0 + (value1 * (value0 - 1n)),
|
||||
instance.exports.global.value);
|
||||
})();
|
@ -1016,6 +1016,16 @@ class Binary {
|
||||
case kSimdPrefix:
|
||||
this.emit_bytes(wasmS128Const(expr.value));
|
||||
break;
|
||||
case kExprI32Add:
|
||||
case kExprI32Sub:
|
||||
case kExprI32Mul:
|
||||
case kExprI64Add:
|
||||
case kExprI64Sub:
|
||||
case kExprI64Mul:
|
||||
this.emit_init_expr_recursive(expr.operands[0]);
|
||||
this.emit_init_expr_recursive(expr.operands[1]);
|
||||
this.emit_u8(expr.kind);
|
||||
break;
|
||||
case kExprRefFunc:
|
||||
this.emit_u8(kExprRefFunc);
|
||||
this.emit_u32v(expr.value);
|
||||
@ -1192,6 +1202,24 @@ class WasmInitExpr {
|
||||
static S128Const(value) {
|
||||
return {kind: kSimdPrefix, value: value};
|
||||
}
|
||||
static I32Add(lhs, rhs) {
|
||||
return {kind: kExprI32Add, operands: [lhs, rhs]};
|
||||
}
|
||||
static I32Sub(lhs, rhs) {
|
||||
return {kind: kExprI32Sub, operands: [lhs, rhs]};
|
||||
}
|
||||
static I32Mul(lhs, rhs) {
|
||||
return {kind: kExprI32Mul, operands: [lhs, rhs]};
|
||||
}
|
||||
static I64Add(lhs, rhs) {
|
||||
return {kind: kExprI64Add, operands: [lhs, rhs]};
|
||||
}
|
||||
static I64Sub(lhs, rhs) {
|
||||
return {kind: kExprI64Sub, operands: [lhs, rhs]};
|
||||
}
|
||||
static I64Mul(lhs, rhs) {
|
||||
return {kind: kExprI64Mul, operands: [lhs, rhs]};
|
||||
}
|
||||
static GlobalGet(index) {
|
||||
return {kind: kExprGlobalGet, value: index};
|
||||
}
|
||||
|
@ -2048,6 +2048,65 @@ TEST_F(WasmModuleVerifyTest, ElementSectionGlobalGetOutOfBounds) {
|
||||
EXPECT_FAILURE_WITH_MSG(data, "Invalid global index: 0");
|
||||
}
|
||||
|
||||
// Make sure extended constants do not work without the experimental feature.
|
||||
TEST_F(WasmModuleVerifyTest, ExtendedConstantsFail) {
|
||||
static const byte data[] = {
|
||||
SECTION(Import, ENTRY_COUNT(1), // one import
|
||||
0x01, 'm', 0x01, 'g', // module, name
|
||||
kExternalGlobal, kI32Code, 0), // type, mutability
|
||||
SECTION(Global, ENTRY_COUNT(1), // one defined global
|
||||
kI32Code, 0, // type, mutability
|
||||
// initializer
|
||||
kExprGlobalGet, 0x00, kExprGlobalGet, 0x00, kExprI32Add,
|
||||
kExprEnd)};
|
||||
EXPECT_FAILURE_WITH_MSG(data,
|
||||
"opcode i32.add is not allowed in init. expressions");
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, ExtendedConstantsI32) {
|
||||
WASM_FEATURE_SCOPE(extended_const);
|
||||
static const byte data[] = {
|
||||
SECTION(Import, ENTRY_COUNT(1), // one import
|
||||
0x01, 'm', 0x01, 'g', // module, name
|
||||
kExternalGlobal, kI32Code, 0), // type, mutability
|
||||
SECTION(Global, ENTRY_COUNT(1), // one defined global
|
||||
kI32Code, 0, // type, mutability
|
||||
// initializer
|
||||
kExprGlobalGet, 0x00, kExprGlobalGet, 0x00, kExprI32Add,
|
||||
kExprGlobalGet, 0x00, kExprI32Sub, kExprGlobalGet, 0x00,
|
||||
kExprI32Mul, kExprEnd)};
|
||||
EXPECT_VERIFIES(data);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, ExtendedConstantsI64) {
|
||||
WASM_FEATURE_SCOPE(extended_const);
|
||||
static const byte data[] = {
|
||||
SECTION(Import, ENTRY_COUNT(1), // one import
|
||||
0x01, 'm', 0x01, 'g', // module, name
|
||||
kExternalGlobal, kI64Code, 0), // type, mutability
|
||||
SECTION(Global, ENTRY_COUNT(1), // one defined global
|
||||
kI64Code, 0, // type, mutability
|
||||
// initializer
|
||||
kExprGlobalGet, 0x00, kExprGlobalGet, 0x00, kExprI64Add,
|
||||
kExprGlobalGet, 0x00, kExprI64Sub, kExprGlobalGet, 0x00,
|
||||
kExprI64Mul, kExprEnd)};
|
||||
EXPECT_VERIFIES(data);
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, ExtendedConstantsTypeError) {
|
||||
WASM_FEATURE_SCOPE(extended_const);
|
||||
static const byte data[] = {
|
||||
SECTION(Import, ENTRY_COUNT(1), // one import
|
||||
0x01, 'm', 0x01, 'g', // module, name
|
||||
kExternalGlobal, kI32Code, 0), // type, mutability
|
||||
SECTION(Global, ENTRY_COUNT(1), // one defined global
|
||||
kI32Code, 0, // type, mutability
|
||||
// initializer
|
||||
kExprGlobalGet, 0x00, kExprI64Const, 1, kExprI32Add, kExprEnd)};
|
||||
EXPECT_FAILURE_WITH_MSG(
|
||||
data, "i32.add[1] expected type i32, found i64.const of type i64");
|
||||
}
|
||||
|
||||
TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
|
||||
static const byte data[] = {
|
||||
// sig#0 -------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user