Files
Kmake/deps/v8/test/mjsunit/regress/wasm/regress-1514072-2.js
2026-05-26 23:36:42 -07:00

69 lines
2.7 KiB
JavaScript

// Copyright 2024 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: --no-wasm-loop-unrolling --no-wasm-loop-peeling
d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
let structA = builder.addStruct([makeField(kWasmI32, true)]);
let structB = builder.addStruct([makeField(kWasmI64, true)]);
builder.addFunction('main', makeSig([kWasmI32], [kWasmI32]))
.addLocals(kWasmAnyRef, 1)
.addLocals(kWasmI32, 1)
.addBody([
// Initialize local[1] with structA.
kGCPrefix, kExprStructNewDefault, structA,
kExprLocalSet, 1,
kExprLoop, 0x7f,
// Just a useless branch to move the ref.test out of the loop header.
kExprI32Const, 1,
kExprIf, kWasmVoid,
kExprEnd,
// ref.test if local[1] is of type structA.
// This is guaranteed to succeed on the first iteration.
// The else branch is marked as unreachable.
kExprLocalGet, 1,
kGCPrefix, kExprRefTest, structA,
kExprIf, kWasmVoid,
// This branch is taken on the first iteration.
kExprElse,
// This branch is taken on subsequent iterations.
kExprEnd,
// Push local[1] onto the value stack.
kExprLocalGet, 1,
// Update local[1] to a different type.
// This will cause the analyzer having to revisit the loop a second time
// as the LoopPhi for local[1] has now a different type.
...wasmI64Const(0x1234567812345678n),
kGCPrefix, kExprStructNew, structB,
kExprLocalSet, 1,
// Cast the old local[1] value on the stack to structA.
// This is guaranteed to succeed on the first iteration.
// It is guaranteed to fail on subsequent iterations, however the
// WasmGCTypeReducer ignores this as the else branch of the if following
// the ref.test is still marked as unreachable when revisiting the loop
// a second time.
kGCPrefix, kExprRefCast, structA,
// <-- The value here is structB in the second iteration on which we have
// a type confusion as the static type is structA.
// Read the i32 field from the structA.
// On the second iteration this is going to read one half of the i64 of
// structB.
kGCPrefix, kExprStructGet, structA, 0,
kExprLocalTee, 2,
kExprLocalGet, 2,
// Compare the field with 0. If it is zero, repeat the loop, if it isn't
// zero return the value.
kExprI32Eqz,
kExprBrIf, 0,
kExprReturn,
kExprEnd,
]).exportFunc();
const instance = builder.instantiate();
assertTraps(kTrapIllegalCast, () => instance.exports.main(1));