1 package compiler
2
3 import (
4 "testing"
5
6 "github.com/tetratelabs/wazero/internal/asm"
7 "github.com/tetratelabs/wazero/internal/testing/require"
8 "github.com/tetratelabs/wazero/internal/wasm"
9 "github.com/tetratelabs/wazero/internal/wazeroir"
10 )
11
12 func TestCompiler_compileGlobalGet(t *testing.T) {
13 const globalValue uint64 = 12345
14 for _, tp := range []wasm.ValueType{
15 wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref,
16 } {
17 tp := tp
18 t.Run(wasm.ValueTypeName(tp), func(t *testing.T) {
19 env := newCompilerEnvironment()
20 compiler := env.requireNewCompiler(t, &wasm.FunctionType{}, newCompiler, &wazeroir.CompilationResult{
21 Globals: []wasm.GlobalType{{}, {ValType: tp}},
22 })
23
24
25 globals := []*wasm.GlobalInstance{nil, {Val: globalValue, Type: wasm.GlobalType{ValType: tp}}}
26 env.addGlobals(globals...)
27
28
29 err := compiler.compilePreamble()
30 require.NoError(t, err)
31 op := operationPtr(wazeroir.NewOperationGlobalGet(1))
32 err = compiler.compileGlobalGet(op)
33 require.NoError(t, err)
34
35
36 global := compiler.runtimeValueLocationStack().peek()
37 require.True(t, global.onRegister())
38 require.Equal(t, 1, len(compiler.runtimeValueLocationStack().usedRegisters.list()))
39 switch tp {
40 case wasm.ValueTypeF32, wasm.ValueTypeF64:
41 require.True(t, isVectorRegister(global.register))
42 case wasm.ValueTypeI32, wasm.ValueTypeI64:
43 require.True(t, isGeneralPurposeRegister(global.register))
44 }
45 err = compiler.compileReturnFunction()
46 require.NoError(t, err)
47
48 code := asm.CodeSegment{}
49 defer func() { require.NoError(t, code.Unmap()) }()
50
51
52 _, err = compiler.compile(code.NextCodeSection())
53 require.NoError(t, err)
54
55
56 env.exec(code.Bytes())
57
58
59 require.Equal(t, globalValue, env.stackTopAsUint64())
60
61 require.Equal(t, uint64(1), env.stackPointer())
62 })
63 }
64 }
65
66 func TestCompiler_compileGlobalGet_v128(t *testing.T) {
67 const v128Type = wasm.ValueTypeV128
68 env := newCompilerEnvironment()
69 compiler := env.requireNewCompiler(t, &wasm.FunctionType{}, newCompiler, &wazeroir.CompilationResult{
70 Globals: []wasm.GlobalType{{}, {ValType: v128Type}},
71 })
72
73
74 globals := []*wasm.GlobalInstance{nil, {Val: 12345, ValHi: 6789, Type: wasm.GlobalType{ValType: v128Type}}}
75 env.addGlobals(globals...)
76
77
78 err := compiler.compilePreamble()
79 require.NoError(t, err)
80 op := operationPtr(wazeroir.NewOperationGlobalGet(1))
81 err = compiler.compileGlobalGet(op)
82 require.NoError(t, err)
83
84
85 global := compiler.runtimeValueLocationStack().peek()
86 require.True(t, global.onRegister())
87 require.Equal(t, 1, len(compiler.runtimeValueLocationStack().usedRegisters.list()))
88 require.True(t, isVectorRegister(global.register))
89 err = compiler.compileReturnFunction()
90 require.NoError(t, err)
91
92 code := asm.CodeSegment{}
93 defer func() { require.NoError(t, code.Unmap()) }()
94
95
96 _, err = compiler.compile(code.NextCodeSection())
97 require.NoError(t, err)
98
99
100 env.exec(code.Bytes())
101
102 require.Equal(t, uint64(2), env.stackPointer())
103 require.Equal(t, nativeCallStatusCodeReturned, env.callEngine().statusCode)
104
105
106 actual := globals[1]
107 sp := env.ce.stackContext.stackPointer
108 stack := env.stack()
109 require.Equal(t, actual.Val, stack[sp-2])
110 require.Equal(t, actual.ValHi, stack[sp-1])
111 }
112
113 func TestCompiler_compileGlobalSet(t *testing.T) {
114 const valueToSet uint64 = 12345
115 for _, tp := range []wasm.ValueType{
116 wasm.ValueTypeF32, wasm.ValueTypeF64,
117 wasm.ValueTypeI32, wasm.ValueTypeI64,
118 wasm.ValueTypeExternref, wasm.ValueTypeFuncref,
119 } {
120 tp := tp
121 t.Run(wasm.ValueTypeName(tp), func(t *testing.T) {
122 env := newCompilerEnvironment()
123 compiler := env.requireNewCompiler(t, &wasm.FunctionType{}, newCompiler, &wazeroir.CompilationResult{
124 Globals: []wasm.GlobalType{{}, {ValType: tp}},
125 })
126
127
128 env.addGlobals(nil, &wasm.GlobalInstance{Val: 40, Type: wasm.GlobalType{ValType: tp}})
129
130 err := compiler.compilePreamble()
131 require.NoError(t, err)
132
133
134 loc := compiler.runtimeValueLocationStack().pushRuntimeValueLocationOnStack()
135 switch tp {
136 case wasm.ValueTypeI32:
137 loc.valueType = runtimeValueTypeI32
138 case wasm.ValueTypeI64, wasm.ValueTypeExternref, wasm.ValueTypeFuncref:
139 loc.valueType = runtimeValueTypeI64
140 case wasm.ValueTypeF32:
141 loc.valueType = runtimeValueTypeF32
142 case wasm.ValueTypeF64:
143 loc.valueType = runtimeValueTypeF64
144 }
145 env.stack()[loc.stackPointer] = valueToSet
146
147 const index = 1
148 op := operationPtr(wazeroir.NewOperationGlobalSet(index))
149 err = compiler.compileGlobalSet(op)
150 requireRuntimeLocationStackPointerEqual(t, 0, compiler)
151
152 require.NoError(t, err)
153
154 err = compiler.compileReturnFunction()
155 require.NoError(t, err)
156
157 code := asm.CodeSegment{}
158 defer func() { require.NoError(t, code.Unmap()) }()
159
160
161 _, err = compiler.compile(code.NextCodeSection())
162 require.NoError(t, err)
163 env.exec(code.Bytes())
164
165
166 actual := env.globals()[index]
167 require.Equal(t, valueToSet, actual.Val)
168
169 require.Equal(t, uint64(0), env.stackPointer())
170 })
171 }
172 }
173
174 func TestCompiler_compileGlobalSet_v128(t *testing.T) {
175 const v128Type = wasm.ValueTypeV128
176 const valueToSetLo, valueToSetHi uint64 = 0xffffff, 1
177
178 env := newCompilerEnvironment()
179 compiler := env.requireNewCompiler(t, &wasm.FunctionType{}, newCompiler, &wazeroir.CompilationResult{
180 Globals: []wasm.GlobalType{{}, {ValType: v128Type}},
181 })
182
183
184 env.addGlobals(nil, &wasm.GlobalInstance{Val: 0, ValHi: 0, Type: wasm.GlobalType{ValType: v128Type}})
185
186 err := compiler.compilePreamble()
187 require.NoError(t, err)
188
189
190 lo := compiler.runtimeValueLocationStack().pushRuntimeValueLocationOnStack()
191 lo.valueType = runtimeValueTypeV128Lo
192 env.stack()[lo.stackPointer] = valueToSetLo
193 hi := compiler.runtimeValueLocationStack().pushRuntimeValueLocationOnStack()
194 hi.valueType = runtimeValueTypeV128Hi
195 env.stack()[hi.stackPointer] = valueToSetHi
196
197 const index = 1
198 op := operationPtr(wazeroir.NewOperationGlobalSet(index))
199 err = compiler.compileGlobalSet(op)
200 requireRuntimeLocationStackPointerEqual(t, 0, compiler)
201 require.NoError(t, err)
202
203 err = compiler.compileReturnFunction()
204 require.NoError(t, err)
205
206 code := asm.CodeSegment{}
207 defer func() { require.NoError(t, code.Unmap()) }()
208
209
210 _, err = compiler.compile(code.NextCodeSection())
211 require.NoError(t, err)
212 env.exec(code.Bytes())
213
214 require.Equal(t, uint64(0), env.stackPointer())
215 require.Equal(t, nativeCallStatusCodeReturned, env.callEngine().statusCode)
216
217
218 actual := env.globals()[index]
219 require.Equal(t, valueToSetLo, actual.Val)
220 require.Equal(t, valueToSetHi, actual.ValHi)
221 }
222
View as plain text