wazevo: scaffolds amd64 backend (#1893)

Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
This commit is contained in:
Takeshi Yoneda
2024-01-04 08:34:32 -08:00
committed by GitHub
parent 498d4b4f72
commit 85c0c791a0
6 changed files with 308 additions and 43 deletions

View File

@@ -0,0 +1,188 @@
package amd64
import (
"context"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
"github.com/tetratelabs/wazero/internal/engine/wazevo/wazevoapi"
)
// NewBackend returns a new backend for arm64.
func NewBackend() backend.Machine {
m := &machine{}
return m
}
// machine implements backend.Machine for amd64.
type machine struct {
stackBoundsCheckDisabled bool
}
// DisableStackCheck implements backend.Machine.
func (m *machine) DisableStackCheck() {
m.stackBoundsCheckDisabled = true
}
// RegisterInfo implements backend.Machine.
func (m *machine) RegisterInfo() *regalloc.RegisterInfo {
// TODO implement me
panic("implement me")
}
// InitializeABI implements backend.Machine.
func (m *machine) InitializeABI(sig *ssa.Signature) {
// TODO implement me
panic("implement me")
}
// ABI implements backend.Machine.
func (m *machine) ABI() backend.FunctionABI {
// TODO implement me
panic("implement me")
}
// SetCompiler implements backend.Machine.
func (m *machine) SetCompiler(compiler backend.Compiler) {
// TODO implement me
panic("implement me")
}
// StartLoweringFunction implements backend.Machine.
func (m *machine) StartLoweringFunction(maximumBlockID ssa.BasicBlockID) {
// TODO implement me
panic("implement me")
}
// StartBlock implements backend.Machine.
func (m *machine) StartBlock(block ssa.BasicBlock) {
// TODO implement me
panic("implement me")
}
// LowerSingleBranch implements backend.Machine.
func (m *machine) LowerSingleBranch(b *ssa.Instruction) {
// TODO implement me
panic("implement me")
}
// LowerConditionalBranch implements backend.Machine.
func (m *machine) LowerConditionalBranch(b *ssa.Instruction) {
// TODO implement me
panic("implement me")
}
// LowerInstr implements backend.Machine.
func (m *machine) LowerInstr(instruction *ssa.Instruction) {
// TODO implement me
panic("implement me")
}
// EndBlock implements backend.Machine.
func (m *machine) EndBlock() {
// TODO implement me
panic("implement me")
}
// LinkAdjacentBlocks implements backend.Machine.
func (m *machine) LinkAdjacentBlocks(prev, next ssa.BasicBlock) {
// TODO implement me
panic("implement me")
}
// EndLoweringFunction implements backend.Machine.
func (m *machine) EndLoweringFunction() {
// TODO implement me
panic("implement me")
}
// Reset implements backend.Machine.
func (m *machine) Reset() {
// TODO implement me
panic("implement me")
}
// FlushPendingInstructions implements backend.Machine.
func (m *machine) FlushPendingInstructions() {
// TODO implement me
panic("implement me")
}
// InsertMove implements backend.Machine.
func (m *machine) InsertMove(dst, src regalloc.VReg, typ ssa.Type) {
// TODO implement me
panic("implement me")
}
// InsertReturn implements backend.Machine.
func (m *machine) InsertReturn() {
// TODO implement me
panic("implement me")
}
// InsertLoadConstant implements backend.Machine.
func (m *machine) InsertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg) {
// TODO implement me
panic("implement me")
}
// Format implements backend.Machine.
func (m *machine) Format() string {
// TODO implement me
panic("implement me")
}
// Function implements backend.Machine.
func (m *machine) Function() regalloc.Function {
// TODO implement me
panic("implement me")
}
// SetupPrologue implements backend.Machine.
func (m *machine) SetupPrologue() {
// TODO implement me
panic("implement me")
}
// SetupEpilogue implements backend.Machine.
func (m *machine) SetupEpilogue() {
// TODO implement me
panic("implement me")
}
// ResolveRelativeAddresses implements backend.Machine.
func (m *machine) ResolveRelativeAddresses(ctx context.Context) {
// TODO implement me
panic("implement me")
}
// ResolveRelocations implements backend.Machine.
func (m *machine) ResolveRelocations(refToBinaryOffset map[ssa.FuncRef]int, binary []byte, relocations []backend.RelocationInfo) {
// TODO implement me
panic("implement me")
}
// Encode implements backend.Machine.
func (m *machine) Encode() {
// TODO implement me
panic("implement me")
}
// CompileGoFunctionTrampoline implements backend.Machine.
func (m *machine) CompileGoFunctionTrampoline(exitCode wazevoapi.ExitCode, sig *ssa.Signature, needModuleContextPtr bool) []byte {
// TODO implement me
panic("implement me")
}
// CompileStackGrowCallSequence implements backend.Machine.
func (m *machine) CompileStackGrowCallSequence() []byte {
// TODO implement me
panic("implement me")
}
// CompileEntryPreamble implements backend.Machine.
func (m *machine) CompileEntryPreamble(signature *ssa.Signature) []byte {
// TODO implement me
panic("implement me")
}

View File

@@ -0,0 +1,11 @@
package amd64
func UnwindStack(sp, top uintptr, returnAddresses []uintptr) []uintptr {
panic("implement me")
}
// GoCallStackView is a function to get a view of the stack before a Go call, which
// is the view of the stack allocated in CompileGoFunctionTrampoline.
func GoCallStackView(stackPointerBeforeGoCall *uint64) []uint64 {
panic("implement me")
}

View File

@@ -6,6 +6,7 @@ import (
"encoding/binary"
"fmt"
"math"
"runtime"
"testing"
"github.com/tetratelabs/wazero"
@@ -29,6 +30,13 @@ const (
v128 = wasm.ValueTypeV128
)
// TODO: delete once we complete the implementation for amd64.
func skipOnAmd64(t *testing.T) {
if runtime.GOARCH == "amd64" {
t.Skip("skip on amd64")
}
}
func TestE2E(t *testing.T) {
tmp := t.TempDir()
type callCase struct {
@@ -40,9 +48,11 @@ func TestE2E(t *testing.T) {
name string
imported, m *wasm.Module
calls []callCase
skipAMD64 bool
}{
{
name: "selects", m: testcases.Selects.Module,
skipAMD64: true,
calls: []callCase{
{
params: []uint64{
@@ -62,22 +72,26 @@ func TestE2E(t *testing.T) {
},
{
name: "swap", m: testcases.SwapParamAndReturn.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{math.MaxUint32, math.MaxInt32}, expResults: []uint64{math.MaxInt32, math.MaxUint32}},
},
},
{
name: "consts", m: testcases.Constants.Module,
skipAMD64: true,
calls: []callCase{
{expResults: []uint64{1, 2, uint64(math.Float32bits(32.0)), math.Float64bits(64.0)}},
},
},
{
name: "unreachable", m: testcases.Unreachable.Module,
calls: []callCase{{expErr: "unreachable"}},
skipAMD64: true,
calls: []callCase{{expErr: "unreachable"}},
},
{
name: "fibonacci_recursive", m: testcases.FibonacciRecursive.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0}, expResults: []uint64{0}},
{params: []uint64{1}, expResults: []uint64{1}},
@@ -96,14 +110,16 @@ func TestE2E(t *testing.T) {
CodeSection: []wasm.Code{{Body: []byte{wasm.OpcodeCall, 0, wasm.OpcodeEnd}}},
ExportSection: []wasm.Export{{Name: testcases.ExportedFunctionName, Index: 0, Type: wasm.ExternTypeFunc}},
},
skipAMD64: true,
calls: []callCase{
{expErr: "stack overflow"}, {expErr: "stack overflow"}, {expErr: "stack overflow"}, {expErr: "stack overflow"},
},
},
{
name: "imported_function_call",
imported: testcases.ImportedFunctionCall.Imported,
m: testcases.ImportedFunctionCall.Module,
name: "imported_function_call",
imported: testcases.ImportedFunctionCall.Imported,
m: testcases.ImportedFunctionCall.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0}, expResults: []uint64{0}},
{params: []uint64{2}, expResults: []uint64{2 * 2}},
@@ -114,8 +130,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "memory_store_basic",
m: testcases.MemoryStoreBasic.Module,
name: "memory_store_basic",
m: testcases.MemoryStoreBasic.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0, 0xf}, expResults: []uint64{0xf}},
{params: []uint64{256, 0xff}, expResults: []uint64{0xff}},
@@ -125,8 +142,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "memory_load_basic",
m: testcases.MemoryLoadBasic.Module,
name: "memory_load_basic",
m: testcases.MemoryLoadBasic.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0}, expResults: []uint64{0x03_02_01_00}},
{params: []uint64{256}, expResults: []uint64{0x03_02_01_00}},
@@ -136,8 +154,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "memory out of bounds",
m: testcases.MemoryLoadBasic.Module,
name: "memory out of bounds",
m: testcases.MemoryLoadBasic.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{uint64(wasm.MemoryPageSize)}, expErr: "out of bounds memory access"},
// We load I32, so we can't load from the last 3 bytes.
@@ -145,8 +164,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "memory_loads",
m: testcases.MemoryLoads.Module,
name: "memory_loads",
m: testcases.MemoryLoads.Module,
skipAMD64: true,
calls: []callCase{
// These expected results are derived by commenting out `configureWazevo(config)` below to run the old compiler, assuming that it is correct.
{params: []uint64{0}, expResults: []uint64{0x3020100, 0x706050403020100, 0x3020100, 0x706050403020100, 0x1211100f, 0x161514131211100f, 0x1211100f, 0x161514131211100f, 0x0, 0xf, 0x0, 0xf, 0x100, 0x100f, 0x100, 0x100f, 0x0, 0xf, 0x0, 0xf, 0x100, 0x100f, 0x100, 0x100f, 0x3020100, 0x1211100f, 0x3020100, 0x1211100f}},
@@ -160,40 +180,46 @@ func TestE2E(t *testing.T) {
},
},
{
name: "globals_get",
m: testcases.GlobalsGet.Module,
name: "globals_get",
m: testcases.GlobalsGet.Module,
skipAMD64: true,
calls: []callCase{
{expResults: []uint64{0x80000000, 0x8000000000000000, 0x7f7fffff, 0x7fefffffffffffff}},
},
},
{
name: "globals_set",
m: testcases.GlobalsSet.Module,
calls: []callCase{{expResults: []uint64{1, 2, uint64(math.Float32bits(3.0)), math.Float64bits(4.0)}}},
name: "globals_set",
m: testcases.GlobalsSet.Module,
skipAMD64: true,
calls: []callCase{{expResults: []uint64{1, 2, uint64(math.Float32bits(3.0)), math.Float64bits(4.0)}}},
},
{
name: "globals_mutable",
m: testcases.GlobalsMutable.Module,
name: "globals_mutable",
m: testcases.GlobalsMutable.Module,
skipAMD64: true,
calls: []callCase{{expResults: []uint64{
100, 200, uint64(math.Float32bits(300.0)), math.Float64bits(400.0),
1, 2, uint64(math.Float32bits(3.0)), math.Float64bits(4.0),
}}},
},
{
name: "memory_size_grow",
m: testcases.MemorySizeGrow.Module,
calls: []callCase{{expResults: []uint64{1, 2, 0xffffffff}}},
name: "memory_size_grow",
m: testcases.MemorySizeGrow.Module,
skipAMD64: true,
calls: []callCase{{expResults: []uint64{1, 2, 0xffffffff}}},
},
{
name: "imported_memory_grow",
imported: testcases.ImportedMemoryGrow.Imported,
m: testcases.ImportedMemoryGrow.Module,
calls: []callCase{{expResults: []uint64{1, 1, 11, 11}}},
name: "imported_memory_grow",
imported: testcases.ImportedMemoryGrow.Imported,
m: testcases.ImportedMemoryGrow.Module,
skipAMD64: true,
calls: []callCase{{expResults: []uint64{1, 1, 11, 11}}},
},
{
name: "call_indirect",
m: testcases.CallIndirect.Module,
// parameter == table offset.
skipAMD64: true,
calls: []callCase{
{params: []uint64{0}, expErr: "indirect call type mismatch"},
{params: []uint64{1}, expResults: []uint64{10}},
@@ -203,8 +229,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "br_table",
m: testcases.BrTable.Module,
name: "br_table",
m: testcases.BrTable.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0}, expResults: []uint64{11}},
{params: []uint64{1}, expResults: []uint64{12}},
@@ -218,8 +245,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "br_table_with_args",
m: testcases.BrTableWithArg.Module,
name: "br_table_with_args",
m: testcases.BrTableWithArg.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0, 100}, expResults: []uint64{11 + 100}},
{params: []uint64{1, 100}, expResults: []uint64{12 + 100}},
@@ -233,8 +261,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "multi_predecessor_local_ref",
m: testcases.MultiPredecessorLocalRef.Module,
name: "multi_predecessor_local_ref",
m: testcases.MultiPredecessorLocalRef.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0, 100}, expResults: []uint64{100}},
{params: []uint64{1, 100}, expResults: []uint64{1}},
@@ -242,15 +271,17 @@ func TestE2E(t *testing.T) {
},
},
{
name: "vector_bit_select",
m: testcases.VecBitSelect.Module,
name: "vector_bit_select",
m: testcases.VecBitSelect.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{1, 2, 3, 4, 5, 6}, expResults: []uint64{0x3, 0x2, 0x5, 0x6}},
},
},
{
name: "vector_shuffle",
m: testcases.VecShuffle.Module,
name: "vector_shuffle",
m: testcases.VecShuffle.Module,
skipAMD64: true,
calls: []callCase{
{params: []uint64{0x01010101, 0x02020202, 0x03030303, 0x04040404}, expResults: []uint64{0x01010101, 0x04040404}},
{params: []uint64{0x03030303, 0x04040404, 0x01010101, 0x02020202}, expResults: []uint64{0x03030303, 0x02020202}},
@@ -260,8 +291,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "vector_shuffle (1st only)",
m: testcases.VecShuffleWithLane(1, 1, 1, 1, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0, 0, 0),
name: "vector_shuffle (1st only)",
m: testcases.VecShuffleWithLane(1, 1, 1, 1, 0, 0, 0, 0, 10, 10, 10, 10, 0, 0, 0, 0),
skipAMD64: true,
calls: []callCase{
{params: []uint64{0x0000000000000b0a, 0x0c0000, 0xffffffffffffffff, 0xffffffffffffffff}, expResults: []uint64{0x0a0a0a0a0b0b0b0b, 0x0a0a0a0a0c0c0c0c}},
{params: []uint64{0x01010101, 0x02020202, 0x03030303, 0x04040404}, expResults: []uint64{0x0101010101010101, 0x101010102020202}},
@@ -272,8 +304,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "vector_shuffle (2nd only)",
m: testcases.VecShuffleWithLane(17, 17, 17, 17, 16, 16, 16, 16, 26, 26, 26, 26, 16, 16, 16, 16),
name: "vector_shuffle (2nd only)",
m: testcases.VecShuffleWithLane(17, 17, 17, 17, 16, 16, 16, 16, 26, 26, 26, 26, 16, 16, 16, 16),
skipAMD64: true,
calls: []callCase{
{params: []uint64{0xffffffffffffffff, 0xffffffffffffffff, 0x0000000000000b0a, 0x0c0000}, expResults: []uint64{0x0a0a0a0a0b0b0b0b, 0x0a0a0a0a0c0c0c0c}},
{params: []uint64{0x01010101, 0x02020202, 0x03030303, 0x04040404}, expResults: []uint64{0x303030303030303, 0x303030304040404}},
@@ -284,8 +317,9 @@ func TestE2E(t *testing.T) {
},
},
{
name: "vector_shuffle (mixed)",
m: testcases.VecShuffleWithLane(0, 17, 2, 19, 4, 21, 6, 23, 8, 25, 10, 27, 12, 29, 14, 31),
name: "vector_shuffle (mixed)",
m: testcases.VecShuffleWithLane(0, 17, 2, 19, 4, 21, 6, 23, 8, 25, 10, 27, 12, 29, 14, 31),
skipAMD64: true,
calls: []callCase{
{params: []uint64{0xff08ff07ff06ff05, 0xff04ff03ff02ff01, 0x18ff17ff16ff15ff, 0x14ff13ff12ff11ff}, expResults: []uint64{0x1808170716061505, 0x1404130312021101}},
{params: []uint64{0x01010101, 0x02020202, 0x03030303, 0x04040404}, expResults: []uint64{0x3010301, 0x4020402}},
@@ -297,6 +331,9 @@ func TestE2E(t *testing.T) {
},
} {
tc := tc
if tc.skipAMD64 {
skipOnAmd64(t)
}
t.Run(tc.name, func(t *testing.T) {
for i := 0; i < 2; i++ {
var name string
@@ -360,6 +397,7 @@ func TestE2E(t *testing.T) {
}
func TestE2E_host_functions(t *testing.T) {
skipOnAmd64(t)
var buf bytes.Buffer
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
@@ -456,6 +494,7 @@ func TestE2E_host_functions(t *testing.T) {
}
func TestE2E_stores(t *testing.T) {
skipOnAmd64(t)
config := opt.NewRuntimeConfigOptimizingCompiler()
ctx := context.Background()
@@ -523,6 +562,7 @@ func TestE2E_stores(t *testing.T) {
}
func TestE2E_reexported_memory(t *testing.T) {
skipOnAmd64(t)
m1 := &wasm.Module{
ExportSection: []wasm.Export{{Name: "mem", Type: wasm.ExternTypeMemory, Index: 0}},
MemorySection: &wasm.Memory{Min: 1},
@@ -571,6 +611,7 @@ func TestE2E_reexported_memory(t *testing.T) {
}
func TestStackUnwind_panic_in_host(t *testing.T) {
skipOnAmd64(t)
unreachable := &wasm.Module{
ImportFunctionCount: 1,
ImportSection: []wasm.Import{{Module: "host", Name: "cause_unreachable", Type: wasm.ExternTypeFunc, DescFunc: 0}},
@@ -624,6 +665,7 @@ wasm stack trace:
}
func TestStackUnwind_unreachable(t *testing.T) {
skipOnAmd64(t)
unreachable := &wasm.Module{
TypeSection: []wasm.FunctionType{{}},
ExportSection: []wasm.Export{{Name: "main", Type: wasm.ExternTypeFunc, Index: 0}},
@@ -663,6 +705,7 @@ wasm stack trace:
}
func TestListener_local(t *testing.T) {
skipOnAmd64(t)
var buf bytes.Buffer
config := opt.NewRuntimeConfigOptimizingCompiler()
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
@@ -691,6 +734,7 @@ func TestListener_local(t *testing.T) {
}
func TestListener_imported(t *testing.T) {
skipOnAmd64(t)
var buf bytes.Buffer
config := opt.NewRuntimeConfigOptimizingCompiler()
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&buf))
@@ -722,6 +766,7 @@ func TestListener_imported(t *testing.T) {
}
func TestListener_long(t *testing.T) {
skipOnAmd64(t)
pickOneParam := binaryencoding.EncodeModule(&wasm.Module{
TypeSection: []wasm.FunctionType{{Results: []wasm.ValueType{i32}, Params: []wasm.ValueType{
i32, i32, f32, f64, i64, i32, i32, v128, f32,
@@ -771,6 +816,7 @@ func TestListener_long(t *testing.T) {
}
func TestListener_long_as_is(t *testing.T) {
skipOnAmd64(t)
params := []wasm.ValueType{
i32, i64, i32, i64, i32, i64, i32, i64, i32, i64,
i32, i64, i32, i64, i32, i64, i32, i64, i32, i64,
@@ -821,6 +867,7 @@ func TestListener_long_as_is(t *testing.T) {
}
func TestListener_long_many_consts(t *testing.T) {
skipOnAmd64(t)
const paramNum = 61
var exp []uint64
@@ -867,6 +914,7 @@ func TestListener_long_many_consts(t *testing.T) {
// TestDWARF verifies that the DWARF based stack traces work as expected before/after compilation cache.
func TestDWARF(t *testing.T) {
skipOnAmd64(t)
config := opt.NewRuntimeConfigOptimizingCompiler()
ctx := context.Background()

View File

@@ -61,6 +61,7 @@ func (f fakeFinalizer) setFinalizer(obj interface{}, finalizer interface{}) {
}
func TestEngine_CompileModule(t *testing.T) {
skipOnAmd64(t)
ctx := context.Background()
e := NewEngine(ctx, 0, nil).(*engine)
ff := fakeFinalizer{}

View File

@@ -4,6 +4,7 @@ import (
"runtime"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/amd64"
"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/isa/arm64"
)
@@ -11,6 +12,8 @@ func newMachine() backend.Machine {
switch runtime.GOARCH {
case "arm64":
return arm64.NewBackend()
case "amd64":
return amd64.NewBackend()
default:
panic("unsupported architecture")
}
@@ -20,6 +23,8 @@ func unwindStack(sp, top uintptr, returnAddresses []uintptr) []uintptr {
switch runtime.GOARCH {
case "arm64":
return arm64.UnwindStack(sp, top, returnAddresses)
case "amd64":
return amd64.UnwindStack(sp, top, returnAddresses)
default:
panic("unsupported architecture")
}
@@ -29,6 +34,8 @@ func goCallStackView(stackPointerBeforeGoCall *uint64) []uint64 {
switch runtime.GOARCH {
case "arm64":
return arm64.GoCallStackView(stackPointerBeforeGoCall)
case "amd64":
return amd64.GoCallStackView(stackPointerBeforeGoCall)
default:
panic("unsupported architecture")
}

View File

@@ -16,18 +16,27 @@ import (
var ctx = context.Background()
func TestMain(m *testing.M) {
if runtime.GOARCH != "arm64" {
if runtime.GOARCH != "arm64" && runtime.GOARCH != "amd64" {
os.Exit(0)
}
os.Exit(m.Run())
}
// TODO: delete once we complete the implementation for amd64.
func skipOnAmd64(t *testing.T) {
if runtime.GOARCH == "amd64" {
t.Skip("skip on amd64")
}
}
func TestNewEngine(t *testing.T) {
skipOnAmd64(t)
e := NewEngine(ctx, api.CoreFeaturesV1, nil)
require.NotNil(t, e)
}
func TestEngine_CompiledModuleCount(t *testing.T) {
skipOnAmd64(t)
e, ok := NewEngine(ctx, api.CoreFeaturesV1, nil).(*engine)
require.True(t, ok)
require.Equal(t, uint32(0), e.CompiledModuleCount())
@@ -36,6 +45,7 @@ func TestEngine_CompiledModuleCount(t *testing.T) {
}
func TestEngine_DeleteCompiledModule(t *testing.T) {
skipOnAmd64(t)
e, ok := NewEngine(ctx, api.CoreFeaturesV1, nil).(*engine)
require.True(t, ok)
id := wasm.ModuleID{0xaa}