Commit 8a06685d authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Support v128 global init expressions

v128.const (kExprS128) is the only constant expression supported
(similar to the other value types).

Bug: v8:10731
Change-Id: I9b11b47a851903dfd79d3590eff67b615057f81c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2308389
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68975}
parent 32ff8961
...@@ -122,6 +122,8 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) { ...@@ -122,6 +122,8 @@ ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
return kWasmF32; return kWasmF32;
case WasmInitExpr::kF64Const: case WasmInitExpr::kF64Const:
return kWasmF64; return kWasmF64;
case WasmInitExpr::kS128Const:
return kWasmS128;
case WasmInitExpr::kRefFuncConst: case WasmInitExpr::kRefFuncConst:
return ValueType::Ref(HeapType::kFunc, kNonNullable); return ValueType::Ref(HeapType::kFunc, kNonNullable);
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
...@@ -1727,6 +1729,19 @@ class ModuleDecoderImpl : public Decoder { ...@@ -1727,6 +1729,19 @@ class ModuleDecoderImpl : public Decoder {
module->functions[imm.index].declared = true; module->functions[imm.index].declared = true;
break; break;
} }
case kSimdPrefix: {
opcode = read_prefixed_opcode<validate>(pc(), &len);
if (V8_UNLIKELY(opcode != kExprS128Const)) {
errorf(pc(), "invalid SIMD opcode 0x%x in global initializer",
opcode);
break;
}
Simd128Immediate<validate> imm(this, pc() + len + 1);
len += 1 + kSimd128Size;
stack.emplace_back(imm.value);
break;
}
case kGCPrefix: { case kGCPrefix: {
opcode = read_prefixed_opcode<validate>(pc(), &len); opcode = read_prefixed_opcode<validate>(pc(), &len);
switch (opcode) { switch (opcode) {
......
...@@ -1466,6 +1466,7 @@ Handle<Object> InstanceBuilder::RecursivelyEvaluateGlobalInitializer( ...@@ -1466,6 +1466,7 @@ Handle<Object> InstanceBuilder::RecursivelyEvaluateGlobalInitializer(
case WasmInitExpr::kI64Const: case WasmInitExpr::kI64Const:
case WasmInitExpr::kF32Const: case WasmInitExpr::kF32Const:
case WasmInitExpr::kF64Const: case WasmInitExpr::kF64Const:
case WasmInitExpr::kS128Const:
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
case WasmInitExpr::kRefFuncConst: case WasmInitExpr::kRefFuncConst:
case WasmInitExpr::kNone: case WasmInitExpr::kNone:
...@@ -1534,6 +1535,12 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) { ...@@ -1534,6 +1535,12 @@ void InstanceBuilder::InitGlobals(Handle<WasmInstanceObject> instance) {
WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
global.init.immediate().f64_const); global.init.immediate().f64_const);
break; break;
case WasmInitExpr::kS128Const:
DCHECK(enabled_.has_simd());
WriteLittleEndianValue<uint8_t[kSimd128Size]>(
GetRawGlobalPtr<uint8_t[kSimd128Size]>(global),
global.init.immediate().s128_const);
break;
case WasmInitExpr::kRefNullConst: case WasmInitExpr::kRefNullConst:
DCHECK(enabled_.has_reftypes() || enabled_.has_eh()); DCHECK(enabled_.has_reftypes() || enabled_.has_eh());
if (global.imported) break; // We already initialized imported globals. if (global.imported) break; // We already initialized imported globals.
......
...@@ -441,6 +441,11 @@ void WriteGlobalInitializer(ZoneBuffer* buffer, const WasmInitExpr& init, ...@@ -441,6 +441,11 @@ void WriteGlobalInitializer(ZoneBuffer* buffer, const WasmInitExpr& init,
buffer->write_u8(kExprF64Const); buffer->write_u8(kExprF64Const);
buffer->write_f64(init.immediate().f64_const); buffer->write_f64(init.immediate().f64_const);
break; break;
case WasmInitExpr::kS128Const:
buffer->write_u8(kSimdPrefix);
buffer->write_u8(kExprS128Const & 0xFF);
buffer->write(init.immediate().s128_const, kSimd128Size);
break;
case WasmInitExpr::kGlobalGet: case WasmInitExpr::kGlobalGet:
buffer->write_u8(kExprGlobalGet); buffer->write_u8(kExprGlobalGet);
buffer->write_u32v(init.immediate().index); buffer->write_u32v(init.immediate().index);
......
...@@ -761,6 +761,7 @@ class WasmInitExpr { ...@@ -761,6 +761,7 @@ class WasmInitExpr {
kI64Const, kI64Const,
kF32Const, kF32Const,
kF64Const, kF64Const,
kS128Const,
kRefNullConst, kRefNullConst,
kRefFuncConst, kRefFuncConst,
kRttCanon, kRttCanon,
...@@ -772,6 +773,7 @@ class WasmInitExpr { ...@@ -772,6 +773,7 @@ class WasmInitExpr {
int64_t i64_const; int64_t i64_const;
float f32_const; float f32_const;
double f64_const; double f64_const;
uint8_t s128_const[kSimd128Size];
uint32_t index; uint32_t index;
HeapType::Representation heap_type; HeapType::Representation heap_type;
}; };
...@@ -789,6 +791,9 @@ class WasmInitExpr { ...@@ -789,6 +791,9 @@ class WasmInitExpr {
explicit WasmInitExpr(double v) : kind_(kF64Const) { explicit WasmInitExpr(double v) : kind_(kF64Const) {
immediate_.f64_const = v; immediate_.f64_const = v;
} }
explicit WasmInitExpr(uint8_t v[kSimd128Size]) : kind_(kS128Const) {
memcpy(immediate_.s128_const, v, kSimd128Size);
}
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmInitExpr); MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmInitExpr);
...@@ -849,6 +854,9 @@ class WasmInitExpr { ...@@ -849,6 +854,9 @@ class WasmInitExpr {
return immediate().f32_const == other.immediate().f32_const; return immediate().f32_const == other.immediate().f32_const;
case kF64Const: case kF64Const:
return immediate().f64_const == other.immediate().f64_const; return immediate().f64_const == other.immediate().f64_const;
case kS128Const:
return 0 == memcmp(immediate().s128_const, other.immediate().s128_const,
kSimd128Size);
case kRefNullConst: case kRefNullConst:
case kRttCanon: case kRttCanon:
return immediate().heap_type == other.immediate().heap_type; return immediate().heap_type == other.immediate().heap_type;
......
...@@ -268,6 +268,24 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) { ...@@ -268,6 +268,24 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
EXPECT_OFF_END_FAILURE(data, 1); EXPECT_OFF_END_FAILURE(data, 1);
} }
TEST_F(WasmModuleVerifyTest, S128Global) {
WASM_FEATURE_SCOPE(simd);
uint8_t v[kSimd128Size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
static const byte data[] = {SECTION(Global, // --
ENTRY_COUNT(1), // --
kLocalS128, // memory type
0, // immutable
WASM_SIMD_CONSTANT(v), kExprEnd)};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
const WasmGlobal* global = &result.value()->globals.back();
EXPECT_EQ(kWasmS128, global->type);
EXPECT_EQ(0u, global->offset);
EXPECT_FALSE(global->mutability);
EXPECT_EQ(WasmInitExpr::kS128Const, global->init.kind());
EXPECT_EQ(0, memcmp(global->init.immediate().s128_const, v, kSimd128Size));
}
TEST_F(WasmModuleVerifyTest, ExternRefGlobal) { TEST_F(WasmModuleVerifyTest, ExternRefGlobal) {
WASM_FEATURE_SCOPE(reftypes); WASM_FEATURE_SCOPE(reftypes);
WASM_FEATURE_SCOPE(bulk_memory); WASM_FEATURE_SCOPE(bulk_memory);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment