authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-11-15 00:33:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-06 12:15:04-07:00
logef447c3ecac4211a0a03f487e84acc61160d7ede
treee7772cd5938f699cf4d172ee1aa07cdeae6c739c
parent8c1c67bdd0a636006e7ddbc14da8c2484b131df7

redo CMakeLists.txt to use WASI interpreter

current status is that it hits error: OutOfMemory for unknown reasons, probably due to bugs in the C WASI interpreter port.

5 files changed, 4340 insertions(+), 428 deletions(-)

CMakeLists.txt+77-415
...@@ -1,11 +1,5 @@...@@ -1,11 +1,5 @@
1cmake_minimum_required(VERSION 2.8.12)1cmake_minimum_required(VERSION 2.8.12)
22
3# Use ccache if possible
4FIND_PROGRAM(CCACHE_PROGRAM ccache)
5IF(CCACHE_PROGRAM)
6 MESSAGE(STATUS "Found ccache ${CCACHE_PROGRAM}")
7ENDIF()
8
9if(NOT CMAKE_BUILD_TYPE)3if(NOT CMAKE_BUILD_TYPE)
10 set(CMAKE_BUILD_TYPE "Debug" CACHE STRING4 set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
11 "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)5 "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE)
...@@ -98,10 +92,15 @@ set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries...@@ -98,10 +92,15 @@ set(ZIG_SHARED_LLVM off CACHE BOOL "Prefer linking against shared LLVM libraries
98set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")92set(ZIG_STATIC_LLVM off CACHE BOOL "Prefer linking against static LLVM libraries")
99set(ZIG_STATIC_ZLIB off CACHE BOOL "Prefer linking against static zlib")93set(ZIG_STATIC_ZLIB off CACHE BOOL "Prefer linking against static zlib")
100set(ZIG_STATIC_ZSTD off CACHE BOOL "Prefer linking against static zstd")94set(ZIG_STATIC_ZSTD off CACHE BOOL "Prefer linking against static zstd")
101set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache if available")95set(ZIG_USE_CCACHE off CACHE BOOL "Use ccache")
10296
103if(CCACHE_PROGRAM AND ZIG_USE_CCACHE)97if(ZIG_USE_CCACHE)
104 SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")98 find_program(CCACHE_PROGRAM ccache)
99 if(CCACHE_PROGRAM)
100 set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
101 else()
102 message(SEND_ERROR "ccache requested but not found")
103 endif()
105endif()104endif()
106105
107if(ZIG_STATIC)106if(ZIG_STATIC)
...@@ -118,19 +117,9 @@ string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_...@@ -118,19 +117,9 @@ string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_
118string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_STATIC_LIB_DIR_ESCAPED "${ZIG_LIBC_STATIC_LIB_DIR}")117string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_STATIC_LIB_DIR_ESCAPED "${ZIG_LIBC_STATIC_LIB_DIR}")
119string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_INCLUDE_DIR_ESCAPED "${ZIG_LIBC_INCLUDE_DIR}")118string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_INCLUDE_DIR_ESCAPED "${ZIG_LIBC_INCLUDE_DIR}")
120119
121option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)
122
123set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")120set(ZIG_TARGET_TRIPLE "native" CACHE STRING "arch-os-abi to output binaries for")
124set(ZIG_TARGET_MCPU "native" CACHE STRING "-mcpu parameter to output binaries for")121set(ZIG_TARGET_MCPU "native" CACHE STRING "-mcpu parameter to output binaries for")
125set(ZIG_EXECUTABLE "" CACHE STRING "(when cross compiling) path to already-built zig binary")
126set(ZIG_SINGLE_THREADED off CACHE BOOL "limit the zig compiler to use only 1 thread")122set(ZIG_SINGLE_THREADED off CACHE BOOL "limit the zig compiler to use only 1 thread")
127set(ZIG_OMIT_STAGE2 off CACHE BOOL "omit the stage2 backend from stage1")
128
129if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
130 set(ZIG_ENABLE_LOGGING ON CACHE BOOL "enable logging")
131else()
132 set(ZIG_ENABLE_LOGGING OFF CACHE BOOL "enable logging")
133endif()
134123
135if("${ZIG_TARGET_TRIPLE}" STREQUAL "native")124if("${ZIG_TARGET_TRIPLE}" STREQUAL "native")
136 set(ZIG_USE_LLVM_CONFIG ON CACHE BOOL "use llvm-config to find LLVM libraries")125 set(ZIG_USE_LLVM_CONFIG ON CACHE BOOL "use llvm-config to find LLVM libraries")
...@@ -179,190 +168,6 @@ include_directories(${LLVM_INCLUDE_DIRS})...@@ -179,190 +168,6 @@ include_directories(${LLVM_INCLUDE_DIRS})
179include_directories(${LLD_INCLUDE_DIRS})168include_directories(${LLD_INCLUDE_DIRS})
180include_directories(${CLANG_INCLUDE_DIRS})169include_directories(${CLANG_INCLUDE_DIRS})
181170
182# No patches have been applied to SoftFloat-3e
183set(EMBEDDED_SOFTFLOAT_SOURCES
184 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c"
185 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c"
186 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c"
187 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c"
188 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c"
189 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c"
190 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c"
191 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c"
192 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c"
193 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c"
194 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c"
195 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c"
196 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c"
197 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c"
198 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c"
199 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c"
200 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_add.c"
201 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_div.c"
202 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_eq.c"
203 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_eq_signaling.c"
204 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_le.c"
205 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_le_quiet.c"
206 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_lt.c"
207 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_lt_quiet.c"
208 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mul.c"
209 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
210 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_rem.c"
211 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_roundToInt.c"
212 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_sqrt.c"
213 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_sub.c"
214 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f16.c"
215 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f32.c"
216 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_f64.c"
217 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_extF80M.c"
218 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32.c"
219 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c"
220 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64.c"
221 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_i64_r_minMag.c"
222 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32.c"
223 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c"
224 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64.c"
225 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c"
226 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_add.c"
227 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_div.c"
228 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_eq.c"
229 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_le.c"
230 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_lt.c"
231 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_mul.c"
232 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_rem.c"
233 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_roundToInt.c"
234 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sqrt.c"
235 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_sub.c"
236 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f16.c"
237 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f32.c"
238 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f64.c"
239 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/extF80M_to_f128M.c"
240 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_add.c"
241 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_div.c"
242 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_eq.c"
243 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_isSignalingNaN.c"
244 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_lt.c"
245 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mul.c"
246 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_rem.c"
247 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_roundToInt.c"
248 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sqrt.c"
249 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_sub.c"
250 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_extF80M.c"
251 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f128M.c"
252 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_to_f64.c"
253 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_extF80M.c"
254 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f32_to_f128M.c"
255 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_extF80M.c"
256 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f128M.c"
257 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f64_to_f16.c"
258 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/i32_to_f128M.c"
259 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_add256M.c"
260 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addCarryM.c"
261 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addComplCarryM.c"
262 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addF128M.c"
263 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addExtF80M.c"
264 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addM.c"
265 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF16.c"
266 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF32.c"
267 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_addMagsF64.c"
268 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip32_1.c"
269 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecipSqrt32_1.c"
270 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecipSqrt_1Ks.c"
271 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_approxRecip_1Ks.c"
272 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare128M.c"
273 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compare96M.c"
274 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c"
275 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros16.c"
276 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros32.c"
277 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros64.c"
278 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_countLeadingZeros8.c"
279 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_eq128.c"
280 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidF128M.c"
281 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_invalidExtF80M.c"
282 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_isNaNF128M.c"
283 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_le128.c"
284 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_lt128.c"
285 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mul128MTo256M.c"
286 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mul64To128M.c"
287 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF128M.c"
288 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF16.c"
289 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF32.c"
290 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_mulAddF64.c"
291 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_negXM.c"
292 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normExtF80SigM.c"
293 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c"
294 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c"
295 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF16.c"
296 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF32.c"
297 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normRoundPackToF64.c"
298 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normSubnormalF128SigM.c"
299 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normSubnormalF16Sig.c"
300 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normSubnormalF32Sig.c"
301 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_normSubnormalF64Sig.c"
302 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_remStepMBy32.c"
303 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToI64.c"
304 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundMToUI64.c"
305 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c"
306 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackMToF128M.c"
307 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF16.c"
308 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF32.c"
309 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundPackToF64.c"
310 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundToI32.c"
311 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundToI64.c"
312 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundToUI32.c"
313 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_roundToUI64.c"
314 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftLeftM.c"
315 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftNormSigF128M.c"
316 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftRightJam256M.c"
317 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftRightJam32.c"
318 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftRightJam64.c"
319 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftRightJamM.c"
320 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shiftRightM.c"
321 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftLeft64To96M.c"
322 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftLeftM.c"
323 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftRightExtendM.c"
324 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftRightJam64.c"
325 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftRightJamM.c"
326 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_shortShiftRightM.c"
327 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_sub1XM.c"
328 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_sub256M.c"
329 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subM.c"
330 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF16.c"
331 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF32.c"
332 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_subMagsF64.c"
333 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c"
334 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c"
335 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f16_mulAdd.c"
336 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/f128M_mulAdd.c"
337 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/softfloat_state.c"
338 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_f128M.c"
339 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_f128M.c"
340 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui32_to_extF80M.c"
341 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/ui64_to_extF80M.c"
342)
343add_library(embedded_softfloat STATIC ${EMBEDDED_SOFTFLOAT_SOURCES})
344if(MSVC)
345 set(SOFTFLOAT_CFLAGS "/w")
346
347 if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
348 set(SOFTFLOAT_CFLAGS "${SOFTFLOAT_CFLAGS} /O2")
349 endif()
350
351 set_target_properties(embedded_softfloat PROPERTIES
352 COMPILE_FLAGS ${SOFTFLOAT_CFLAGS}
353 )
354else()
355 set_target_properties(embedded_softfloat PROPERTIES
356 COMPILE_FLAGS "-std=c99 -O3"
357 )
358endif()
359target_include_directories(embedded_softfloat PUBLIC
360 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e-prebuilt"
361 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/8086"
362)
363include_directories("${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e/source/include")
364set(SOFTFLOAT_LIBRARIES embedded_softfloat)
365
366find_package(Threads)171find_package(Threads)
367172
368set(ZIG_LIB_DIR "lib/zig")173set(ZIG_LIB_DIR "lib/zig")
...@@ -374,35 +179,8 @@ set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std")...@@ -374,35 +179,8 @@ set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std")
374set(ZIG_CONFIG_H_OUT "${CMAKE_BINARY_DIR}/config.h")179set(ZIG_CONFIG_H_OUT "${CMAKE_BINARY_DIR}/config.h")
375set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig")180set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig")
376181
377# This is our shim which will be replaced by stage1.zig.
378set(ZIG1_SOURCES
379 "${CMAKE_SOURCE_DIR}/src/stage1/zig0.cpp"
380)
381
382set(STAGE1_SOURCES182set(STAGE1_SOURCES
383 "${CMAKE_SOURCE_DIR}/src/stage1/analyze.cpp"183 "${CMAKE_SOURCE_DIR}/stage1/zig1.c"
384 "${CMAKE_SOURCE_DIR}/src/stage1/astgen.cpp"
385 "${CMAKE_SOURCE_DIR}/src/stage1/bigfloat.cpp"
386 "${CMAKE_SOURCE_DIR}/src/stage1/bigint.cpp"
387 "${CMAKE_SOURCE_DIR}/src/stage1/buffer.cpp"
388 "${CMAKE_SOURCE_DIR}/src/stage1/codegen.cpp"
389 "${CMAKE_SOURCE_DIR}/src/stage1/errmsg.cpp"
390 "${CMAKE_SOURCE_DIR}/src/stage1/error.cpp"
391 "${CMAKE_SOURCE_DIR}/src/stage1/heap.cpp"
392 "${CMAKE_SOURCE_DIR}/src/stage1/ir.cpp"
393 "${CMAKE_SOURCE_DIR}/src/stage1/ir_print.cpp"
394 "${CMAKE_SOURCE_DIR}/src/stage1/mem.cpp"
395 "${CMAKE_SOURCE_DIR}/src/stage1/os.cpp"
396 "${CMAKE_SOURCE_DIR}/src/stage1/parser.cpp"
397 "${CMAKE_SOURCE_DIR}/src/stage1/range_set.cpp"
398 "${CMAKE_SOURCE_DIR}/src/stage1/softfloat_ext.cpp"
399 "${CMAKE_SOURCE_DIR}/src/stage1/stage1.cpp"
400 "${CMAKE_SOURCE_DIR}/src/stage1/target.cpp"
401 "${CMAKE_SOURCE_DIR}/src/stage1/tokenizer.cpp"
402 "${CMAKE_SOURCE_DIR}/src/stage1/util.cpp"
403)
404set(OPTIMIZED_C_SOURCES
405 "${CMAKE_SOURCE_DIR}/src/stage1/parse_f128.c"
406)184)
407set(ZIG_CPP_SOURCES185set(ZIG_CPP_SOURCES
408 # These are planned to stay even when we are self-hosted.186 # These are planned to stay even when we are self-hosted.
...@@ -416,11 +194,7 @@ set(ZIG_CPP_SOURCES...@@ -416,11 +194,7 @@ set(ZIG_CPP_SOURCES
416 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"194 "${CMAKE_SOURCE_DIR}/src/windows_sdk.cpp"
417)195)
418# Needed because we use cmake, not the zig build system, to build zig2.o.196# Needed because we use cmake, not the zig build system, to build zig2.o.
419# This list is generated by building zig and then clearing the zig-cache directory,
420# then manually running the build-obj command (see BUILD_ZIG2_ARGS), and then looking
421# in the zig-cache directory for the compiler-generated list of zig file dependencies.
422set(ZIG_STAGE2_SOURCES197set(ZIG_STAGE2_SOURCES
423 "${ZIG_CONFIG_ZIG_OUT}"
424 "${CMAKE_SOURCE_DIR}/lib/std/array_hash_map.zig"198 "${CMAKE_SOURCE_DIR}/lib/std/array_hash_map.zig"
425 "${CMAKE_SOURCE_DIR}/lib/std/array_list.zig"199 "${CMAKE_SOURCE_DIR}/lib/std/array_list.zig"
426 "${CMAKE_SOURCE_DIR}/lib/std/ascii.zig"200 "${CMAKE_SOURCE_DIR}/lib/std/ascii.zig"
...@@ -828,7 +602,6 @@ set(ZIG_STAGE2_SOURCES...@@ -828,7 +602,6 @@ set(ZIG_STAGE2_SOURCES
828 "${CMAKE_SOURCE_DIR}/src/print_targets.zig"602 "${CMAKE_SOURCE_DIR}/src/print_targets.zig"
829 "${CMAKE_SOURCE_DIR}/src/print_zir.zig"603 "${CMAKE_SOURCE_DIR}/src/print_zir.zig"
830 "${CMAKE_SOURCE_DIR}/src/register_manager.zig"604 "${CMAKE_SOURCE_DIR}/src/register_manager.zig"
831 "${CMAKE_SOURCE_DIR}/src/stage1.zig"
832 "${CMAKE_SOURCE_DIR}/src/target.zig"605 "${CMAKE_SOURCE_DIR}/src/target.zig"
833 "${CMAKE_SOURCE_DIR}/src/tracy.zig"606 "${CMAKE_SOURCE_DIR}/src/tracy.zig"
834 "${CMAKE_SOURCE_DIR}/src/translate_c.zig"607 "${CMAKE_SOURCE_DIR}/src/translate_c.zig"
...@@ -847,24 +620,12 @@ if(MSVC)...@@ -847,24 +620,12 @@ if(MSVC)
847 endif()620 endif()
848endif()621endif()
849622
850if(ZIG_OMIT_STAGE2)
851 set(ZIG_OMIT_STAGE2_BOOL "true")
852else()
853 set(ZIG_OMIT_STAGE2_BOOL "false")
854endif()
855
856if(ZIG_ENABLE_LOGGING)
857 set(ZIG_ENABLE_LOGGING_BOOL "true")
858else()
859 set(ZIG_ENABLE_LOGGING_BOOL "false")
860endif()
861
862configure_file (623configure_file (
863 "${CMAKE_SOURCE_DIR}/src/stage1/config.h.in"624 "${CMAKE_SOURCE_DIR}/stage1/config.h.in"
864 "${ZIG_CONFIG_H_OUT}"625 "${ZIG_CONFIG_H_OUT}"
865)626)
866configure_file (627configure_file (
867 "${CMAKE_SOURCE_DIR}/src/config.zig.in"628 "${CMAKE_SOURCE_DIR}/stage1/config.zig.in"
868 "${ZIG_CONFIG_ZIG_OUT}"629 "${ZIG_CONFIG_ZIG_OUT}"
869)630)
870631
...@@ -872,55 +633,40 @@ include_directories(...@@ -872,55 +633,40 @@ include_directories(
872 ${CMAKE_SOURCE_DIR}633 ${CMAKE_SOURCE_DIR}
873 ${CMAKE_BINARY_DIR}634 ${CMAKE_BINARY_DIR}
874 "${CMAKE_SOURCE_DIR}/src"635 "${CMAKE_SOURCE_DIR}/src"
875 "${CMAKE_SOURCE_DIR}/src/stage1"
876)636)
877637
878# These have to go before the -Wno- flags638# These have to go before the -Wno- flags
879if(MSVC)639if(MSVC)
880 set(EXE_CFLAGS "/std:c++14")640 set(EXE_CXX_FLAGS "/std:c++14")
881else(MSVC)641else(MSVC)
882 set(EXE_CFLAGS "-std=c++14")642 set(EXE_CXX_FLAGS "-std=c++14")
883endif(MSVC)643endif(MSVC)
884644
885if(ZIG_STATIC)
886 set(EXE_CFLAGS "${EXE_CFLAGS} -DZIG_LINK_MODE=Static")
887else()
888 set(EXE_CFLAGS "${EXE_CFLAGS} -DZIG_LINK_MODE=Dynamic")
889endif()
890
891if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")645if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
892 if(MSVC)646 if(MSVC)
893 set(EXE_CFLAGS "${EXE_CFLAGS} /w")647 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} /w")
894 else()648 else()
895 set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall")649 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} -Werror -Wall")
896 # fallthrough support was added in GCC 7.0650 # fallthrough support was added in GCC 7.0
897 if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)651 if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 7.0)
898 set(EXE_CFLAGS "${EXE_CFLAGS} -Werror=implicit-fallthrough")652 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} -Werror=implicit-fallthrough")
899 endif()653 endif()
900 # GCC 9.2 and older are unable to detect valid variable initialization in some cases654 # GCC 9.2 and older are unable to detect valid variable initialization in some cases
901 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 9.2)655 if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS_EQUAL 9.2)
902 set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-maybe-uninitialized")656 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} -Wno-maybe-uninitialized")
903 endif()657 endif()
904 endif()658 endif()
905endif()659endif()
906660
907if(MSVC)661if(MSVC)
908 set(EXE_CFLAGS "${EXE_CFLAGS}")662 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS}")
909else()663else()
910 set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces -Wno-comment")664 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fvisibility-inlines-hidden -fno-exceptions -fno-rtti -Werror=type-limits -Wno-missing-braces -Wno-comment")
911 if(MINGW)665 if(MINGW)
912 set(EXE_CFLAGS "${EXE_CFLAGS} -Wno-format")666 set(EXE_CXX_FLAGS "${EXE_CXX_FLAGS} -Wno-format")
913 endif()667 endif()
914endif()668endif()
915669
916if(MSVC)
917 if(NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
918 set(OPTIMIZED_C_FLAGS "/O2")
919 endif()
920else(MSVC)
921 set(OPTIMIZED_C_FLAGS "-std=c99 -O3")
922endif(MSVC)
923
924set(EXE_LDFLAGS " ")670set(EXE_LDFLAGS " ")
925if(MSVC)671if(MSVC)
926 set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216")672 set(EXE_LDFLAGS "${EXE_LDFLAGS} /STACK:16777216")
...@@ -939,21 +685,10 @@ if(ZIG_STATIC)...@@ -939,21 +685,10 @@ if(ZIG_STATIC)
939 elseif(NOT MSVC)685 elseif(NOT MSVC)
940 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static")686 set(EXE_LDFLAGS "${EXE_LDFLAGS} -static")
941 endif()687 endif()
942else()
943 if(MINGW)
944 set(EXE_LDFLAGS "${EXE_LDFLAGS}")
945 endif()
946endif()
947
948if(ZIG_TEST_COVERAGE)
949 set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage")
950 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
951endif()688endif()
952689
953add_library(zigcpp STATIC ${ZIG_CPP_SOURCES})690add_library(zigcpp STATIC ${ZIG_CPP_SOURCES})
954set_target_properties(zigcpp PROPERTIES691set_target_properties(zigcpp PROPERTIES COMPILE_FLAGS ${EXE_CXX_FLAGS})
955 COMPILE_FLAGS ${EXE_CFLAGS}
956)
957692
958target_link_libraries(zigcpp LINK_PUBLIC693target_link_libraries(zigcpp LINK_PUBLIC
959 ${CLANG_LIBRARIES}694 ${CLANG_LIBRARIES}
...@@ -962,146 +697,73 @@ target_link_libraries(zigcpp LINK_PUBLIC...@@ -962,146 +697,73 @@ target_link_libraries(zigcpp LINK_PUBLIC
962 ${CMAKE_THREAD_LIBS_INIT}697 ${CMAKE_THREAD_LIBS_INIT}
963)698)
964699
965add_library(opt_c_util STATIC ${OPTIMIZED_C_SOURCES})
966set_target_properties(opt_c_util PROPERTIES
967 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
968)
969target_include_directories(opt_c_util PRIVATE
970 "${CMAKE_SOURCE_DIR}/deps/SoftFloat-3e-prebuilt"
971)
972
973add_library(zigstage1 STATIC ${STAGE1_SOURCES})
974set_target_properties(zigstage1 PROPERTIES
975 COMPILE_FLAGS ${EXE_CFLAGS}
976 LINK_FLAGS ${EXE_LDFLAGS}
977)
978target_link_libraries(zigstage1 LINK_PUBLIC
979 opt_c_util
980 ${SOFTFLOAT_LIBRARIES}
981 zigcpp
982)
983if(NOT MSVC)
984 target_link_libraries(zigstage1 LINK_PUBLIC ${LIBXML2})
985endif()
986
987if(ZIG_DIA_GUIDS_LIB)
988 target_link_libraries(zigstage1 LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
989endif()
990
991if(MSVC OR MINGW)
992 target_link_libraries(zigstage1 LINK_PUBLIC version)
993endif()
994
995if("${ZIG_EXECUTABLE}" STREQUAL "")
996 add_executable(zig1 ${ZIG1_SOURCES})
997 set_target_properties(zig1 PROPERTIES
998 COMPILE_FLAGS ${EXE_CFLAGS}
999 LINK_FLAGS ${EXE_LDFLAGS}
1000 )
1001 target_link_libraries(zig1 zigstage1)
1002endif()
1003
1004if(MSVC)700if(MSVC)
1005 set(ZIG2_OBJECT "${CMAKE_BINARY_DIR}/zig2.obj")701 set(ZIG1_COMPILE_FLAGS "/std:c99")
1006else()702 set(ZIG2_COMPILE_FLAGS "/std:c99")
1007 set(ZIG2_OBJECT "${CMAKE_BINARY_DIR}/zig2.o")703 set(ZIG2_LINK_FLAGS "/STACK:16777216")
1008endif()
1009if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
1010 set(ZIG_RELEASE_ARG "")
1011elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
1012 set(ZIG_RELEASE_ARG -Drelease)
1013else()
1014 set(ZIG_RELEASE_ARG -Drelease -Dstrip)
1015endif()
1016if(ZIG_NO_LIB)
1017 set(ZIG_NO_LIB_ARG "-Dno-lib")
1018else()704else()
1019 set(ZIG_NO_LIB_ARG "")705 #set(ZIG1_COMPILE_FLAGS "-std=c99 -O2 -march=native")
1020endif()706 set(ZIG1_COMPILE_FLAGS "-std=c99 -march=native")
1021if(ZIG_SINGLE_THREADED)707 set(ZIG2_COMPILE_FLAGS "-std=c99 -O2 -march=native")
1022 set(ZIG_SINGLE_THREADED_ARG "-fsingle-threaded")708 set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")
1023else()
1024 set(ZIG_SINGLE_THREADED_ARG "")
1025endif()
1026if(ZIG_STATIC)
1027 set(ZIG_STATIC_ARG "-Duse-zig-libcxx")
1028else()
1029 set(ZIG_STATIC_ARG "")
1030endif()709endif()
1031710
711add_executable(zig1 ${STAGE1_SOURCES})
712set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})
713#target_include_directories(zig1 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
714target_link_libraries(zig1 LINK_PUBLIC m)
715
716
717set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
1032set(BUILD_ZIG2_ARGS718set(BUILD_ZIG2_ARGS
1033 "src/stage1.zig"719 "${CMAKE_SOURCE_DIR}/lib"
1034 --name zig2720 "${CMAKE_BINARY_DIR}/zig1-cache"
1035 --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"721 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
1036 "-femit-bin=${ZIG2_OBJECT}"722 build-exe src/main.zig -ofmt=c -lc
1037 -fcompiler-rt723 --name zig2
1038 ${ZIG_SINGLE_THREADED_ARG}724 --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"
1039 -target native725 --pkg-end
1040 -mcpu native726 -target x86_64-linux-musl # TODO: autodetect in zig1.c
1041 -lc727 --color on # TODO: autodetect in zig1.c
1042 --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"728 -OReleaseFast
1043 --pkg-end729)
730
731add_custom_command(
732 OUTPUT "${ZIG2_C_SOURCE}"
733 COMMAND zig1 ${BUILD_ZIG2_ARGS}
734 DEPENDS zig1 "${ZIG_STAGE2_SOURCES}"
735 COMMENT STATUS "Interpreting zig1.wasm to produce ${ZIG2_C_SOURCE}"
736 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
1044)737)
1045738
1046if("${ZIG_EXECUTABLE}" STREQUAL "")739set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")
1047 add_custom_command(740set(BUILD_COMPILER_RT_ARGS
1048 OUTPUT "${ZIG2_OBJECT}"741 "${CMAKE_SOURCE_DIR}/lib"
1049 COMMAND zig1 ${BUILD_ZIG2_ARGS}742 "${CMAKE_BINARY_DIR}/zig1-cache"
1050 DEPENDS zig1 "${ZIG_STAGE2_SOURCES}"743 "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm"
1051 COMMENT STATUS "Building stage2 object ${ZIG2_OBJECT}"744 build-obj lib/compiler_rt.zig -ofmt=c
1052 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"745 --name compiler_rt
1053 )746 -target x86_64-linux-musl # TODO: autodetect in zig1.c
1054 if (WIN32)747 --color on # TODO: autodetect in zig1.c
1055 set(ZIG_EXECUTABLE "${CMAKE_BINARY_DIR}/zig2.exe")748 -OReleaseFast
1056 else()749)
1057 set(ZIG_EXECUTABLE "${CMAKE_BINARY_DIR}/zig2")750
1058 endif()751add_custom_command(
1059else()752 OUTPUT "${ZIG_COMPILER_RT_C_SOURCE}"
1060 add_custom_command(753 COMMAND zig1 ${BUILD_COMPILER_RT_ARGS}
1061 OUTPUT "${ZIG2_OBJECT}"754 DEPENDS zig1 "${ZIG_STAGE2_SOURCES}"
1062 COMMAND "${ZIG_EXECUTABLE}" "build-obj" ${BUILD_ZIG2_ARGS}755 COMMENT STATUS "Interpreting zig1.wasm to produce ${ZIG_COMPILER_RT_C_SOURCE}"
1063 DEPENDS ${ZIG_STAGE2_SOURCES}756 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
1064 COMMENT STATUS "Building stage2 component ${ZIG2_OBJECT}"757)
1065 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
1066 )
1067endif()
1068758
1069# cmake won't let us configure an executable without C sources.
1070add_executable(zig2 "${CMAKE_SOURCE_DIR}/src/stage1/empty.cpp" "${ZIG2_OBJECT}")
1071759
760add_executable(zig2 ${ZIG2_C_SOURCE})
1072set_target_properties(zig2 PROPERTIES761set_target_properties(zig2 PROPERTIES
1073 COMPILE_FLAGS ${EXE_CFLAGS}762 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}
1074 LINK_FLAGS ${EXE_LDFLAGS}763 LINK_FLAGS ${ZIG2_LINK_FLAGS}
1075)764)
1076target_link_libraries(zig2 zigstage1)
1077if(MSVC)
1078 target_link_libraries(zig2 ntdll.lib)
1079elseif(MINGW)
1080 target_link_libraries(zig2 ntdll)
1081endif()
1082765
1083set(ZIG_BUILD_ARGS
1084 --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
1085 "-Dconfig_h=${ZIG_CONFIG_H_OUT}"
1086 "-Denable-llvm"
1087 ${ZIG_RELEASE_ARG}
1088 ${ZIG_STATIC_ARG}
1089 ${ZIG_NO_LIB_ARG}
1090 ${ZIG_SINGLE_THREADED_ARG}
1091 "-Dtarget=${ZIG_TARGET_TRIPLE}"
1092 "-Dcpu=${ZIG_TARGET_MCPU}"
1093 "-Dversion-string=${RESOLVED_ZIG_VERSION}"
1094)
1095766
1096add_custom_target(stage3 ALL
1097 COMMAND zig2 build compile ${ZIG_BUILD_ARGS}
1098 DEPENDS zig2
1099 COMMENT STATUS "Building stage3"
1100 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
1101)
1102767
1103install(CODE "set(ZIG_EXECUTABLE \"${ZIG_EXECUTABLE}\")")768
1104install(CODE "set(ZIG_BUILD_ARGS \"${ZIG_BUILD_ARGS}\")")769
1105install(CODE "set(CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\")")
1106install(CODE "set(CMAKE_SOURCE_DIR \"${CMAKE_SOURCE_DIR}\")")
1107install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/install.cmake")
src/config.zig.in deleted-13
...@@ -1,13 +0,0 @@
1pub const have_llvm = true;
2pub const llvm_has_m68k = false;
3pub const llvm_has_csky = false;
4pub const llvm_has_arc = false;
5pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@";
6pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable;
7pub const enable_logging: bool = @ZIG_ENABLE_LOGGING_BOOL@;
8pub const enable_link_snapshots: bool = false;
9pub const enable_tracy = false;
10pub const value_tracing = false;
11pub const have_stage1 = true;
12pub const skip_non_native = false;
13pub const only_c = false;
stage1/config.h.in created+30
...@@ -0,0 +1,30 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_CONFIG_H
9#define ZIG_CONFIG_H
10
11// Used by zig0.cpp
12#define ZIG_VERSION_MAJOR @ZIG_VERSION_MAJOR@
13#define ZIG_VERSION_MINOR @ZIG_VERSION_MINOR@
14#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@
15#define ZIG_VERSION_STRING "@ZIG_VERSION@"
16
17// Used by build.zig for communicating build information to self hosted build.
18#define ZIG_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@"
19#define ZIG_LLVM_LINK_MODE "@LLVM_LINK_MODE@"
20#define ZIG_CMAKE_PREFIX_PATH "@ZIG_CMAKE_PREFIX_PATH@"
21#define ZIG_CXX_COMPILER "@CMAKE_CXX_COMPILER@"
22#define ZIG_LLD_INCLUDE_PATH "@LLD_INCLUDE_DIRS@"
23#define ZIG_LLD_LIBRARIES "@LLD_LIBRARIES@"
24#define ZIG_CLANG_LIBRARIES "@CLANG_LIBRARIES@"
25#define ZIG_LLVM_INCLUDE_PATH "@LLVM_INCLUDE_DIRS@"
26#define ZIG_LLVM_LIB_PATH "@LLVM_LIBDIRS@"
27#define ZIG_LLVM_LIBRARIES "@LLVM_LIBRARIES@"
28#define ZIG_DIA_GUIDS_LIB "@ZIG_DIA_GUIDS_LIB_ESCAPED@"
29
30#endif
stage1/config.zig.in created+13
...@@ -0,0 +1,13 @@
1pub const have_llvm = false;
2pub const llvm_has_m68k = false;
3pub const llvm_has_csky = false;
4pub const llvm_has_arc = false;
5pub const version: [:0]const u8 = "@RESOLVED_ZIG_VERSION@";
6pub const semver = @import("std").SemanticVersion.parse(version) catch unreachable;
7pub const enable_logging: bool = false;
8pub const enable_link_snapshots: bool = false;
9pub const enable_tracy = false;
10pub const value_tracing = false;
11pub const have_stage1 = false;
12pub const skip_non_native = false;
13pub const only_c = true;
stage1/zig1.c created+4220
...@@ -0,0 +1,4220 @@
1// TODO get rid of _GNU_SOURCE
2#define _GNU_SOURCE
3#include <assert.h>
4#include <errno.h>
5#include <limits.h>
6#include <math.h>
7#include <stdbool.h>
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include <sys/mman.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16#include <unistd.h>
17
18enum wasi_errno_t {
19 WASI_ESUCCESS = 0,
20 WASI_E2BIG = 1,
21 WASI_EACCES = 2,
22 WASI_EADDRINUSE = 3,
23 WASI_EADDRNOTAVAIL = 4,
24 WASI_EAFNOSUPPORT = 5,
25 WASI_EAGAIN = 6,
26 WASI_EALREADY = 7,
27 WASI_EBADF = 8,
28 WASI_EBADMSG = 9,
29 WASI_EBUSY = 10,
30 WASI_ECANCELED = 11,
31 WASI_ECHILD = 12,
32 WASI_ECONNABORTED = 13,
33 WASI_ECONNREFUSED = 14,
34 WASI_ECONNRESET = 15,
35 WASI_EDEADLK = 16,
36 WASI_EDESTADDRREQ = 17,
37 WASI_EDOM = 18,
38 WASI_EDQUOT = 19,
39 WASI_EEXIST = 20,
40 WASI_EFAULT = 21,
41 WASI_EFBIG = 22,
42 WASI_EHOSTUNREACH = 23,
43 WASI_EIDRM = 24,
44 WASI_EILSEQ = 25,
45 WASI_EINPROGRESS = 26,
46 WASI_EINTR = 27,
47 WASI_EINVAL = 28,
48 WASI_EIO = 29,
49 WASI_EISCONN = 30,
50 WASI_EISDIR = 31,
51 WASI_ELOOP = 32,
52 WASI_EMFILE = 33,
53 WASI_EMLINK = 34,
54 WASI_EMSGSIZE = 35,
55 WASI_EMULTIHOP = 36,
56 WASI_ENAMETOOLONG = 37,
57 WASI_ENETDOWN = 38,
58 WASI_ENETRESET = 39,
59 WASI_ENETUNREACH = 40,
60 WASI_ENFILE = 41,
61 WASI_ENOBUFS = 42,
62 WASI_ENODEV = 43,
63 WASI_ENOENT = 44,
64 WASI_ENOEXEC = 45,
65 WASI_ENOLCK = 46,
66 WASI_ENOLINK = 47,
67 WASI_ENOMEM = 48,
68 WASI_ENOMSG = 49,
69 WASI_ENOPROTOOPT = 50,
70 WASI_ENOSPC = 51,
71 WASI_ENOSYS = 52,
72 WASI_ENOTCONN = 53,
73 WASI_ENOTDIR = 54,
74 WASI_ENOTEMPTY = 55,
75 WASI_ENOTRECOVERABLE = 56,
76 WASI_ENOTSOCK = 57,
77 WASI_EOPNOTSUPP = 58,
78 WASI_ENOTTY = 59,
79 WASI_ENXIO = 60,
80 WASI_EOVERFLOW = 61,
81 WASI_EOWNERDEAD = 62,
82 WASI_EPERM = 63,
83 WASI_EPIPE = 64,
84 WASI_EPROTO = 65,
85 WASI_EPROTONOSUPPORT = 66,
86 WASI_EPROTOTYPE = 67,
87 WASI_ERANGE = 68,
88 WASI_EROFS = 69,
89 WASI_ESPIPE = 70,
90 WASI_ESRCH = 71,
91 WASI_ESTALE = 72,
92 WASI_ETIMEDOUT = 73,
93 WASI_ETXTBSY = 74,
94 WASI_EXDEV = 75,
95 WASI_ENOTCAPABLE = 76,
96};
97
98static void panic(const char *msg) {
99 fprintf(stderr, "%s\n", msg);
100 abort();
101}
102
103static uint32_t min_u32(uint32_t a, uint32_t b) {
104 return (a < b) ? a : b;
105}
106
107static uint32_t rotl32(uint32_t n, unsigned c) {
108 const unsigned mask = CHAR_BIT * sizeof(n) - 1;
109 c &= mask & 31;
110 return (n << c) | (n >> ((-c) & mask));
111}
112
113static uint32_t rotr32(uint32_t n, unsigned c) {
114 const unsigned mask = CHAR_BIT * sizeof(n) - 1;
115 c &= mask & 31;
116 return (n >> c) | (n << ((-c) & mask));
117}
118
119static uint64_t rotl64(uint64_t n, unsigned c) {
120 const unsigned mask = CHAR_BIT * sizeof(n) - 1;
121 c &= mask & 63;
122 return (n << c) | (n >> ((-c) & mask));
123}
124
125static uint64_t rotr64(uint64_t n, unsigned c) {
126 const unsigned mask = CHAR_BIT * sizeof(n) - 1;
127 c &= mask & 63;
128 return (n >> c) | (n << ((-c) & mask));
129}
130
131static void *arena_alloc(size_t n) {
132 void *ptr = malloc(n);
133 if (!ptr) panic("out of memory");
134 return ptr;
135}
136
137static void *arena_realloc(void *ptr, size_t new_n) {
138 void *new_ptr = realloc(ptr, new_n);
139 if (!new_ptr) panic("out of memory");
140 return new_ptr;
141}
142
143static int err_wrap(const char *prefix, int rc) {
144 if (rc == -1) {
145 perror(prefix);
146 abort();
147 }
148 return rc;
149}
150
151static bool bs_isSet(const uint32_t *bitset, uint32_t index) {
152 return (bitset[index >> 5] >> (index & 0x1f)) & 1;
153}
154static void bs_set(uint32_t *bitset, uint32_t index) {
155 bitset[index >> 5] |= ((uint32_t)1 << (index & 0x1f));
156}
157static void bs_unset(uint32_t *bitset, uint32_t index) {
158 bitset[index >> 5] &= ~((uint32_t)1 << (index & 0x1f));
159}
160static void bs_setValue(uint32_t *bitset, uint32_t index, bool value) {
161 if (value) bs_set(bitset, index); else bs_unset(bitset, index);
162}
163
164struct ByteSlice {
165 char *ptr;
166 size_t len;
167};
168
169static struct ByteSlice read_file_alloc(const char *file_path) {
170 FILE *f = fopen(file_path, "rb");
171 if (!f) {
172 fprintf(stderr, "failed to read %s: ", file_path);
173 perror("");
174 abort();
175 }
176 if (fseek(f, 0L, SEEK_END) == -1) panic("failed to seek");
177 struct ByteSlice res;
178 res.len = ftell(f);
179 res.ptr = malloc(res.len);
180 rewind(f);
181 size_t amt_read = fread(res.ptr, 1, res.len, f);
182 if (amt_read != res.len) panic("short read");
183 fclose(f);
184 return res;
185}
186
187
188struct Preopen {
189 int wasi_fd;
190 int host_fd;
191 const char *name;
192 size_t name_len;
193};
194
195static struct Preopen preopens_buffer[10];
196static size_t preopens_len = 0;
197
198static void add_preopen(int wasi_fd, const char *name, int host_fd) {
199 preopens_buffer[preopens_len].wasi_fd = wasi_fd;
200 preopens_buffer[preopens_len].host_fd = host_fd;
201 preopens_buffer[preopens_len].name = name;
202 preopens_buffer[preopens_len].name_len = strlen(name);
203 preopens_len += 1;
204}
205
206static const struct Preopen *find_preopen(int32_t wasi_fd) {
207 for (size_t i = 0; i < preopens_len; i += 1) {
208 const struct Preopen *preopen = &preopens_buffer[i];
209 if (preopen->wasi_fd == wasi_fd) {
210 return preopen;
211 }
212 }
213 return NULL;
214}
215
216static const size_t max_memory = 2ul * 1024ul * 1024ul * 1024ul; // 2 GiB
217
218static uint16_t read_u16_le(const char *ptr) {
219 const uint8_t *u8_ptr = (const uint8_t *)ptr;
220 return
221 (((uint64_t)u8_ptr[0]) << 0x00) |
222 (((uint64_t)u8_ptr[1]) << 0x08);
223}
224
225static int16_t read_i16_le(const char *ptr) {
226 return read_u16_le(ptr);
227}
228
229static uint32_t read_u32_le(const char *ptr) {
230 const uint8_t *u8_ptr = (const uint8_t *)ptr;
231 return
232 (((uint64_t)u8_ptr[0]) << 0x00) |
233 (((uint64_t)u8_ptr[1]) << 0x08) |
234 (((uint64_t)u8_ptr[2]) << 0x10) |
235 (((uint64_t)u8_ptr[3]) << 0x18);
236}
237
238static uint32_t read_i32_le(const char *ptr) {
239 return read_u32_le(ptr);
240}
241
242static uint64_t read_u64_le(const char *ptr) {
243 const uint8_t *u8_ptr = (const uint8_t *)ptr;
244 return
245 (((uint64_t)u8_ptr[0]) << 0x00) |
246 (((uint64_t)u8_ptr[1]) << 0x08) |
247 (((uint64_t)u8_ptr[2]) << 0x10) |
248 (((uint64_t)u8_ptr[3]) << 0x18) |
249 (((uint64_t)u8_ptr[4]) << 0x20) |
250 (((uint64_t)u8_ptr[5]) << 0x28) |
251 (((uint64_t)u8_ptr[6]) << 0x30) |
252 (((uint64_t)u8_ptr[7]) << 0x38);
253}
254
255static void write_u16_le(char *ptr, uint16_t x) {
256 uint8_t *u8_ptr = (uint8_t*)ptr;
257 u8_ptr[0] = (x >> 0x00);
258 u8_ptr[1] = (x >> 0x08);
259}
260
261static void write_u32_le(char *ptr, uint32_t x) {
262 uint8_t *u8_ptr = (uint8_t*)ptr;
263 u8_ptr[0] = (x >> 0x00);
264 u8_ptr[1] = (x >> 0x08);
265 u8_ptr[2] = (x >> 0x10);
266 u8_ptr[3] = (x >> 0x18);
267}
268
269static void write_u64_le(char *ptr, uint64_t x) {
270 uint8_t *u8_ptr = (uint8_t*)ptr;
271 u8_ptr[0] = (x >> 0x00);
272 u8_ptr[1] = (x >> 0x08);
273 u8_ptr[2] = (x >> 0x10);
274 u8_ptr[3] = (x >> 0x18);
275 u8_ptr[4] = (x >> 0x20);
276 u8_ptr[5] = (x >> 0x28);
277 u8_ptr[6] = (x >> 0x30);
278 u8_ptr[7] = (x >> 0x38);
279}
280
281static uint32_t read32_uleb128(const char *ptr, uint32_t *i) {
282 uint32_t result = 0;
283 uint32_t shift = 0;
284
285 for (;;) {
286 uint32_t byte = ptr[*i];
287 *i += 1;
288 result |= ((byte & 0x7f) << shift);
289 shift += 7;
290 if ((byte & 0x80) == 0) return result;
291 if (shift >= 32) panic("read32_uleb128 failed");
292 }
293}
294
295static int64_t read64_ileb128(const char *ptr, uint32_t *i) {
296 int64_t result = 0;
297 uint32_t shift = 0;
298
299 for (;;) {
300 uint64_t byte = ptr[*i];
301 *i += 1;
302 result |= ((byte & 0x7f) << shift);
303 shift += 7;
304 if ((byte & 0x80) == 0) {
305 if ((byte & 0x40) && (shift < 64)) {
306 uint64_t extend = 0;
307 result |= (~extend << shift);
308 }
309 return result;
310 }
311 if (shift >= 64) panic("read64_ileb128 failed");
312 }
313}
314
315static int32_t read32_ileb128(const char *ptr, uint32_t *i) {
316 return read64_ileb128(ptr, i);
317}
318
319static struct ByteSlice read_name(char *ptr, uint32_t *i) {
320 uint32_t len = read32_uleb128(ptr, i);
321 struct ByteSlice res;
322 res.ptr = ptr + *i;
323 res.len = len;
324 *i += len;
325 return res;
326}
327
328enum Section {
329 Section_custom,
330 Section_type,
331 Section_import,
332 Section_function,
333 Section_table,
334 Section_memory,
335 Section_global,
336 Section_export,
337 Section_start,
338 Section_element,
339 Section_code,
340 Section_data,
341 Section_data_count,
342};
343
344enum Op {
345 Op_unreachable,
346 Op_br_void,
347 Op_br_32,
348 Op_br_64,
349 Op_br_if_nez_void,
350 Op_br_if_nez_32,
351 Op_br_if_nez_64,
352 Op_br_if_eqz_void,
353 Op_br_if_eqz_32,
354 Op_br_if_eqz_64,
355 Op_br_table_void,
356 Op_br_table_32,
357 Op_br_table_64,
358 Op_return_void,
359 Op_return_32,
360 Op_return_64,
361 Op_call,
362 Op_drop_32,
363 Op_drop_64,
364 Op_select_32,
365 Op_select_64,
366 Op_local_get_32,
367 Op_local_get_64,
368 Op_local_set_32,
369 Op_local_set_64,
370 Op_local_tee_32,
371 Op_local_tee_64,
372 Op_global_get_0_32,
373 Op_global_get_32,
374 Op_global_set_0_32,
375 Op_global_set_32,
376 Op_const_32,
377 Op_const_64,
378 Op_add_32,
379 Op_and_32,
380 Op_wasm,
381 Op_wasm_prefixed,
382};
383
384enum WasmOp {
385 WasmOp_unreachable = 0x00,
386 WasmOp_nop = 0x01,
387 WasmOp_block = 0x02,
388 WasmOp_loop = 0x03,
389 WasmOp_if = 0x04,
390 WasmOp_else = 0x05,
391 WasmOp_end = 0x0B,
392 WasmOp_br = 0x0C,
393 WasmOp_br_if = 0x0D,
394 WasmOp_br_table = 0x0E,
395 WasmOp_return = 0x0F,
396 WasmOp_call = 0x10,
397 WasmOp_call_indirect = 0x11,
398 WasmOp_drop = 0x1A,
399 WasmOp_select = 0x1B,
400 WasmOp_local_get = 0x20,
401 WasmOp_local_set = 0x21,
402 WasmOp_local_tee = 0x22,
403 WasmOp_global_get = 0x23,
404 WasmOp_global_set = 0x24,
405 WasmOp_i32_load = 0x28,
406 WasmOp_i64_load = 0x29,
407 WasmOp_f32_load = 0x2A,
408 WasmOp_f64_load = 0x2B,
409 WasmOp_i32_load8_s = 0x2C,
410 WasmOp_i32_load8_u = 0x2D,
411 WasmOp_i32_load16_s = 0x2E,
412 WasmOp_i32_load16_u = 0x2F,
413 WasmOp_i64_load8_s = 0x30,
414 WasmOp_i64_load8_u = 0x31,
415 WasmOp_i64_load16_s = 0x32,
416 WasmOp_i64_load16_u = 0x33,
417 WasmOp_i64_load32_s = 0x34,
418 WasmOp_i64_load32_u = 0x35,
419 WasmOp_i32_store = 0x36,
420 WasmOp_i64_store = 0x37,
421 WasmOp_f32_store = 0x38,
422 WasmOp_f64_store = 0x39,
423 WasmOp_i32_store8 = 0x3A,
424 WasmOp_i32_store16 = 0x3B,
425 WasmOp_i64_store8 = 0x3C,
426 WasmOp_i64_store16 = 0x3D,
427 WasmOp_i64_store32 = 0x3E,
428 WasmOp_memory_size = 0x3F,
429 WasmOp_memory_grow = 0x40,
430 WasmOp_i32_const = 0x41,
431 WasmOp_i64_const = 0x42,
432 WasmOp_f32_const = 0x43,
433 WasmOp_f64_const = 0x44,
434 WasmOp_i32_eqz = 0x45,
435 WasmOp_i32_eq = 0x46,
436 WasmOp_i32_ne = 0x47,
437 WasmOp_i32_lt_s = 0x48,
438 WasmOp_i32_lt_u = 0x49,
439 WasmOp_i32_gt_s = 0x4A,
440 WasmOp_i32_gt_u = 0x4B,
441 WasmOp_i32_le_s = 0x4C,
442 WasmOp_i32_le_u = 0x4D,
443 WasmOp_i32_ge_s = 0x4E,
444 WasmOp_i32_ge_u = 0x4F,
445 WasmOp_i64_eqz = 0x50,
446 WasmOp_i64_eq = 0x51,
447 WasmOp_i64_ne = 0x52,
448 WasmOp_i64_lt_s = 0x53,
449 WasmOp_i64_lt_u = 0x54,
450 WasmOp_i64_gt_s = 0x55,
451 WasmOp_i64_gt_u = 0x56,
452 WasmOp_i64_le_s = 0x57,
453 WasmOp_i64_le_u = 0x58,
454 WasmOp_i64_ge_s = 0x59,
455 WasmOp_i64_ge_u = 0x5A,
456 WasmOp_f32_eq = 0x5B,
457 WasmOp_f32_ne = 0x5C,
458 WasmOp_f32_lt = 0x5D,
459 WasmOp_f32_gt = 0x5E,
460 WasmOp_f32_le = 0x5F,
461 WasmOp_f32_ge = 0x60,
462 WasmOp_f64_eq = 0x61,
463 WasmOp_f64_ne = 0x62,
464 WasmOp_f64_lt = 0x63,
465 WasmOp_f64_gt = 0x64,
466 WasmOp_f64_le = 0x65,
467 WasmOp_f64_ge = 0x66,
468 WasmOp_i32_clz = 0x67,
469 WasmOp_i32_ctz = 0x68,
470 WasmOp_i32_popcnt = 0x69,
471 WasmOp_i32_add = 0x6A,
472 WasmOp_i32_sub = 0x6B,
473 WasmOp_i32_mul = 0x6C,
474 WasmOp_i32_div_s = 0x6D,
475 WasmOp_i32_div_u = 0x6E,
476 WasmOp_i32_rem_s = 0x6F,
477 WasmOp_i32_rem_u = 0x70,
478 WasmOp_i32_and = 0x71,
479 WasmOp_i32_or = 0x72,
480 WasmOp_i32_xor = 0x73,
481 WasmOp_i32_shl = 0x74,
482 WasmOp_i32_shr_s = 0x75,
483 WasmOp_i32_shr_u = 0x76,
484 WasmOp_i32_rotl = 0x77,
485 WasmOp_i32_rotr = 0x78,
486 WasmOp_i64_clz = 0x79,
487 WasmOp_i64_ctz = 0x7A,
488 WasmOp_i64_popcnt = 0x7B,
489 WasmOp_i64_add = 0x7C,
490 WasmOp_i64_sub = 0x7D,
491 WasmOp_i64_mul = 0x7E,
492 WasmOp_i64_div_s = 0x7F,
493 WasmOp_i64_div_u = 0x80,
494 WasmOp_i64_rem_s = 0x81,
495 WasmOp_i64_rem_u = 0x82,
496 WasmOp_i64_and = 0x83,
497 WasmOp_i64_or = 0x84,
498 WasmOp_i64_xor = 0x85,
499 WasmOp_i64_shl = 0x86,
500 WasmOp_i64_shr_s = 0x87,
501 WasmOp_i64_shr_u = 0x88,
502 WasmOp_i64_rotl = 0x89,
503 WasmOp_i64_rotr = 0x8A,
504 WasmOp_f32_abs = 0x8B,
505 WasmOp_f32_neg = 0x8C,
506 WasmOp_f32_ceil = 0x8D,
507 WasmOp_f32_floor = 0x8E,
508 WasmOp_f32_trunc = 0x8F,
509 WasmOp_f32_nearest = 0x90,
510 WasmOp_f32_sqrt = 0x91,
511 WasmOp_f32_add = 0x92,
512 WasmOp_f32_sub = 0x93,
513 WasmOp_f32_mul = 0x94,
514 WasmOp_f32_div = 0x95,
515 WasmOp_f32_min = 0x96,
516 WasmOp_f32_max = 0x97,
517 WasmOp_f32_copysign = 0x98,
518 WasmOp_f64_abs = 0x99,
519 WasmOp_f64_neg = 0x9A,
520 WasmOp_f64_ceil = 0x9B,
521 WasmOp_f64_floor = 0x9C,
522 WasmOp_f64_trunc = 0x9D,
523 WasmOp_f64_nearest = 0x9E,
524 WasmOp_f64_sqrt = 0x9F,
525 WasmOp_f64_add = 0xA0,
526 WasmOp_f64_sub = 0xA1,
527 WasmOp_f64_mul = 0xA2,
528 WasmOp_f64_div = 0xA3,
529 WasmOp_f64_min = 0xA4,
530 WasmOp_f64_max = 0xA5,
531 WasmOp_f64_copysign = 0xA6,
532 WasmOp_i32_wrap_i64 = 0xA7,
533 WasmOp_i32_trunc_f32_s = 0xA8,
534 WasmOp_i32_trunc_f32_u = 0xA9,
535 WasmOp_i32_trunc_f64_s = 0xAA,
536 WasmOp_i32_trunc_f64_u = 0xAB,
537 WasmOp_i64_extend_i32_s = 0xAC,
538 WasmOp_i64_extend_i32_u = 0xAD,
539 WasmOp_i64_trunc_f32_s = 0xAE,
540 WasmOp_i64_trunc_f32_u = 0xAF,
541 WasmOp_i64_trunc_f64_s = 0xB0,
542 WasmOp_i64_trunc_f64_u = 0xB1,
543 WasmOp_f32_convert_i32_s = 0xB2,
544 WasmOp_f32_convert_i32_u = 0xB3,
545 WasmOp_f32_convert_i64_s = 0xB4,
546 WasmOp_f32_convert_i64_u = 0xB5,
547 WasmOp_f32_demote_f64 = 0xB6,
548 WasmOp_f64_convert_i32_s = 0xB7,
549 WasmOp_f64_convert_i32_u = 0xB8,
550 WasmOp_f64_convert_i64_s = 0xB9,
551 WasmOp_f64_convert_i64_u = 0xBA,
552 WasmOp_f64_promote_f32 = 0xBB,
553 WasmOp_i32_reinterpret_f32 = 0xBC,
554 WasmOp_i64_reinterpret_f64 = 0xBD,
555 WasmOp_f32_reinterpret_i32 = 0xBE,
556 WasmOp_f64_reinterpret_i64 = 0xBF,
557 WasmOp_i32_extend8_s = 0xC0,
558 WasmOp_i32_extend16_s = 0xC1,
559 WasmOp_i64_extend8_s = 0xC2,
560 WasmOp_i64_extend16_s = 0xC3,
561 WasmOp_i64_extend32_s = 0xC4,
562
563 WasmOp_prefixed = 0xFC,
564};
565
566enum WasmPrefixedOp {
567 WasmPrefixedOp_i32_trunc_sat_f32_s = 0x00,
568 WasmPrefixedOp_i32_trunc_sat_f32_u = 0x01,
569 WasmPrefixedOp_i32_trunc_sat_f64_s = 0x02,
570 WasmPrefixedOp_i32_trunc_sat_f64_u = 0x03,
571 WasmPrefixedOp_i64_trunc_sat_f32_s = 0x04,
572 WasmPrefixedOp_i64_trunc_sat_f32_u = 0x05,
573 WasmPrefixedOp_i64_trunc_sat_f64_s = 0x06,
574 WasmPrefixedOp_i64_trunc_sat_f64_u = 0x07,
575 WasmPrefixedOp_memory_init = 0x08,
576 WasmPrefixedOp_data_drop = 0x09,
577 WasmPrefixedOp_memory_copy = 0x0A,
578 WasmPrefixedOp_memory_fill = 0x0B,
579 WasmPrefixedOp_table_init = 0x0C,
580 WasmPrefixedOp_elem_drop = 0x0D,
581 WasmPrefixedOp_table_copy = 0x0E,
582 WasmPrefixedOp_table_grow = 0x0F,
583 WasmPrefixedOp_table_size = 0x10,
584 WasmPrefixedOp_table_fill = 0x11,
585};
586
587static const uint32_t wasm_page_size = 64 * 1024;
588
589struct ProgramCounter {
590 uint32_t opcode;
591 uint32_t operand;
592};
593
594struct TypeInfo {
595 uint32_t param_count;
596 // bitset with param_count bits, indexed from lsb, 0 -> 32-bit, 1 -> 64-bit
597 uint32_t param_types;
598 uint32_t result_count;
599 // bitset with result_count bits, indexed from lsb, 0 -> 32-bit, 1 -> 64-bit
600 uint32_t result_types;
601};
602
603struct Function {
604 // Index to start of code in opcodes/operands.
605 struct ProgramCounter entry_pc;
606 uint32_t type_idx;
607 uint32_t locals_count;
608 // multi-word bitset with vm->types[type_idx].param_count + locals_count bits
609 // indexed from lsb of the first element, 0 -> 32-bit, 1 -> 64-bit
610 uint32_t *local_types;
611};
612
613enum ImpMod {
614 ImpMod_wasi_snapshot_preview1,
615};
616
617enum ImpName {
618 ImpName_args_get,
619 ImpName_args_sizes_get,
620 ImpName_clock_time_get,
621 ImpName_debug,
622 ImpName_debug_slice,
623 ImpName_environ_get,
624 ImpName_environ_sizes_get,
625 ImpName_fd_close,
626 ImpName_fd_fdstat_get,
627 ImpName_fd_filestat_get,
628 ImpName_fd_filestat_set_size,
629 ImpName_fd_filestat_set_times,
630 ImpName_fd_pread,
631 ImpName_fd_prestat_dir_name,
632 ImpName_fd_prestat_get,
633 ImpName_fd_pwrite,
634 ImpName_fd_read,
635 ImpName_fd_readdir,
636 ImpName_fd_write,
637 ImpName_path_create_directory,
638 ImpName_path_filestat_get,
639 ImpName_path_open,
640 ImpName_path_remove_directory,
641 ImpName_path_rename,
642 ImpName_path_unlink_file,
643 ImpName_proc_exit,
644 ImpName_random_get,
645};
646
647struct Import {
648 enum ImpMod mod;
649 enum ImpName name;
650 uint32_t type_idx;
651};
652
653struct VirtualMachine {
654 uint64_t *stack;
655 /// Points to one after the last stack item.
656 uint32_t stack_top;
657 struct ProgramCounter pc;
658 uint32_t memory_len;
659 const char *mod_ptr;
660 uint8_t *opcodes;
661 uint32_t *operands;
662 struct Function *functions;
663 /// Type index to start of type in module_bytes.
664 struct TypeInfo *types;
665 uint64_t *globals;
666 char *memory;
667 struct Import *imports;
668 uint32_t imports_len;
669 char **args;
670 uint32_t *table;
671};
672
673static int to_host_fd(int32_t wasi_fd) {
674 const struct Preopen *preopen = find_preopen(wasi_fd);
675 if (!preopen) return wasi_fd;
676 return preopen->host_fd;
677}
678
679static enum wasi_errno_t to_wasi_err(int err) {
680 switch (err) {
681 case EACCES: return WASI_EACCES;
682 case EDQUOT: return WASI_EDQUOT;
683 case EIO: return WASI_EIO;
684 case EFBIG: return WASI_EFBIG;
685 case ENOSPC: return WASI_ENOSPC;
686 case EPIPE: return WASI_EPIPE;
687 case EBADF: return WASI_EBADF;
688 case ENOMEM: return WASI_ENOMEM;
689 case ENOENT: return WASI_ENOENT;
690 case EEXIST: return WASI_EEXIST;
691 default:
692 fprintf(stderr, "unexpected errno: %s\n", strerror(err));
693 abort();
694 };
695}
696
697/// fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
698static enum wasi_errno_t wasi_args_sizes_get(struct VirtualMachine *vm,
699 uint32_t argc, uint32_t argv_buf_size)
700{
701 uint32_t args_len = 0;
702 size_t buf_size = 0;
703 while (vm->args[args_len]) {
704 buf_size += strlen(vm->args[args_len]) + 1;
705 args_len += 1;
706 }
707 write_u32_le(vm->memory + argc, args_len);
708 write_u32_le(vm->memory + argv_buf_size, buf_size);
709 return WASI_ESUCCESS;
710}
711
712/// extern fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t;
713static enum wasi_errno_t wasi_args_get(struct VirtualMachine *vm,
714 uint32_t argv, uint32_t argv_buf)
715{
716 panic("TODO implement wasi_args_get");
717 //var argv_buf_i: usize = 0;
718 //for (vm->args) |arg, arg_i| {
719 // // Write the arg to the buffer.
720 // const argv_ptr = argv_buf + argv_buf_i;
721 // const arg_len = mem.span(arg).len + 1;
722 // mem.copy(u8, vm->memory[argv_buf + argv_buf_i ..], arg[0..arg_len]);
723 // argv_buf_i += arg_len;
724
725 // write_u32_le(vm->memory[argv + 4 * arg_i ..][0..4], @intCast(u32, argv_ptr));
726 //}
727 return WASI_ESUCCESS;
728}
729
730/// extern fn random_get(buf: [*]u8, buf_len: usize) errno_t;
731static enum wasi_errno_t wasi_random_get(struct VirtualMachine *vm,
732 uint32_t buf, uint32_t buf_len)
733{
734 panic("TODO implement wasi_random_get");
735 //const host_buf = vm->memory[buf..][0..buf_len];
736 //std.crypto.random.bytes(host_buf);
737 return WASI_ESUCCESS;
738}
739
740/// fn fd_prestat_get(fd: fd_t, buf: *prestat_t) errno_t;
741/// const prestat_t = extern struct {
742/// pr_type: u8,
743/// u: usize,
744/// };
745static enum wasi_errno_t wasi_fd_prestat_get(struct VirtualMachine *vm,
746 int32_t fd, uint32_t buf)
747{
748 panic("TODO implement wasi_fd_prestat_get");
749 //const preopen = findPreopen(fd) orelse return .BADF;
750 //write_u32_le(vm->memory[buf + 0 ..][0..4], 0);
751 //write_u32_le(vm->memory[buf + 4 ..][0..4], @intCast(u32, preopen.name.len));
752 return WASI_ESUCCESS;
753}
754
755/// fn fd_prestat_dir_name(fd: fd_t, path: [*]u8, path_len: usize) errno_t;
756static enum wasi_errno_t wasi_fd_prestat_dir_name(struct VirtualMachine *vm,
757 int32_t fd, uint32_t path, uint32_t path_len)
758{
759 panic("TODO implement wasi_fd_prestat_dir_name");
760 //const preopen = findPreopen(fd) orelse return .BADF;
761 //assert(path_len == preopen.name.len);
762 //mem.copy(u8, vm->memory[path..], preopen.name);
763 return WASI_ESUCCESS;
764}
765
766/// extern fn fd_close(fd: fd_t) errno_t;
767static enum wasi_errno_t wasi_fd_close(struct VirtualMachine *vm, int32_t fd) {
768 panic("TODO implement wasi_fd_close");
769 //_ = vm;
770 //const host_fd = toHostFd(fd);
771 //os.close(host_fd);
772 return WASI_ESUCCESS;
773}
774
775static enum wasi_errno_t wasi_fd_read(
776 struct VirtualMachine *vm,
777 int32_t fd,
778 uint32_t iovs, // [*]const iovec_t
779 uint32_t iovs_len, // usize
780 uint32_t nread // *usize
781) {
782 panic("TODO implement wasi_fd_read");
783 //const host_fd = toHostFd(fd);
784 //var i: u32 = 0;
785 //var total_read: usize = 0;
786 //while (i < iovs_len) : (i += 1) {
787 // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
788 // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
789 // const buf = vm->memory[ptr..][0..len];
790 // const read = os.read(host_fd, buf) catch |err| return toWasiError(err);
791 // trace_log.debug("read {d} bytes out of {d}", .{ read, buf.len });
792 // total_read += read;
793 // if (read != buf.len) break;
794 //}
795 //write_u32_le(vm->memory[nread..][0..4], @intCast(u32, total_read));
796 return WASI_ESUCCESS;
797}
798
799/// extern fn fd_write(fd: fd_t, iovs: [*]const ciovec_t, iovs_len: usize, nwritten: *usize) errno_t;
800/// const ciovec_t = extern struct {
801/// base: [*]const u8,
802/// len: usize,
803/// };
804static enum wasi_errno_t wasi_fd_write(struct VirtualMachine *vm,
805 int32_t fd, uint32_t iovs, uint32_t iovs_len, uint32_t nwritten)
806{
807 int host_fd = to_host_fd(fd);
808 size_t total_written = 0;
809 for (uint32_t i = 0; i < iovs_len; i += 1) {
810 uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
811 uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
812 ssize_t written = write(host_fd, vm->memory + ptr, len);
813 if (written < 0) return to_wasi_err(errno);
814 total_written += written;
815 if (written != len) break;
816 }
817 write_u32_le(vm->memory + nwritten, total_written);
818 return WASI_ESUCCESS;
819}
820
821static enum wasi_errno_t wasi_fd_pwrite(
822 struct VirtualMachine *vm,
823 int32_t fd,
824 uint32_t iovs, // [*]const ciovec_t
825 uint32_t iovs_len, // usize
826 uint64_t offset, // wasi.filesize_t,
827 uint32_t written_ptr // *usize
828) {
829 panic("TODO implement wasi_fd_pwrite");
830 //const host_fd = toHostFd(fd);
831 //var i: u32 = 0;
832 //var written: usize = 0;
833 //while (i < iovs_len) : (i += 1) {
834 // uint32_t ptr = read_u32_le(vm->memory + iovs + i * 8 + 0);
835 // uint32_t len = read_u32_le(vm->memory + iovs + i * 8 + 4);
836 // const buf = vm->memory[ptr..][0..len];
837 // const w = os.pwrite(host_fd, buf, offset + written) catch |err| return toWasiError(err);
838 // written += w;
839 // if (w != buf.len) break;
840 //}
841 //write_u32_le(vm->memory[written_ptr..][0..4], @intCast(u32, written));
842 return WASI_ESUCCESS;
843}
844
845///extern fn path_open(
846/// dirfd: fd_t,
847/// dirflags: lookupflags_t,
848/// path: [*]const u8,
849/// path_len: usize,
850/// oflags: oflags_t,
851/// fs_rights_base: rights_t,
852/// fs_rights_inheriting: rights_t,
853/// fs_flags: fdflags_t,
854/// fd: *fd_t,
855///) errno_t;
856static enum wasi_errno_t wasi_path_open(
857 struct VirtualMachine *vm,
858 int32_t dirfd,
859 uint32_t dirflags, // wasi.lookupflags_t,
860 uint32_t path,
861 uint32_t path_len,
862 uint16_t oflags, // wasi.oflags_t,
863 uint64_t fs_rights_base, // wasi.rights_t,
864 uint64_t fs_rights_inheriting, // wasi.rights_t,
865 uint16_t fs_flags, // wasi.fdflags_t,
866 uint32_t fd
867) {
868 panic("TODO implement wasi_path_open");
869 //const sub_path = vm->memory[path..][0..path_len];
870 //const host_fd = toHostFd(dirfd);
871 //var flags: u32 = @as(u32, if (oflags & wasi.O.CREAT != 0) os.O.CREAT else 0) |
872 // @as(u32, if (oflags & wasi.O.DIRECTORY != 0) os.O.DIRECTORY else 0) |
873 // @as(u32, if (oflags & wasi.O.EXCL != 0) os.O.EXCL else 0) |
874 // @as(u32, if (oflags & wasi.O.TRUNC != 0) os.O.TRUNC else 0) |
875 // @as(u32, if (fs_flags & wasi.FDFLAG.APPEND != 0) os.O.APPEND else 0) |
876 // @as(u32, if (fs_flags & wasi.FDFLAG.DSYNC != 0) os.O.DSYNC else 0) |
877 // @as(u32, if (fs_flags & wasi.FDFLAG.NONBLOCK != 0) os.O.NONBLOCK else 0) |
878 // @as(u32, if (fs_flags & wasi.FDFLAG.SYNC != 0) os.O.SYNC else 0);
879 //if ((fs_rights_base & wasi.RIGHT.FD_READ != 0) and
880 // (fs_rights_base & wasi.RIGHT.FD_WRITE != 0))
881 //{
882 // flags |= os.O.RDWR;
883 //} else if (fs_rights_base & wasi.RIGHT.FD_WRITE != 0) {
884 // flags |= os.O.WRONLY;
885 //} else if (fs_rights_base & wasi.RIGHT.FD_READ != 0) {
886 // flags |= os.O.RDONLY; // no-op because O_RDONLY is 0
887 //}
888 //const mode = 0o644;
889 //const res_fd = os.openat(host_fd, sub_path, flags, mode) catch |err| return toWasiError(err);
890 //mem.writeIntLittle(i32, vm->memory[fd..][0..4], res_fd);
891 return WASI_ESUCCESS;
892}
893
894static enum wasi_errno_t wasi_path_filestat_get(
895 struct VirtualMachine *vm,
896 int32_t fd,
897 uint32_t flags, // wasi.lookupflags_t,
898 uint32_t path, // [*]const u8
899 uint32_t path_len, // usize
900 uint32_t buf // *filestat_t
901) {
902 panic("TODO implement wasi_path_filestat_get");
903 //const sub_path = vm->memory[path..][0..path_len];
904 //const host_fd = toHostFd(fd);
905 //const dir: fs.Dir = .{ .fd = host_fd };
906 //const stat = dir.statFile(sub_path) catch |err| return toWasiError(err);
907 //return finishWasiStat(vm, buf, stat);
908 return WASI_ESUCCESS;
909}
910
911/// extern fn path_create_directory(fd: fd_t, path: [*]const u8, path_len: usize) errno_t;
912static enum wasi_errno_t wasi_path_create_directory(struct VirtualMachine *vm, int32_t fd, uint32_t path, uint32_t path_len) {
913 panic("TODO implement wasi_path_create_directory");
914 //const sub_path = vm->memory[path..][0..path_len];
915 //trace_log.debug("wasi_path_create_directory fd={d} path={s}", .{ fd, sub_path });
916 //const host_fd = toHostFd(fd);
917 //const dir: fs.Dir = .{ .fd = host_fd };
918 //dir.makeDir(sub_path) catch |err| return toWasiError(err);
919 return WASI_ESUCCESS;
920}
921
922static enum wasi_errno_t wasi_path_rename(
923 struct VirtualMachine *vm,
924 int32_t old_fd,
925 uint32_t old_path_ptr, // [*]const u8
926 uint32_t old_path_len, // usize
927 int32_t new_fd,
928 uint32_t new_path_ptr, // [*]const u8
929 uint32_t new_path_len // usize
930) {
931 panic("TODO implement wasi_path_rename");
932 //const old_path = vm->memory[old_path_ptr..][0..old_path_len];
933 //const new_path = vm->memory[new_path_ptr..][0..new_path_len];
934 //trace_log.debug("wasi_path_rename old_fd={d} old_path={s} new_fd={d} new_path={s}", .{
935 // old_fd, old_path, new_fd, new_path,
936 //});
937 //const old_host_fd = toHostFd(old_fd);
938 //const new_host_fd = toHostFd(new_fd);
939 //os.renameat(old_host_fd, old_path, new_host_fd, new_path) catch |err| return toWasiError(err);
940 return WASI_ESUCCESS;
941}
942
943/// extern fn fd_filestat_get(fd: fd_t, buf: *filestat_t) errno_t;
944static enum wasi_errno_t wasi_fd_filestat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
945 panic("TODO implement wasi_fd_filestat_get");
946 //const host_fd = toHostFd(fd);
947 //const file = fs.File{ .handle = host_fd };
948 //const stat = file.stat() catch |err| return toWasiError(err);
949 //return finishWasiStat(vm, buf, stat);
950 return WASI_ESUCCESS;
951}
952
953static enum wasi_errno_t wasi_fd_filestat_set_size( struct VirtualMachine *vm,
954 int32_t fd, uint64_t size)
955{
956 panic("TODO implement wasi_fd_filestat_set_size");
957 //_ = vm;
958 //const host_fd = toHostFd(fd);
959 //os.ftruncate(host_fd, size) catch |err| return toWasiError(err);
960 return WASI_ESUCCESS;
961}
962
963/// pub extern "wasi_snapshot_preview1" fn fd_fdstat_get(fd: fd_t, buf: *fdstat_t) errno_t;
964/// pub const fdstat_t = extern struct {
965/// fs_filetype: filetype_t, u8
966/// fs_flags: fdflags_t, u16
967/// fs_rights_base: rights_t, u64
968/// fs_rights_inheriting: rights_t, u64
969/// };
970static enum wasi_errno_t wasi_fd_fdstat_get(struct VirtualMachine *vm, int32_t fd, uint32_t buf) {
971 panic("TODO implement wasi_fd_fdstat_get");
972 //const host_fd = toHostFd(fd);
973 //const file = fs.File{ .handle = host_fd };
974 //const stat = file.stat() catch |err| return toWasiError(err);
975 //mem.writeIntLittle(u16, vm->memory[buf + 0x00 ..][0..2], @enumToInt(toWasiFileType(stat.kind)));
976 //mem.writeIntLittle(u16, vm->memory[buf + 0x02 ..][0..2], 0); // flags
977 //mem.writeIntLittle(u64, vm->memory[buf + 0x08 ..][0..8], math.maxInt(u64)); // rights_base
978 //mem.writeIntLittle(u64, vm->memory[buf + 0x10 ..][0..8], math.maxInt(u64)); // rights_inheriting
979 return WASI_ESUCCESS;
980}
981
982/// extern fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t;
983static enum wasi_errno_t wasi_clock_time_get(struct VirtualMachine *vm,
984 uint32_t clock_id, uint64_t precision, uint32_t timestamp)
985{
986 panic("TODO implement wasi_clock_time_get");
987 ////const host_clock_id = toHostClockId(clock_id);
988 //_ = precision;
989 //_ = clock_id;
990 //const wasi_ts = toWasiTimestamp(std.time.nanoTimestamp());
991 //mem.writeIntLittle(u64, vm->memory[timestamp..][0..8], wasi_ts);
992 return WASI_ESUCCESS;
993}
994
995///pub extern "wasi_snapshot_preview1" fn debug(string: [*:0]const u8, x: u64) void;
996void wasi_debug(struct VirtualMachine *vm, uint32_t text, uint64_t n) {
997 panic("TODO implement wasi_debug");
998 //const s = mem.sliceTo(vm->memory[text..], 0);
999 //trace_log.debug("wasi_debug: '{s}' number={d} {x}", .{ s, n, n });
1000}
1001
1002/// pub extern "wasi_snapshot_preview1" fn debug_slice(ptr: [*]const u8, len: usize) void;
1003void wasi_debug_slice(struct VirtualMachine *vm, uint32_t ptr, uint32_t len) {
1004 panic("TODO implement wasi_debug_slice");
1005 //const s = vm->memory[ptr..][0..len];
1006 //trace_log.debug("wasi_debug_slice: '{s}'", .{s});
1007}
1008
1009
1010
1011struct Label {
1012 enum WasmOp opcode;
1013 uint32_t stack_depth;
1014 struct TypeInfo type_info;
1015 // this is a UINT32_MAX terminated linked list that is stored in the operands array
1016 uint32_t ref_list;
1017 union {
1018 struct ProgramCounter loop_pc;
1019 uint32_t else_ref;
1020 } extra;
1021};
1022
1023static uint32_t Label_operandCount(const struct Label *label) {
1024 if (label->opcode == WasmOp_loop) {
1025 return label->type_info.param_count;
1026 } else {
1027 return label->type_info.result_count;
1028 }
1029}
1030
1031static bool Label_operandType(const struct Label *label, uint32_t index) {
1032 if (label->opcode == WasmOp_loop) {
1033 return bs_isSet(&label->type_info.param_types, index);
1034 } else {
1035 return bs_isSet(&label->type_info.result_types, index);
1036 }
1037}
1038
1039static void vm_decodeCode(struct VirtualMachine *vm, struct Function *func, uint32_t *code_i,
1040 struct ProgramCounter *pc)
1041{
1042 const char *mod_ptr = vm->mod_ptr;
1043 uint8_t *opcodes = vm->opcodes;
1044 uint32_t *operands = vm->operands;
1045 struct TypeInfo *func_type_info = &vm->types[func->type_idx];
1046
1047 uint32_t unreachable_depth = 0;
1048 uint32_t stack_depth = func_type_info->param_count + func->locals_count + 2;
1049 static uint32_t stack_types[1 << (12 - 3)];
1050
1051 static struct Label labels[1 << 9];
1052 uint32_t label_i = 0;
1053 labels[label_i].opcode = WasmOp_block;
1054 labels[label_i].stack_depth = stack_depth;
1055 labels[label_i].type_info = vm->types[func->type_idx];
1056 labels[label_i].ref_list = UINT32_MAX;
1057
1058 for (;;) {
1059 enum WasmOp opcode = (uint8_t)mod_ptr[*code_i];
1060 *code_i += 1;
1061 enum WasmPrefixedOp prefixed_opcode;
1062 if (opcode == WasmOp_prefixed) prefixed_opcode = read32_uleb128(mod_ptr, code_i);
1063
1064 uint32_t initial_stack_depth = stack_depth;
1065 if (unreachable_depth == 0) {
1066 switch (opcode) {
1067 case WasmOp_unreachable:
1068 case WasmOp_nop:
1069 case WasmOp_block:
1070 case WasmOp_loop:
1071 case WasmOp_else:
1072 case WasmOp_end:
1073 case WasmOp_br:
1074 case WasmOp_call:
1075 case WasmOp_return:
1076 break;
1077
1078 case WasmOp_if:
1079 case WasmOp_br_if:
1080 case WasmOp_br_table:
1081 case WasmOp_call_indirect:
1082 case WasmOp_drop:
1083 case WasmOp_local_set:
1084 case WasmOp_global_set:
1085 stack_depth -= 1;
1086 break;
1087
1088 case WasmOp_select:
1089 stack_depth -= 2;
1090 break;
1091
1092 case WasmOp_local_get:
1093 case WasmOp_global_get:
1094 case WasmOp_memory_size:
1095 case WasmOp_i32_const:
1096 case WasmOp_i64_const:
1097 case WasmOp_f32_const:
1098 case WasmOp_f64_const:
1099 stack_depth += 1;
1100 break;
1101
1102 case WasmOp_local_tee:
1103 case WasmOp_i32_load:
1104 case WasmOp_i64_load:
1105 case WasmOp_f32_load:
1106 case WasmOp_f64_load:
1107 case WasmOp_i32_load8_s:
1108 case WasmOp_i32_load8_u:
1109 case WasmOp_i32_load16_s:
1110 case WasmOp_i32_load16_u:
1111 case WasmOp_i64_load8_s:
1112 case WasmOp_i64_load8_u:
1113 case WasmOp_i64_load16_s:
1114 case WasmOp_i64_load16_u:
1115 case WasmOp_i64_load32_s:
1116 case WasmOp_i64_load32_u:
1117 case WasmOp_memory_grow:
1118 case WasmOp_i32_eqz:
1119 case WasmOp_i32_clz:
1120 case WasmOp_i32_ctz:
1121 case WasmOp_i32_popcnt:
1122 case WasmOp_i64_eqz:
1123 case WasmOp_i64_clz:
1124 case WasmOp_i64_ctz:
1125 case WasmOp_i64_popcnt:
1126 case WasmOp_f32_abs:
1127 case WasmOp_f32_neg:
1128 case WasmOp_f32_ceil:
1129 case WasmOp_f32_floor:
1130 case WasmOp_f32_trunc:
1131 case WasmOp_f32_nearest:
1132 case WasmOp_f32_sqrt:
1133 case WasmOp_f64_abs:
1134 case WasmOp_f64_neg:
1135 case WasmOp_f64_ceil:
1136 case WasmOp_f64_floor:
1137 case WasmOp_f64_trunc:
1138 case WasmOp_f64_nearest:
1139 case WasmOp_f64_sqrt:
1140 case WasmOp_i32_wrap_i64:
1141 case WasmOp_i32_trunc_f32_s:
1142 case WasmOp_i32_trunc_f32_u:
1143 case WasmOp_i32_trunc_f64_s:
1144 case WasmOp_i32_trunc_f64_u:
1145 case WasmOp_i64_extend_i32_s:
1146 case WasmOp_i64_extend_i32_u:
1147 case WasmOp_i64_trunc_f32_s:
1148 case WasmOp_i64_trunc_f32_u:
1149 case WasmOp_i64_trunc_f64_s:
1150 case WasmOp_i64_trunc_f64_u:
1151 case WasmOp_f32_convert_i32_s:
1152 case WasmOp_f32_convert_i32_u:
1153 case WasmOp_f32_convert_i64_s:
1154 case WasmOp_f32_convert_i64_u:
1155 case WasmOp_f32_demote_f64:
1156 case WasmOp_f64_convert_i32_s:
1157 case WasmOp_f64_convert_i32_u:
1158 case WasmOp_f64_convert_i64_s:
1159 case WasmOp_f64_convert_i64_u:
1160 case WasmOp_f64_promote_f32:
1161 case WasmOp_i32_reinterpret_f32:
1162 case WasmOp_i64_reinterpret_f64:
1163 case WasmOp_f32_reinterpret_i32:
1164 case WasmOp_f64_reinterpret_i64:
1165 case WasmOp_i32_extend8_s:
1166 case WasmOp_i32_extend16_s:
1167 case WasmOp_i64_extend8_s:
1168 case WasmOp_i64_extend16_s:
1169 case WasmOp_i64_extend32_s:
1170 break;
1171
1172 case WasmOp_i32_store:
1173 case WasmOp_i64_store:
1174 case WasmOp_f32_store:
1175 case WasmOp_f64_store:
1176 case WasmOp_i32_store8:
1177 case WasmOp_i32_store16:
1178 case WasmOp_i64_store8:
1179 case WasmOp_i64_store16:
1180 case WasmOp_i64_store32:
1181 stack_depth -= 2;
1182 break;
1183
1184 case WasmOp_i32_eq:
1185 case WasmOp_i32_ne:
1186 case WasmOp_i32_lt_s:
1187 case WasmOp_i32_lt_u:
1188 case WasmOp_i32_gt_s:
1189 case WasmOp_i32_gt_u:
1190 case WasmOp_i32_le_s:
1191 case WasmOp_i32_le_u:
1192 case WasmOp_i32_ge_s:
1193 case WasmOp_i32_ge_u:
1194 case WasmOp_i64_eq:
1195 case WasmOp_i64_ne:
1196 case WasmOp_i64_lt_s:
1197 case WasmOp_i64_lt_u:
1198 case WasmOp_i64_gt_s:
1199 case WasmOp_i64_gt_u:
1200 case WasmOp_i64_le_s:
1201 case WasmOp_i64_le_u:
1202 case WasmOp_i64_ge_s:
1203 case WasmOp_i64_ge_u:
1204 case WasmOp_f32_eq:
1205 case WasmOp_f32_ne:
1206 case WasmOp_f32_lt:
1207 case WasmOp_f32_gt:
1208 case WasmOp_f32_le:
1209 case WasmOp_f32_ge:
1210 case WasmOp_f64_eq:
1211 case WasmOp_f64_ne:
1212 case WasmOp_f64_lt:
1213 case WasmOp_f64_gt:
1214 case WasmOp_f64_le:
1215 case WasmOp_f64_ge:
1216 case WasmOp_i32_add:
1217 case WasmOp_i32_sub:
1218 case WasmOp_i32_mul:
1219 case WasmOp_i32_div_s:
1220 case WasmOp_i32_div_u:
1221 case WasmOp_i32_rem_s:
1222 case WasmOp_i32_rem_u:
1223 case WasmOp_i32_and:
1224 case WasmOp_i32_or:
1225 case WasmOp_i32_xor:
1226 case WasmOp_i32_shl:
1227 case WasmOp_i32_shr_s:
1228 case WasmOp_i32_shr_u:
1229 case WasmOp_i32_rotl:
1230 case WasmOp_i32_rotr:
1231 case WasmOp_i64_add:
1232 case WasmOp_i64_sub:
1233 case WasmOp_i64_mul:
1234 case WasmOp_i64_div_s:
1235 case WasmOp_i64_div_u:
1236 case WasmOp_i64_rem_s:
1237 case WasmOp_i64_rem_u:
1238 case WasmOp_i64_and:
1239 case WasmOp_i64_or:
1240 case WasmOp_i64_xor:
1241 case WasmOp_i64_shl:
1242 case WasmOp_i64_shr_s:
1243 case WasmOp_i64_shr_u:
1244 case WasmOp_i64_rotl:
1245 case WasmOp_i64_rotr:
1246 case WasmOp_f32_add:
1247 case WasmOp_f32_sub:
1248 case WasmOp_f32_mul:
1249 case WasmOp_f32_div:
1250 case WasmOp_f32_min:
1251 case WasmOp_f32_max:
1252 case WasmOp_f32_copysign:
1253 case WasmOp_f64_add:
1254 case WasmOp_f64_sub:
1255 case WasmOp_f64_mul:
1256 case WasmOp_f64_div:
1257 case WasmOp_f64_min:
1258 case WasmOp_f64_max:
1259 case WasmOp_f64_copysign:
1260 stack_depth -= 1;
1261 break;
1262
1263 case WasmOp_prefixed:
1264 switch (prefixed_opcode) {
1265 case WasmPrefixedOp_i32_trunc_sat_f32_s:
1266 case WasmPrefixedOp_i32_trunc_sat_f32_u:
1267 case WasmPrefixedOp_i32_trunc_sat_f64_s:
1268 case WasmPrefixedOp_i32_trunc_sat_f64_u:
1269 case WasmPrefixedOp_i64_trunc_sat_f32_s:
1270 case WasmPrefixedOp_i64_trunc_sat_f32_u:
1271 case WasmPrefixedOp_i64_trunc_sat_f64_s:
1272 case WasmPrefixedOp_i64_trunc_sat_f64_u:
1273 break;
1274
1275 case WasmPrefixedOp_memory_init:
1276 case WasmPrefixedOp_memory_copy:
1277 case WasmPrefixedOp_memory_fill:
1278 case WasmPrefixedOp_table_init:
1279 case WasmPrefixedOp_table_copy:
1280 case WasmPrefixedOp_table_fill:
1281 stack_depth -= 3;
1282 break;
1283
1284 case WasmPrefixedOp_data_drop:
1285 case WasmPrefixedOp_elem_drop:
1286 break;
1287
1288 case WasmPrefixedOp_table_grow:
1289 stack_depth -= 1;
1290 break;
1291
1292 case WasmPrefixedOp_table_size:
1293 stack_depth += 1;
1294 break;
1295
1296 default: panic("unexpected prefixed opcode");
1297 }
1298 break;
1299
1300 default: panic("unexpected opcode");
1301 }
1302 switch (opcode) {
1303 case WasmOp_unreachable:
1304 case WasmOp_nop:
1305 case WasmOp_block:
1306 case WasmOp_loop:
1307 case WasmOp_else:
1308 case WasmOp_end:
1309 case WasmOp_br:
1310 case WasmOp_call:
1311 case WasmOp_return:
1312 case WasmOp_if:
1313 case WasmOp_br_if:
1314 case WasmOp_br_table:
1315 case WasmOp_call_indirect:
1316 case WasmOp_drop:
1317 case WasmOp_select:
1318 case WasmOp_local_set:
1319 case WasmOp_local_get:
1320 case WasmOp_local_tee:
1321 case WasmOp_global_set:
1322 case WasmOp_global_get:
1323 case WasmOp_i32_store:
1324 case WasmOp_i64_store:
1325 case WasmOp_f32_store:
1326 case WasmOp_f64_store:
1327 case WasmOp_i32_store8:
1328 case WasmOp_i32_store16:
1329 case WasmOp_i64_store8:
1330 case WasmOp_i64_store16:
1331 case WasmOp_i64_store32:
1332 break;
1333
1334 case WasmOp_i32_const:
1335 case WasmOp_f32_const:
1336 case WasmOp_memory_size:
1337 case WasmOp_i32_load:
1338 case WasmOp_f32_load:
1339 case WasmOp_i32_load8_s:
1340 case WasmOp_i32_load8_u:
1341 case WasmOp_i32_load16_s:
1342 case WasmOp_i32_load16_u:
1343 case WasmOp_memory_grow:
1344 case WasmOp_i32_eqz:
1345 case WasmOp_i32_clz:
1346 case WasmOp_i32_ctz:
1347 case WasmOp_i32_popcnt:
1348 case WasmOp_i64_eqz:
1349 case WasmOp_f32_abs:
1350 case WasmOp_f32_neg:
1351 case WasmOp_f32_ceil:
1352 case WasmOp_f32_floor:
1353 case WasmOp_f32_trunc:
1354 case WasmOp_f32_nearest:
1355 case WasmOp_f32_sqrt:
1356 case WasmOp_i32_wrap_i64:
1357 case WasmOp_i32_trunc_f32_s:
1358 case WasmOp_i32_trunc_f32_u:
1359 case WasmOp_i32_trunc_f64_s:
1360 case WasmOp_i32_trunc_f64_u:
1361 case WasmOp_f32_convert_i32_s:
1362 case WasmOp_f32_convert_i32_u:
1363 case WasmOp_f32_convert_i64_s:
1364 case WasmOp_f32_convert_i64_u:
1365 case WasmOp_f32_demote_f64:
1366 case WasmOp_i32_reinterpret_f32:
1367 case WasmOp_f32_reinterpret_i32:
1368 case WasmOp_i32_extend8_s:
1369 case WasmOp_i32_extend16_s:
1370 case WasmOp_i32_eq:
1371 case WasmOp_i32_ne:
1372 case WasmOp_i32_lt_s:
1373 case WasmOp_i32_lt_u:
1374 case WasmOp_i32_gt_s:
1375 case WasmOp_i32_gt_u:
1376 case WasmOp_i32_le_s:
1377 case WasmOp_i32_le_u:
1378 case WasmOp_i32_ge_s:
1379 case WasmOp_i32_ge_u:
1380 case WasmOp_i64_eq:
1381 case WasmOp_i64_ne:
1382 case WasmOp_i64_lt_s:
1383 case WasmOp_i64_lt_u:
1384 case WasmOp_i64_gt_s:
1385 case WasmOp_i64_gt_u:
1386 case WasmOp_i64_le_s:
1387 case WasmOp_i64_le_u:
1388 case WasmOp_i64_ge_s:
1389 case WasmOp_i64_ge_u:
1390 case WasmOp_f32_eq:
1391 case WasmOp_f32_ne:
1392 case WasmOp_f32_lt:
1393 case WasmOp_f32_gt:
1394 case WasmOp_f32_le:
1395 case WasmOp_f32_ge:
1396 case WasmOp_f64_eq:
1397 case WasmOp_f64_ne:
1398 case WasmOp_f64_lt:
1399 case WasmOp_f64_gt:
1400 case WasmOp_f64_le:
1401 case WasmOp_f64_ge:
1402 case WasmOp_i32_add:
1403 case WasmOp_i32_sub:
1404 case WasmOp_i32_mul:
1405 case WasmOp_i32_div_s:
1406 case WasmOp_i32_div_u:
1407 case WasmOp_i32_rem_s:
1408 case WasmOp_i32_rem_u:
1409 case WasmOp_i32_and:
1410 case WasmOp_i32_or:
1411 case WasmOp_i32_xor:
1412 case WasmOp_i32_shl:
1413 case WasmOp_i32_shr_s:
1414 case WasmOp_i32_shr_u:
1415 case WasmOp_i32_rotl:
1416 case WasmOp_i32_rotr:
1417 case WasmOp_f32_add:
1418 case WasmOp_f32_sub:
1419 case WasmOp_f32_mul:
1420 case WasmOp_f32_div:
1421 case WasmOp_f32_min:
1422 case WasmOp_f32_max:
1423 case WasmOp_f32_copysign:
1424 bs_unset(stack_types, stack_depth - 1);
1425 break;
1426
1427 case WasmOp_i64_const:
1428 case WasmOp_f64_const:
1429 case WasmOp_i64_load:
1430 case WasmOp_f64_load:
1431 case WasmOp_i64_load8_s:
1432 case WasmOp_i64_load8_u:
1433 case WasmOp_i64_load16_s:
1434 case WasmOp_i64_load16_u:
1435 case WasmOp_i64_load32_s:
1436 case WasmOp_i64_load32_u:
1437 case WasmOp_i64_clz:
1438 case WasmOp_i64_ctz:
1439 case WasmOp_i64_popcnt:
1440 case WasmOp_f64_abs:
1441 case WasmOp_f64_neg:
1442 case WasmOp_f64_ceil:
1443 case WasmOp_f64_floor:
1444 case WasmOp_f64_trunc:
1445 case WasmOp_f64_nearest:
1446 case WasmOp_f64_sqrt:
1447 case WasmOp_i64_extend_i32_s:
1448 case WasmOp_i64_extend_i32_u:
1449 case WasmOp_i64_trunc_f32_s:
1450 case WasmOp_i64_trunc_f32_u:
1451 case WasmOp_i64_trunc_f64_s:
1452 case WasmOp_i64_trunc_f64_u:
1453 case WasmOp_f64_convert_i32_s:
1454 case WasmOp_f64_convert_i32_u:
1455 case WasmOp_f64_convert_i64_s:
1456 case WasmOp_f64_convert_i64_u:
1457 case WasmOp_f64_promote_f32:
1458 case WasmOp_i64_reinterpret_f64:
1459 case WasmOp_f64_reinterpret_i64:
1460 case WasmOp_i64_extend8_s:
1461 case WasmOp_i64_extend16_s:
1462 case WasmOp_i64_extend32_s:
1463 case WasmOp_i64_add:
1464 case WasmOp_i64_sub:
1465 case WasmOp_i64_mul:
1466 case WasmOp_i64_div_s:
1467 case WasmOp_i64_div_u:
1468 case WasmOp_i64_rem_s:
1469 case WasmOp_i64_rem_u:
1470 case WasmOp_i64_and:
1471 case WasmOp_i64_or:
1472 case WasmOp_i64_xor:
1473 case WasmOp_i64_shl:
1474 case WasmOp_i64_shr_s:
1475 case WasmOp_i64_shr_u:
1476 case WasmOp_i64_rotl:
1477 case WasmOp_i64_rotr:
1478 case WasmOp_f64_add:
1479 case WasmOp_f64_sub:
1480 case WasmOp_f64_mul:
1481 case WasmOp_f64_div:
1482 case WasmOp_f64_min:
1483 case WasmOp_f64_max:
1484 case WasmOp_f64_copysign:
1485 bs_set(stack_types, stack_depth - 1);
1486 break;
1487
1488 case WasmOp_prefixed:
1489 switch (prefixed_opcode) {
1490 case WasmPrefixedOp_memory_init:
1491 case WasmPrefixedOp_memory_copy:
1492 case WasmPrefixedOp_memory_fill:
1493 case WasmPrefixedOp_table_init:
1494 case WasmPrefixedOp_table_copy:
1495 case WasmPrefixedOp_table_fill:
1496 case WasmPrefixedOp_data_drop:
1497 case WasmPrefixedOp_elem_drop:
1498 break;
1499
1500 case WasmPrefixedOp_i32_trunc_sat_f32_s:
1501 case WasmPrefixedOp_i32_trunc_sat_f32_u:
1502 case WasmPrefixedOp_i32_trunc_sat_f64_s:
1503 case WasmPrefixedOp_i32_trunc_sat_f64_u:
1504 case WasmPrefixedOp_table_grow:
1505 case WasmPrefixedOp_table_size:
1506 bs_unset(stack_types, stack_depth - 1);
1507 break;
1508
1509 case WasmPrefixedOp_i64_trunc_sat_f32_s:
1510 case WasmPrefixedOp_i64_trunc_sat_f32_u:
1511 case WasmPrefixedOp_i64_trunc_sat_f64_s:
1512 case WasmPrefixedOp_i64_trunc_sat_f64_u:
1513 bs_set(stack_types, stack_depth - 1);
1514 break;
1515
1516 default: panic("unexpected prefixed opcode");
1517 }
1518 break;
1519
1520 default: panic("unexpected opcode");
1521 }
1522 }
1523
1524 switch (opcode) {
1525 case WasmOp_unreachable:
1526 if (unreachable_depth == 0) {
1527 opcodes[pc->opcode] = Op_unreachable;
1528 pc->opcode += 1;
1529 }
1530 break;
1531
1532 case WasmOp_nop:
1533 case WasmOp_i32_reinterpret_f32:
1534 case WasmOp_i64_reinterpret_f64:
1535 case WasmOp_f32_reinterpret_i32:
1536 case WasmOp_f64_reinterpret_i64:
1537 break;
1538
1539 case WasmOp_block:
1540 case WasmOp_loop:
1541 case WasmOp_if:
1542 {
1543 int64_t block_type = read64_ileb128(mod_ptr, code_i);
1544 if (unreachable_depth == 0) {
1545 label_i += 1;
1546 struct Label *label = &labels[label_i];
1547 label->opcode = opcode;
1548 if (block_type < 0) {
1549 label->type_info.param_count = 0;
1550 label->type_info.param_types = 0;
1551 label->type_info.result_count = block_type != -0x40;
1552 label->type_info.result_types = 0;
1553 switch (block_type) {
1554 case -0x40: break;
1555 case -1: case -3: bs_unset(&label->type_info.param_types, 0); break;
1556 case -2: case -4: bs_set(&label->type_info.param_types, 0); break;
1557 default: panic("unexpected param type");
1558 }
1559 } else {
1560 label->type_info = vm->types[block_type];
1561 }
1562 label->stack_depth = stack_depth - label->type_info.param_count;
1563 label->ref_list = UINT32_MAX;
1564 switch (opcode) {
1565 case WasmOp_block:
1566 break;
1567
1568 case WasmOp_loop:
1569 label->extra.loop_pc = *pc;
1570 break;
1571
1572 case WasmOp_if:
1573 opcodes[pc->opcode] = Op_br_if_eqz_void;
1574 pc->opcode += 1;
1575 operands[pc->operand] = 0;
1576 label->extra.else_ref = pc->operand + 1;
1577 pc->operand += 3;
1578 break;
1579
1580 default: panic("unexpected label opcode");
1581 }
1582 }
1583 }
1584 break;
1585
1586 case WasmOp_else:
1587 {
1588 struct Label *label = &labels[label_i];
1589 assert(label->opcode == WasmOp_if);
1590 label->opcode = WasmOp_else;
1591 if (unreachable_depth == 0) {
1592 uint32_t operand_count = Label_operandCount(label);
1593 switch (operand_count) {
1594 case 0:
1595 opcodes[pc->opcode] = Op_br_void;
1596 break;
1597
1598 case 1:
1599 switch ((int)Label_operandType(label, 0)) {
1600 case false: opcodes[pc->opcode] = Op_br_32; break;
1601 case true: opcodes[pc->opcode] = Op_br_64; break;
1602 }
1603 break;
1604
1605 default: panic("unexpected operand count");
1606 }
1607 pc->opcode += 1;
1608 operands[pc->operand + 0] = stack_depth - operand_count - label->stack_depth;
1609 operands[pc->operand + 1] = label->ref_list;
1610 label->ref_list = pc->operand + 1;
1611 pc->operand += 3;
1612 assert(stack_depth - label->type_info.result_count == label->stack_depth);
1613 } else unreachable_depth = 0;
1614 operands[label->extra.else_ref + 0] = pc->opcode;
1615 operands[label->extra.else_ref + 1] = pc->operand;
1616 stack_depth = label->stack_depth + label->type_info.param_count;
1617 };
1618 break;
1619
1620 case WasmOp_end:
1621 if (unreachable_depth <= 1) {
1622 unreachable_depth = 0;
1623 struct Label *label = &labels[label_i];
1624 struct ProgramCounter *target_pc = (label->opcode == WasmOp_loop) ? &label->extra.loop_pc : pc;
1625 if (label->opcode == WasmOp_if) {
1626 operands[label->extra.else_ref + 0] = target_pc->opcode;
1627 operands[label->extra.else_ref + 1] = target_pc->operand;
1628 }
1629 uint32_t ref = label->ref_list;
1630 while (ref != UINT32_MAX) {
1631 uint32_t next_ref = operands[ref];
1632 operands[ref + 0] = target_pc->opcode;
1633 operands[ref + 1] = target_pc->operand;
1634 ref = next_ref;
1635 }
1636 stack_depth = label->stack_depth + label->type_info.result_count;
1637
1638 if (label_i == 0) {
1639 uint32_t operand_count = Label_operandCount(&labels[0]);
1640 switch (operand_count) {
1641 case 0:
1642 opcodes[pc->opcode] = Op_return_void;
1643 break;
1644
1645 case 1:
1646 switch ((int)Label_operandType(&labels[0], 0)) {
1647 case false: opcodes[pc->opcode] = Op_return_32; break;
1648 case true: opcodes[pc->opcode] = Op_return_64; break;
1649 }
1650 break;
1651
1652 default: panic("unexpected operand count");
1653 }
1654 pc->opcode += 1;
1655 operands[pc->operand + 0] = 2 + operand_count;
1656 stack_depth -= operand_count;
1657 assert(stack_depth == labels[0].stack_depth);
1658 operands[pc->operand + 1] = stack_depth;
1659 pc->operand += 2;
1660 return;
1661 }
1662 label_i -= 1;
1663 } else unreachable_depth -= 1;
1664 break;
1665
1666 case WasmOp_br:
1667 case WasmOp_br_if:
1668 {
1669 uint32_t label_idx = read32_uleb128(mod_ptr, code_i);
1670 if (unreachable_depth == 0) {
1671 struct Label *label = &labels[label_i - label_idx];
1672 uint32_t operand_count = Label_operandCount(label);
1673 switch (opcode) {
1674 case WasmOp_br:
1675 switch (operand_count) {
1676 case 0:
1677 opcodes[pc->opcode] = Op_br_void;
1678 break;
1679
1680 case 1:
1681 switch ((int)Label_operandType(label, 0)) {
1682 case false: opcodes[pc->opcode] = Op_br_32; break;
1683 case true: opcodes[pc->opcode] = Op_br_64; break;
1684 }
1685 break;
1686
1687 default: panic("unexpected operand count");
1688 }
1689 break;
1690
1691 case WasmOp_br_if:
1692 switch (operand_count) {
1693 case 0:
1694 opcodes[pc->opcode] = Op_br_if_nez_void;
1695 break;
1696
1697 case 1:
1698 switch ((int)Label_operandType(label, 0)) {
1699 case false: opcodes[pc->opcode] = Op_br_if_nez_32; break;
1700 case true: opcodes[pc->opcode] = Op_br_if_nez_64; break;
1701 }
1702 break;
1703
1704 default: panic("unexpected operand count");
1705 }
1706 break;
1707
1708 default: panic("unexpected opcode");
1709 }
1710 pc->opcode += 1;
1711 operands[pc->operand + 0] = stack_depth - operand_count - label->stack_depth;
1712 operands[pc->operand + 1] = label->ref_list;
1713 label->ref_list = pc->operand + 1;
1714 pc->operand += 3;
1715 }
1716 }
1717 break;
1718
1719 case WasmOp_br_table:
1720 {
1721 uint32_t labels_len = read32_uleb128(mod_ptr, code_i);
1722 for (uint32_t i = 0; i <= labels_len; i += 1) {
1723 uint32_t label_idx = read32_uleb128(mod_ptr, code_i);
1724 if (unreachable_depth != 0) continue;
1725 struct Label *label = &labels[label_i - label_idx];
1726 uint32_t operand_count = Label_operandCount(label);
1727 if (i == 0) {
1728 switch (operand_count) {
1729 case 0:
1730 opcodes[pc->opcode] = Op_br_table_void;
1731 break;
1732
1733 case 1:
1734 switch ((int)Label_operandType(label, 0)) {
1735 case false: opcodes[pc->opcode] = Op_br_table_32; break;
1736 case true: opcodes[pc->opcode] = Op_br_table_64; break;
1737 }
1738 break;
1739
1740 default: panic("unexpected operand count");
1741 }
1742 pc->opcode += 1;
1743 operands[pc->operand] = labels_len;
1744 pc->operand += 1;
1745 }
1746 operands[pc->operand + 0] = stack_depth - operand_count - label->stack_depth;
1747 operands[pc->operand + 1] = label->ref_list;
1748 label->ref_list = pc->operand + 1;
1749 pc->operand += 3;
1750 }
1751
1752 opcodes[pc->opcode] = opcode;
1753 pc->opcode += 1;
1754 operands[pc->operand] = labels_len;
1755 pc->operand += 1;
1756 }
1757 break;
1758
1759 case WasmOp_call:
1760 {
1761 uint32_t fn_id = read32_uleb128(mod_ptr, code_i);
1762 if (unreachable_depth == 0) {
1763 opcodes[pc->opcode] = Op_call;
1764 pc->opcode += 1;
1765 operands[pc->operand] = fn_id;
1766 pc->operand += 1;
1767 uint32_t type_idx = (fn_id < vm->imports_len) ?
1768 vm->imports[fn_id].type_idx :
1769 vm->functions[fn_id - vm->imports_len].type_idx;
1770 struct TypeInfo *type_info = &vm->types[type_idx];
1771 stack_depth -= type_info->param_count;
1772 for (uint32_t result_i = 0; result_i < type_info->result_count; result_i += 1)
1773 bs_setValue(stack_types, stack_depth + result_i,
1774 bs_isSet(&type_info->result_types, result_i));
1775 stack_depth += type_info->result_count;
1776 }
1777 }
1778 break;
1779
1780 case WasmOp_call_indirect:
1781 {
1782 uint32_t type_idx = read32_uleb128(mod_ptr, code_i);
1783 if (read32_uleb128(mod_ptr, code_i) != 0) panic("unexpected table index");
1784 if (unreachable_depth == 0) {
1785 opcodes[pc->opcode + 0] = Op_wasm;
1786 opcodes[pc->opcode + 1] = opcode;
1787 pc->opcode += 2;
1788 struct TypeInfo *type_info = &vm->types[type_idx];
1789 stack_depth -= type_info->param_count;
1790 for (uint32_t result_i = 0; result_i < type_info->result_count; result_i += 1)
1791 bs_setValue(stack_types, stack_depth + result_i,
1792 bs_isSet(&type_info->result_types, result_i));
1793 stack_depth += type_info->result_count;
1794 }
1795 }
1796 break;
1797
1798 case WasmOp_return:
1799 {
1800 uint32_t operand_count = Label_operandCount(&labels[0]);
1801 switch (operand_count) {
1802 case 0:
1803 opcodes[pc->opcode] = Op_return_void;
1804 break;
1805
1806 case 1:
1807 switch ((int)Label_operandType(&labels[0], 0)) {
1808 case false: opcodes[pc->opcode] = Op_return_32; break;
1809 case true: opcodes[pc->opcode] = Op_return_64; break;
1810 }
1811 break;
1812
1813 default: panic("unexpected operand count");
1814 }
1815 pc->opcode += 1;
1816 operands[pc->operand + 0] = 2 + stack_depth - labels[0].stack_depth;
1817 stack_depth -= operand_count;
1818 operands[pc->operand + 1] = stack_depth;
1819 pc->operand += 2;
1820 }
1821 break;
1822
1823 case WasmOp_select:
1824 case WasmOp_drop:
1825 if (unreachable_depth == 0) {
1826 switch ((int)bs_isSet(stack_types, stack_depth)) {
1827 case false:
1828 switch (opcode) {
1829 case WasmOp_select:
1830 opcodes[pc->opcode] = Op_select_32;
1831 break;
1832
1833 case WasmOp_drop:
1834 opcodes[pc->opcode] = Op_drop_32;
1835 break;
1836
1837 default: panic("unexpected opcode");
1838 }
1839 break;
1840
1841 case true:
1842 switch (opcode) {
1843 case WasmOp_select:
1844 opcodes[pc->opcode] = Op_select_64;
1845 break;
1846
1847 case WasmOp_drop:
1848 opcodes[pc->opcode] = Op_drop_64;
1849 break;
1850
1851 default: panic("unexpected opcode");
1852 }
1853 break;
1854 }
1855 pc->opcode += 1;
1856 }
1857 break;
1858
1859 case WasmOp_local_get:
1860 case WasmOp_local_set:
1861 case WasmOp_local_tee:
1862 {
1863 uint32_t local_idx = read32_uleb128(mod_ptr, code_i);
1864 if (unreachable_depth == 0) {
1865 bool local_type = bs_isSet(func->local_types, local_idx);
1866 switch ((int)local_type) {
1867 case false:
1868 switch (opcode) {
1869 case WasmOp_local_get:
1870 opcodes[pc->opcode] = Op_local_get_32;
1871 break;
1872
1873 case WasmOp_local_set:
1874 opcodes[pc->opcode] = Op_local_set_32;
1875 break;
1876
1877 case WasmOp_local_tee:
1878 opcodes[pc->opcode] = Op_local_tee_32;
1879 break;
1880
1881 default: panic("unexpected opcode");
1882 }
1883 break;
1884
1885 case true:
1886 switch (opcode) {
1887 case WasmOp_local_get:
1888 opcodes[pc->opcode] = Op_local_get_64;
1889 break;
1890
1891 case WasmOp_local_set:
1892 opcodes[pc->opcode] = Op_local_set_64;
1893 break;
1894
1895 case WasmOp_local_tee:
1896 opcodes[pc->opcode] = Op_local_tee_64;
1897 break;
1898
1899 default: panic("unexpected opcode");
1900 }
1901 break;
1902 }
1903 pc->opcode += 1;
1904 operands[pc->operand] = initial_stack_depth - local_idx;
1905 pc->operand += 1;
1906 if (opcode == WasmOp_local_get) bs_setValue(stack_types, stack_depth - 1, local_type);
1907 }
1908 }
1909 break;
1910
1911 case WasmOp_global_get:
1912 case WasmOp_global_set:
1913 {
1914 uint32_t global_idx = read32_uleb128(mod_ptr, code_i);
1915 if (unreachable_depth == 0) {
1916 switch (global_idx) {
1917 case 0:
1918 switch (opcode) {
1919 case WasmOp_global_get:
1920 opcodes[pc->opcode] = Op_global_get_0_32;
1921 break;
1922
1923 case WasmOp_global_set:
1924 opcodes[pc->opcode] = Op_global_set_0_32;
1925 break;
1926
1927 default: panic("unexpected opcode");
1928 }
1929 break;
1930
1931 default:
1932 switch (opcode) {
1933 case WasmOp_global_get:
1934 opcodes[pc->opcode] = Op_global_get_32;
1935 break;
1936
1937 case WasmOp_global_set:
1938 opcodes[pc->opcode] = Op_global_set_32;
1939 break;
1940
1941 default: panic("unexpected opcode");
1942 }
1943 break;
1944 }
1945 pc->opcode += 1;
1946 if (global_idx != 0) {
1947 operands[pc->operand] = global_idx;
1948 pc->operand += 1;
1949 }
1950 }
1951 }
1952 break;
1953
1954 case WasmOp_i32_load:
1955 case WasmOp_i64_load:
1956 case WasmOp_f32_load:
1957 case WasmOp_f64_load:
1958 case WasmOp_i32_load8_s:
1959 case WasmOp_i32_load8_u:
1960 case WasmOp_i32_load16_s:
1961 case WasmOp_i32_load16_u:
1962 case WasmOp_i64_load8_s:
1963 case WasmOp_i64_load8_u:
1964 case WasmOp_i64_load16_s:
1965 case WasmOp_i64_load16_u:
1966 case WasmOp_i64_load32_s:
1967 case WasmOp_i64_load32_u:
1968 case WasmOp_i32_store:
1969 case WasmOp_i64_store:
1970 case WasmOp_f32_store:
1971 case WasmOp_f64_store:
1972 case WasmOp_i32_store8:
1973 case WasmOp_i32_store16:
1974 case WasmOp_i64_store8:
1975 case WasmOp_i64_store16:
1976 case WasmOp_i64_store32:
1977 {
1978 uint32_t alignment = read32_uleb128(mod_ptr, code_i);
1979 uint32_t offset = read32_uleb128(mod_ptr, code_i);
1980 (void)alignment;
1981 if (unreachable_depth == 0) {
1982 opcodes[pc->opcode + 0] = Op_wasm;
1983 opcodes[pc->opcode + 1] = opcode;
1984 pc->opcode += 2;
1985 operands[pc->operand] = offset;
1986 pc->operand += 1;
1987 }
1988 }
1989 break;
1990
1991 case WasmOp_memory_size:
1992 case WasmOp_memory_grow:
1993 {
1994 if (mod_ptr[*code_i] != 0) panic("unexpected memory index");
1995 *code_i += 1;
1996 if (unreachable_depth == 0) {
1997 opcodes[pc->opcode + 0] = Op_wasm;
1998 opcodes[pc->opcode + 1] = opcode;
1999 pc->opcode += 2;
2000 }
2001 }
2002 break;
2003
2004 case WasmOp_i32_const:
2005 {
2006 uint32_t x = read32_ileb128(mod_ptr, code_i);
2007 if (unreachable_depth == 0) {
2008 opcodes[pc->opcode] = Op_const_32;
2009 pc->opcode += 1;
2010 operands[pc->operand] = x;
2011 pc->operand += 1;
2012 }
2013 }
2014 break;
2015
2016 case WasmOp_i64_const:
2017 {
2018 uint64_t x = read64_ileb128(mod_ptr, code_i);
2019 if (unreachable_depth == 0) {
2020 opcodes[pc->opcode] = Op_const_64;
2021 pc->opcode += 1;
2022 operands[pc->operand + 0] = x & UINT32_MAX;
2023 operands[pc->operand + 1] = (x >> 32) & UINT32_MAX;
2024 pc->operand += 2;
2025 }
2026 }
2027 break;
2028
2029 case WasmOp_f32_const:
2030 {
2031 uint32_t x;
2032 memcpy(&x, mod_ptr + *code_i, 4);
2033 *code_i += 4;
2034 if (unreachable_depth == 0) {
2035 opcodes[pc->opcode] = Op_const_32;
2036 pc->opcode += 1;
2037 operands[pc->operand] = x;
2038 pc->operand += 1;
2039 }
2040 }
2041 break;
2042
2043 case WasmOp_f64_const:
2044 {
2045 uint64_t x;
2046 memcpy(&x, mod_ptr + *code_i, 8);
2047 *code_i += 8;
2048 if (unreachable_depth == 0) {
2049 opcodes[pc->opcode] = Op_const_64;
2050 pc->opcode += 1;
2051 operands[pc->operand + 0] = x & UINT32_MAX;
2052 operands[pc->operand + 1] = (x >> 32) & UINT32_MAX;
2053 pc->operand += 2;
2054 }
2055 }
2056 break;
2057
2058 case WasmOp_i32_add:
2059 opcodes[pc->opcode] = Op_add_32;
2060 pc->opcode += 1;
2061 break;
2062
2063 case WasmOp_i32_and:
2064 opcodes[pc->opcode] = Op_and_32;
2065 pc->opcode += 1;
2066 break;
2067
2068 default:
2069 opcodes[pc->opcode + 0] = Op_wasm;
2070 opcodes[pc->opcode + 1] = opcode;
2071 pc->opcode += 2;
2072 break;
2073
2074 case WasmOp_prefixed:
2075 switch (prefixed_opcode) {
2076 case WasmPrefixedOp_i32_trunc_sat_f32_s:
2077 case WasmPrefixedOp_i32_trunc_sat_f32_u:
2078 case WasmPrefixedOp_i32_trunc_sat_f64_s:
2079 case WasmPrefixedOp_i32_trunc_sat_f64_u:
2080 case WasmPrefixedOp_i64_trunc_sat_f32_s:
2081 case WasmPrefixedOp_i64_trunc_sat_f32_u:
2082 case WasmPrefixedOp_i64_trunc_sat_f64_s:
2083 case WasmPrefixedOp_i64_trunc_sat_f64_u:
2084 if (unreachable_depth == 0) {
2085 opcodes[pc->opcode + 0] = Op_wasm_prefixed;
2086 opcodes[pc->opcode + 1] = prefixed_opcode;
2087 pc->opcode += 2;
2088 }
2089 break;
2090
2091 case WasmPrefixedOp_memory_copy:
2092 if (mod_ptr[*code_i + 0] != 0 || mod_ptr[*code_i + 1] != 0)
2093 panic("unexpected memory index");
2094 *code_i += 2;
2095 if (unreachable_depth == 0) {
2096 opcodes[pc->opcode + 0] = Op_wasm_prefixed;
2097 opcodes[pc->opcode + 1] = prefixed_opcode;
2098 pc->opcode += 2;
2099 }
2100 break;
2101
2102 case WasmPrefixedOp_memory_fill:
2103 if (mod_ptr[*code_i] != 0) panic("unexpected memory index");
2104 *code_i += 1;
2105 if (unreachable_depth == 0) {
2106 opcodes[pc->opcode + 0] = Op_wasm_prefixed;
2107 opcodes[pc->opcode + 1] = prefixed_opcode;
2108 pc->opcode += 2;
2109 }
2110 break;
2111
2112 default: panic("unreachable");
2113 }
2114 break;
2115 }
2116
2117 switch (opcode) {
2118 case WasmOp_unreachable:
2119 case WasmOp_return:
2120 case WasmOp_br:
2121 case WasmOp_br_table:
2122 if (unreachable_depth == 0) unreachable_depth = 1;
2123 break;
2124
2125 default:
2126 break;
2127 }
2128 }
2129}
2130
2131static void vm_push_u32(struct VirtualMachine *vm, uint32_t value) {
2132 vm->stack[vm->stack_top] = value;
2133 vm->stack_top += 1;
2134}
2135
2136static void vm_push_i32(struct VirtualMachine *vm, int32_t value) {
2137 return vm_push_u32(vm, value);
2138}
2139
2140static void vm_push_u64(struct VirtualMachine *vm, uint64_t value) {
2141 vm->stack[vm->stack_top] = value;
2142 vm->stack_top += 1;
2143}
2144
2145static void vm_push_i64(struct VirtualMachine *vm, int64_t value) {
2146 return vm_push_u64(vm, value);
2147}
2148
2149static void vm_push_f32(struct VirtualMachine *vm, float value) {
2150 uint32_t integer;
2151 memcpy(&integer, &value, 4);
2152 return vm_push_u32(vm, integer);
2153}
2154
2155static void vm_push_f64(struct VirtualMachine *vm, double value) {
2156 uint64_t integer;
2157 memcpy(&integer, &value, 8);
2158 return vm_push_u64(vm, integer);
2159}
2160
2161static uint32_t vm_pop_u32(struct VirtualMachine *vm) {
2162 vm->stack_top -= 1;
2163 return vm->stack[vm->stack_top];
2164}
2165
2166static int32_t vm_pop_i32(struct VirtualMachine *vm) {
2167 return vm_pop_u32(vm);
2168}
2169
2170static uint64_t vm_pop_u64(struct VirtualMachine *vm) {
2171 vm->stack_top -= 1;
2172 return vm->stack[vm->stack_top];
2173}
2174
2175static int64_t vm_pop_i64(struct VirtualMachine *vm) {
2176 return vm_pop_u64(vm);
2177}
2178
2179static float vm_pop_f32(struct VirtualMachine *vm) {
2180 uint32_t integer = vm_pop_u32(vm);
2181 float result;
2182 memcpy(&result, &integer, 4);
2183 return result;
2184}
2185
2186static double vm_pop_f64(struct VirtualMachine *vm) {
2187 uint32_t integer = vm_pop_u64(vm);
2188 double result;
2189 memcpy(&result, &integer, 8);
2190 return result;
2191}
2192
2193static void vm_callImport(struct VirtualMachine *vm, struct Import import) {
2194 switch (import.mod) {
2195 case ImpMod_wasi_snapshot_preview1: switch (import.name) {
2196 case ImpName_fd_prestat_get:
2197 {
2198 uint32_t buf = vm_pop_u32(vm);
2199 int32_t fd = vm_pop_i32(vm);
2200 vm_push_u32(vm, wasi_fd_prestat_get(vm, fd, buf));
2201 }
2202 break;
2203 case ImpName_fd_prestat_dir_name:
2204 {
2205 uint32_t path_len = vm_pop_u32(vm);
2206 uint32_t path = vm_pop_u32(vm);
2207 int32_t fd = vm_pop_i32(vm);
2208 vm_push_u32(vm, wasi_fd_prestat_dir_name(vm, fd, path, path_len));
2209 }
2210 break;
2211 case ImpName_fd_close:
2212 {
2213 int32_t fd = vm_pop_i32(vm);
2214 vm_push_u32(vm, wasi_fd_close(vm, fd));
2215 }
2216 break;
2217 case ImpName_fd_read:
2218 {
2219 uint32_t nread = vm_pop_u32(vm);
2220 uint32_t iovs_len = vm_pop_u32(vm);
2221 uint32_t iovs = vm_pop_u32(vm);
2222 int32_t fd = vm_pop_i32(vm);
2223 vm_push_u32(vm, wasi_fd_read(vm, fd, iovs, iovs_len, nread));
2224 }
2225 break;
2226 case ImpName_fd_filestat_get:
2227 {
2228 uint32_t buf = vm_pop_u32(vm);
2229 int32_t fd = vm_pop_i32(vm);
2230 vm_push_u32(vm, wasi_fd_filestat_get(vm, fd, buf));
2231 }
2232 break;
2233 case ImpName_fd_filestat_set_size:
2234 {
2235 uint64_t size = vm_pop_u64(vm);
2236 int32_t fd = vm_pop_i32(vm);
2237 vm_push_u32(vm, wasi_fd_filestat_set_size(vm, fd, size));
2238 }
2239 break;
2240 case ImpName_fd_filestat_set_times:
2241 {
2242 panic("unexpected call to fd_filestat_set_times");
2243 }
2244 break;
2245 case ImpName_fd_fdstat_get:
2246 {
2247 uint32_t buf = vm_pop_u32(vm);
2248 int32_t fd = vm_pop_i32(vm);
2249 vm_push_u32(vm, wasi_fd_fdstat_get(vm, fd, buf));
2250 }
2251 break;
2252 case ImpName_fd_readdir:
2253 {
2254 panic("TODO implement fd_readdir");
2255 }
2256 break;
2257 case ImpName_fd_write:
2258 {
2259 uint32_t nwritten = vm_pop_u32(vm);
2260 uint32_t iovs_len = vm_pop_u32(vm);
2261 uint32_t iovs = vm_pop_u32(vm);
2262 int32_t fd = vm_pop_i32(vm);
2263 vm_push_u32(vm, wasi_fd_write(vm, fd, iovs, iovs_len, nwritten));
2264 }
2265 break;
2266 case ImpName_fd_pwrite:
2267 {
2268 uint32_t nwritten = vm_pop_u32(vm);
2269 uint64_t offset = vm_pop_u64(vm);
2270 uint32_t iovs_len = vm_pop_u32(vm);
2271 uint32_t iovs = vm_pop_u32(vm);
2272 int32_t fd = vm_pop_i32(vm);
2273 vm_push_u32(vm, wasi_fd_pwrite(vm, fd, iovs, iovs_len, offset, nwritten));
2274 }
2275 break;
2276 case ImpName_proc_exit:
2277 {
2278 uint32_t code = vm_pop_u32(vm);
2279 exit(code);
2280 }
2281 break;
2282 case ImpName_args_sizes_get:
2283 {
2284 uint32_t argv_buf_size = vm_pop_u32(vm);
2285 uint32_t argc = vm_pop_u32(vm);
2286 vm_push_u32(vm, wasi_args_sizes_get(vm, argc, argv_buf_size));
2287 }
2288 break;
2289 case ImpName_args_get:
2290 {
2291 uint32_t argv_buf = vm_pop_u32(vm);
2292 uint32_t argv = vm_pop_u32(vm);
2293 vm_push_u32(vm, wasi_args_get(vm, argv, argv_buf));
2294 }
2295 break;
2296 case ImpName_random_get:
2297 {
2298 uint32_t buf_len = vm_pop_u32(vm);
2299 uint32_t buf = vm_pop_u32(vm);
2300 vm_push_u32(vm, wasi_random_get(vm, buf, buf_len));
2301 }
2302 break;
2303 case ImpName_environ_sizes_get:
2304 {
2305 panic("unexpected call to environ_sizes_get");
2306 }
2307 break;
2308 case ImpName_environ_get:
2309 {
2310 panic("unexpected call to environ_get");
2311 }
2312 break;
2313 case ImpName_path_filestat_get:
2314 {
2315 uint32_t buf = vm_pop_u32(vm);
2316 uint32_t path_len = vm_pop_u32(vm);
2317 uint32_t path = vm_pop_u32(vm);
2318 uint32_t flags = vm_pop_u32(vm);
2319 int32_t fd = vm_pop_i32(vm);
2320 vm_push_u32(vm, wasi_path_filestat_get(vm, fd, flags, path, path_len, buf));
2321 }
2322 break;
2323 case ImpName_path_create_directory:
2324 {
2325 uint32_t path_len = vm_pop_u32(vm);
2326 uint32_t path = vm_pop_u32(vm);
2327 int32_t fd = vm_pop_i32(vm);
2328 vm_push_u32(vm, wasi_path_create_directory(vm, fd, path, path_len));
2329 }
2330 break;
2331 case ImpName_path_rename:
2332 {
2333 uint32_t new_path_len = vm_pop_u32(vm);
2334 uint32_t new_path = vm_pop_u32(vm);
2335 int32_t new_fd = vm_pop_i32(vm);
2336 uint32_t old_path_len = vm_pop_u32(vm);
2337 uint32_t old_path = vm_pop_u32(vm);
2338 int32_t old_fd = vm_pop_i32(vm);
2339 vm_push_u32(vm, wasi_path_rename(
2340 vm,
2341 old_fd,
2342 old_path,
2343 old_path_len,
2344 new_fd,
2345 new_path,
2346 new_path_len
2347 ));
2348 }
2349 break;
2350 case ImpName_path_open:
2351 {
2352 uint32_t fd = vm_pop_u32(vm);
2353 uint32_t fs_flags = vm_pop_u32(vm);
2354 uint64_t fs_rights_inheriting = vm_pop_u64(vm);
2355 uint64_t fs_rights_base = vm_pop_u64(vm);
2356 uint32_t oflags = vm_pop_u32(vm);
2357 uint32_t path_len = vm_pop_u32(vm);
2358 uint32_t path = vm_pop_u32(vm);
2359 uint32_t dirflags = vm_pop_u32(vm);
2360 int32_t dirfd = vm_pop_i32(vm);
2361 vm_push_u32(vm, wasi_path_open(
2362 vm,
2363 dirfd,
2364 dirflags,
2365 path,
2366 path_len,
2367 oflags,
2368 fs_rights_base,
2369 fs_rights_inheriting,
2370 fs_flags,
2371 fd
2372 ));
2373 }
2374 break;
2375 case ImpName_path_remove_directory:
2376 {
2377 panic("unexpected call to path_remove_directory");
2378 }
2379 break;
2380 case ImpName_path_unlink_file:
2381 {
2382 panic("unexpected call to path_unlink_file");
2383 }
2384 break;
2385 case ImpName_clock_time_get:
2386 {
2387 uint32_t timestamp = vm_pop_u32(vm);
2388 uint64_t precision = vm_pop_u64(vm);
2389 uint32_t clock_id = vm_pop_u32(vm);
2390 vm_push_u32(vm, wasi_clock_time_get(vm, clock_id, precision, timestamp));
2391 }
2392 break;
2393 case ImpName_fd_pread:
2394 {
2395 panic("unexpected call to fd_pread");
2396 }
2397 break;
2398 case ImpName_debug:
2399 {
2400 uint64_t number = vm_pop_u64(vm);
2401 uint32_t text = vm_pop_u32(vm);
2402 wasi_debug(vm, text, number);
2403 }
2404 break;
2405 case ImpName_debug_slice:
2406 {
2407 uint32_t len = vm_pop_u32(vm);
2408 uint32_t ptr = vm_pop_u32(vm);
2409 wasi_debug_slice(vm, ptr, len);
2410 }
2411 break;
2412 }
2413 break;
2414 }
2415}
2416
2417static void vm_call(struct VirtualMachine *vm, uint32_t fn_id) {
2418 if (fn_id < vm->imports_len) {
2419 struct Import imp = vm->imports[fn_id];
2420 return vm_callImport(vm, imp);
2421 }
2422 uint32_t fn_idx = fn_id - vm->imports_len;
2423 struct Function *func = &vm->functions[fn_idx];
2424
2425 // Push zeroed locals to stack
2426 memset(&vm->stack[vm->stack_top], 0, func->locals_count * sizeof(uint64_t));
2427 vm->stack_top += func->locals_count;
2428
2429 vm_push_u32(vm, vm->pc.opcode);
2430 vm_push_u32(vm, vm->pc.operand);
2431
2432 vm->pc = func->entry_pc;
2433}
2434
2435static void vm_br_void(struct VirtualMachine *vm) {
2436 uint32_t stack_adjust = vm->operands[vm->pc.operand];
2437
2438 vm->stack_top -= stack_adjust;
2439
2440 vm->pc.opcode = vm->operands[vm->pc.operand + 1];
2441 vm->pc.operand = vm->operands[vm->pc.operand + 2];
2442}
2443
2444static void vm_br_u32(struct VirtualMachine *vm) {
2445 uint32_t stack_adjust = vm->operands[vm->pc.operand];
2446
2447 uint32_t result = vm_pop_u32(vm);
2448 vm->stack_top -= stack_adjust;
2449 vm_push_u32(vm, result);
2450
2451 vm->pc.opcode = vm->operands[vm->pc.operand + 1];
2452 vm->pc.operand = vm->operands[vm->pc.operand + 2];
2453}
2454
2455static void vm_br_u64(struct VirtualMachine *vm) {
2456 uint32_t stack_adjust = vm->operands[vm->pc.operand];
2457
2458 uint64_t result = vm_pop_u64(vm);
2459 vm->stack_top -= stack_adjust;
2460 vm_push_u64(vm, result);
2461
2462 vm->pc.opcode = vm->operands[vm->pc.operand + 1];
2463 vm->pc.operand = vm->operands[vm->pc.operand + 2];
2464}
2465
2466static void vm_return_void(struct VirtualMachine *vm) {
2467 uint32_t ret_pc_offset = vm->operands[vm->pc.operand + 0];
2468 uint32_t stack_adjust = vm->operands[vm->pc.operand + 1];
2469
2470 vm->pc.opcode = vm->stack[vm->stack_top - ret_pc_offset];
2471 vm->pc.operand = vm->stack[vm->stack_top - ret_pc_offset + 1];
2472
2473 vm->stack_top -= stack_adjust;
2474}
2475
2476static void vm_return_u32(struct VirtualMachine *vm) {
2477 uint32_t ret_pc_offset = vm->operands[vm->pc.operand + 0];
2478 uint32_t stack_adjust = vm->operands[vm->pc.operand + 1];
2479
2480 vm->pc.opcode = vm->stack[vm->stack_top - ret_pc_offset];
2481 vm->pc.operand = vm->stack[vm->stack_top - ret_pc_offset + 1];
2482
2483 uint32_t result = vm_pop_u32(vm);
2484 vm->stack_top -= stack_adjust;
2485 vm_push_u32(vm, result);
2486}
2487
2488static void vm_return_u64(struct VirtualMachine *vm) {
2489 uint32_t ret_pc_offset = vm->operands[vm->pc.operand + 0];
2490 uint32_t stack_adjust = vm->operands[vm->pc.operand + 1];
2491
2492 vm->pc.opcode = vm->stack[vm->stack_top - ret_pc_offset];
2493 vm->pc.operand = vm->stack[vm->stack_top - ret_pc_offset + 1];
2494
2495 uint64_t result = vm_pop_u64(vm);
2496 vm->stack_top -= stack_adjust;
2497 vm_push_u64(vm, result);
2498}
2499
2500static void vm_run(struct VirtualMachine *vm) {
2501 uint8_t *opcodes = vm->opcodes;
2502 uint32_t *operands = vm->operands;
2503 struct ProgramCounter *pc = &vm->pc;
2504 for (;;) {
2505 enum Op op = opcodes[pc->opcode];
2506 pc->opcode += 1;
2507 switch (op) {
2508 case Op_unreachable:
2509 panic("unreachable reached");
2510
2511 case Op_br_void:
2512 vm_br_void(vm);
2513 break;
2514
2515 case Op_br_32:
2516 vm_br_u32(vm);
2517 break;
2518
2519 case Op_br_64:
2520 vm_br_u64(vm);
2521 break;
2522
2523 case Op_br_if_nez_void:
2524 if (vm_pop_u32(vm) != 0) {
2525 vm_br_void(vm);
2526 } else {
2527 pc->operand += 3;
2528 }
2529 break;
2530
2531 case Op_br_if_nez_32:
2532 if (vm_pop_u32(vm) != 0) {
2533 vm_br_u32(vm);
2534 } else {
2535 pc->operand += 3;
2536 }
2537 break;
2538
2539 case Op_br_if_nez_64:
2540 if (vm_pop_u32(vm) != 0) {
2541 vm_br_u64(vm);
2542 } else {
2543 pc->operand += 3;
2544 }
2545 break;
2546
2547 case Op_br_if_eqz_void:
2548 if (vm_pop_u32(vm) == 0) {
2549 vm_br_void(vm);
2550 } else {
2551 pc->operand += 3;
2552 }
2553 break;
2554
2555 case Op_br_if_eqz_32:
2556 if (vm_pop_u32(vm) == 0) {
2557 vm_br_u32(vm);
2558 } else {
2559 pc->operand += 3;
2560 }
2561 break;
2562
2563 case Op_br_if_eqz_64:
2564 if (vm_pop_u32(vm) == 0) {
2565 vm_br_u64(vm);
2566 } else {
2567 pc->operand += 3;
2568 }
2569 break;
2570
2571 case Op_br_table_void:
2572 {
2573 uint32_t index = min_u32(vm_pop_u32(vm), operands[pc->operand]);
2574 pc->operand += 1 + index * 3;
2575 vm_br_void(vm);
2576 }
2577 break;
2578
2579 case Op_br_table_32:
2580 {
2581 uint32_t index = min_u32(vm_pop_u32(vm), operands[pc->operand]);
2582 pc->operand += 1 + index * 3;
2583 vm_br_u32(vm);
2584 }
2585 break;
2586
2587 case Op_br_table_64:
2588 {
2589 uint32_t index = min_u32(vm_pop_u32(vm), operands[pc->operand]);
2590 pc->operand += 1 + index * 3;
2591 vm_br_u64(vm);
2592 }
2593 break;
2594
2595 case Op_return_void:
2596 vm_return_void(vm);
2597 break;
2598
2599 case Op_return_32:
2600 vm_return_u32(vm);
2601 break;
2602
2603 case Op_return_64:
2604 vm_return_u64(vm);
2605 break;
2606
2607 case Op_call:
2608 {
2609 uint32_t fn_id = operands[pc->operand];
2610 pc->operand += 1;
2611 vm_call(vm, fn_id);
2612 }
2613 break;
2614
2615 case Op_drop_32:
2616 case Op_drop_64:
2617 vm->stack_top -= 1;
2618 break;
2619
2620 case Op_select_32:
2621 {
2622 uint32_t c = vm_pop_u32(vm);
2623 uint32_t b = vm_pop_u32(vm);
2624 uint32_t a = vm_pop_u32(vm);
2625 uint32_t result = (c != 0) ? a : b;
2626 vm_push_u32(vm, result);
2627 }
2628 break;
2629
2630 case Op_select_64:
2631 {
2632 uint32_t c = vm_pop_u32(vm);
2633 uint64_t b = vm_pop_u64(vm);
2634 uint64_t a = vm_pop_u64(vm);
2635 uint64_t result = (c != 0) ? a : b;
2636 vm_push_u64(vm, result);
2637 }
2638 break;
2639
2640 case Op_local_get_32:
2641 {
2642 uint64_t *local = &vm->stack[vm->stack_top - operands[pc->operand]];
2643 pc->operand += 1;
2644 vm_push_u32(vm, *local);
2645 }
2646 break;
2647
2648 case Op_local_get_64:
2649 {
2650 uint64_t *local = &vm->stack[vm->stack_top - operands[pc->operand]];
2651 pc->operand += 1;
2652 vm_push_u64(vm, *local);
2653 }
2654 break;
2655
2656 case Op_local_set_32:
2657 {
2658 uint64_t *local = &vm->stack[vm->stack_top - operands[pc->operand]];
2659 pc->operand += 1;
2660 *local = vm_pop_u32(vm);
2661 }
2662 break;
2663
2664 case Op_local_set_64:
2665 {
2666 uint64_t *local = &vm->stack[vm->stack_top - operands[pc->operand]];
2667 pc->operand += 1;
2668 *local = vm_pop_u64(vm);
2669 }
2670 break;
2671
2672 case Op_local_tee_32:
2673 case Op_local_tee_64:
2674 {
2675 uint64_t *local = &vm->stack[vm->stack_top - operands[pc->operand]];
2676 pc->operand += 1;
2677 *local = vm->stack[vm->stack_top - 1];
2678 }
2679 break;
2680
2681 case Op_global_get_0_32:
2682 vm_push_u32(vm, vm->globals[0]);
2683 break;
2684
2685 case Op_global_get_32:
2686 {
2687 uint32_t idx = operands[pc->operand];
2688 pc->operand += 1;
2689 vm_push_u32(vm, vm->globals[idx]);
2690 }
2691 break;
2692
2693 case Op_global_set_0_32:
2694 vm->globals[0] = vm_pop_u32(vm);
2695 break;
2696
2697 case Op_global_set_32:
2698 {
2699 uint32_t idx = operands[pc->operand];
2700 pc->operand += 1;
2701 vm->globals[idx] = vm_pop_u32(vm);
2702 }
2703 break;
2704
2705 case Op_const_32:
2706 {
2707 uint32_t x = operands[pc->operand];
2708 pc->operand += 1;
2709 vm_push_i32(vm, x);
2710 }
2711 break;
2712
2713 case Op_const_64:
2714 {
2715 uint64_t x = ((uint64_t)operands[pc->operand]) |
2716 (((uint64_t)operands[pc->operand + 1]) << 32);
2717 pc->operand += 2;
2718 vm_push_i64(vm, x);
2719 }
2720 break;
2721
2722 case Op_add_32:
2723 {
2724 uint32_t rhs = vm_pop_u32(vm);
2725 uint32_t lhs = vm_pop_u32(vm);
2726 vm_push_u32(vm, lhs + rhs);
2727 }
2728 break;
2729
2730 case Op_and_32:
2731 {
2732 uint32_t rhs = vm_pop_u32(vm);
2733 uint32_t lhs = vm_pop_u32(vm);
2734 vm_push_u32(vm, lhs & rhs);
2735 }
2736 break;
2737
2738 case Op_wasm:
2739 {
2740 enum WasmOp wasm_op = opcodes[pc->opcode];
2741 pc->opcode += 1;
2742 switch (wasm_op) {
2743 case WasmOp_unreachable:
2744 case WasmOp_nop:
2745 case WasmOp_block:
2746 case WasmOp_loop:
2747 case WasmOp_if:
2748 case WasmOp_else:
2749 case WasmOp_end:
2750 case WasmOp_br:
2751 case WasmOp_br_if:
2752 case WasmOp_br_table:
2753 case WasmOp_return:
2754 case WasmOp_call:
2755 case WasmOp_drop:
2756 case WasmOp_select:
2757 case WasmOp_local_get:
2758 case WasmOp_local_set:
2759 case WasmOp_local_tee:
2760 case WasmOp_global_get:
2761 case WasmOp_global_set:
2762 case WasmOp_i32_const:
2763 case WasmOp_i64_const:
2764 case WasmOp_f32_const:
2765 case WasmOp_f64_const:
2766 case WasmOp_i32_add:
2767 case WasmOp_i32_and:
2768 case WasmOp_i32_reinterpret_f32:
2769 case WasmOp_i64_reinterpret_f64:
2770 case WasmOp_f32_reinterpret_i32:
2771 case WasmOp_f64_reinterpret_i64:
2772 case WasmOp_prefixed:
2773 panic("not produced by decodeCode");
2774 break;
2775
2776 case WasmOp_call_indirect:
2777 {
2778 uint32_t fn_id = vm->table[vm_pop_u32(vm)];
2779 vm_call(vm, fn_id);
2780 }
2781 break;
2782 case WasmOp_i32_load:
2783 {
2784 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2785 pc->operand += 1;
2786 vm_push_u32(vm, read_u32_le(vm->memory + offset));
2787 }
2788 break;
2789 case WasmOp_i64_load:
2790 {
2791 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2792 pc->operand += 1;
2793 vm_push_u64(vm, read_u64_le(vm->memory + offset));
2794 }
2795 break;
2796 case WasmOp_f32_load:
2797 {
2798 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2799 pc->operand += 1;
2800 uint32_t integer = read_u32_le(vm->memory + offset);
2801 vm_push_u32(vm, integer);
2802 }
2803 break;
2804 case WasmOp_f64_load:
2805 {
2806 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2807 pc->operand += 1;
2808 uint64_t integer = read_u64_le(vm->memory + offset);
2809 vm_push_u64(vm, integer);
2810 }
2811 break;
2812 case WasmOp_i32_load8_s:
2813 {
2814 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2815 pc->operand += 1;
2816 vm_push_i32(vm, (int8_t)vm->memory[offset]);
2817 }
2818 break;
2819 case WasmOp_i32_load8_u:
2820 {
2821 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2822 pc->operand += 1;
2823 vm_push_u32(vm, vm->memory[offset]);
2824 }
2825 break;
2826 case WasmOp_i32_load16_s:
2827 {
2828 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2829 pc->operand += 1;
2830 int16_t integer = read_i16_le(vm->memory + offset);
2831 vm_push_i32(vm, integer);
2832 }
2833 break;
2834 case WasmOp_i32_load16_u:
2835 {
2836 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2837 pc->operand += 1;
2838 uint16_t integer = read_u16_le(vm->memory + offset);
2839 vm_push_u32(vm, integer);
2840 }
2841 break;
2842 case WasmOp_i64_load8_s:
2843 {
2844 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2845 pc->operand += 1;
2846 vm_push_i64(vm, (int8_t)vm->memory[offset]);
2847 }
2848 break;
2849 case WasmOp_i64_load8_u:
2850 {
2851 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2852 pc->operand += 1;
2853 vm_push_u64(vm, vm->memory[offset]);
2854 }
2855 break;
2856 case WasmOp_i64_load16_s:
2857 {
2858 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2859 pc->operand += 1;
2860 int16_t integer = read_i16_le(vm->memory + offset);
2861 vm_push_i64(vm, integer);
2862 }
2863 break;
2864 case WasmOp_i64_load16_u:
2865 {
2866 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2867 pc->operand += 1;
2868 uint16_t integer = read_u16_le(vm->memory + offset);
2869 vm_push_u64(vm, integer);
2870 }
2871 break;
2872 case WasmOp_i64_load32_s:
2873 {
2874 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2875 pc->operand += 1;
2876 int32_t integer = read_i32_le(vm->memory + offset);
2877 vm_push_i64(vm, integer);
2878 }
2879 break;
2880 case WasmOp_i64_load32_u:
2881 {
2882 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2883 pc->operand += 1;
2884 uint32_t integer = read_u32_le(vm->memory + offset);
2885 vm_push_u64(vm, integer);
2886 }
2887 break;
2888 case WasmOp_i32_store:
2889 {
2890 uint32_t operand = vm_pop_u32(vm);
2891 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2892 pc->operand += 1;
2893 write_u32_le(vm->memory + offset, operand);
2894 }
2895 break;
2896 case WasmOp_i64_store:
2897 {
2898 uint64_t operand = vm_pop_u64(vm);
2899 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2900 pc->operand += 1;
2901 write_u64_le(vm->memory + offset, operand);
2902 }
2903 break;
2904 case WasmOp_f32_store:
2905 {
2906 uint32_t integer = vm_pop_u32(vm);
2907 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2908 pc->operand += 1;
2909 write_u32_le(vm->memory + offset, integer);
2910 }
2911 break;
2912 case WasmOp_f64_store:
2913 {
2914 uint64_t integer = vm_pop_u64(vm);
2915 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2916 pc->operand += 1;
2917 write_u64_le(vm->memory + offset, integer);
2918 }
2919 break;
2920 case WasmOp_i32_store8:
2921 {
2922 uint8_t small = vm_pop_u32(vm);
2923 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2924 pc->operand += 1;
2925 vm->memory[offset] = small;
2926 }
2927 break;
2928 case WasmOp_i32_store16:
2929 {
2930 uint16_t small = vm_pop_u32(vm);
2931 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2932 pc->operand += 1;
2933 write_u16_le(vm->memory + offset, small);
2934 }
2935 break;
2936 case WasmOp_i64_store8:
2937 {
2938 uint8_t operand = vm_pop_u64(vm);
2939 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2940 pc->operand += 1;
2941 vm->memory[offset] = operand;
2942 }
2943 break;
2944 case WasmOp_i64_store16:
2945 {
2946 uint16_t small = vm_pop_u64(vm);
2947 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2948 pc->operand += 1;
2949 write_u16_le(vm->memory + offset, small);
2950 }
2951 break;
2952 case WasmOp_i64_store32:
2953 {
2954 uint32_t small = vm_pop_u64(vm);
2955 uint32_t offset = operands[pc->operand] + vm_pop_u32(vm);
2956 pc->operand += 1;
2957 write_u32_le(vm->memory + offset, small);
2958 }
2959 break;
2960 case WasmOp_memory_size:
2961 {
2962 uint32_t page_count = vm->memory_len / wasm_page_size;
2963 vm_push_u32(vm, page_count);
2964 }
2965 break;
2966 case WasmOp_memory_grow:
2967 {
2968 uint32_t page_count = vm_pop_u32(vm);
2969 uint32_t old_page_count = vm->memory_len / wasm_page_size;
2970 uint32_t new_len = vm->memory_len + page_count * wasm_page_size;
2971 if (new_len > vm->memory_len) {
2972 vm_push_i32(vm, -1);
2973 } else {
2974 vm->memory_len = new_len;
2975 vm_push_u32(vm, old_page_count);
2976 }
2977 }
2978 break;
2979 case WasmOp_i32_eqz:
2980 {
2981 uint32_t lhs = vm_pop_u32(vm);
2982 vm_push_u32(vm, lhs == 0);
2983 }
2984 break;
2985 case WasmOp_i32_eq:
2986 {
2987 uint32_t rhs = vm_pop_u32(vm);
2988 uint32_t lhs = vm_pop_u32(vm);
2989 vm_push_u32(vm, lhs == rhs);
2990 }
2991 break;
2992 case WasmOp_i32_ne:
2993 {
2994 uint32_t rhs = vm_pop_u32(vm);
2995 uint32_t lhs = vm_pop_u32(vm);
2996 vm_push_u32(vm, lhs != rhs);
2997 }
2998 break;
2999 case WasmOp_i32_lt_s:
3000 {
3001 int32_t rhs = vm_pop_i32(vm);
3002 int32_t lhs = vm_pop_i32(vm);
3003 vm_push_u32(vm, lhs < rhs);
3004 }
3005 break;
3006 case WasmOp_i32_lt_u:
3007 {
3008 uint32_t rhs = vm_pop_u32(vm);
3009 uint32_t lhs = vm_pop_u32(vm);
3010 vm_push_u32(vm, lhs < rhs);
3011 }
3012 break;
3013 case WasmOp_i32_gt_s:
3014 {
3015 int32_t rhs = vm_pop_i32(vm);
3016 int32_t lhs = vm_pop_i32(vm);
3017 vm_push_u32(vm, lhs > rhs);
3018 }
3019 break;
3020 case WasmOp_i32_gt_u:
3021 {
3022 uint32_t rhs = vm_pop_u32(vm);
3023 uint32_t lhs = vm_pop_u32(vm);
3024 vm_push_u32(vm, lhs > rhs);
3025 }
3026 break;
3027 case WasmOp_i32_le_s:
3028 {
3029 int32_t rhs = vm_pop_i32(vm);
3030 int32_t lhs = vm_pop_i32(vm);
3031 vm_push_u32(vm, lhs <= rhs);
3032 }
3033 break;
3034 case WasmOp_i32_le_u:
3035 {
3036 uint32_t rhs = vm_pop_u32(vm);
3037 uint32_t lhs = vm_pop_u32(vm);
3038 vm_push_u32(vm, lhs <= rhs);
3039 }
3040 break;
3041 case WasmOp_i32_ge_s:
3042 {
3043 int32_t rhs = vm_pop_i32(vm);
3044 int32_t lhs = vm_pop_i32(vm);
3045 vm_push_u32(vm, lhs >= rhs);
3046 }
3047 break;
3048 case WasmOp_i32_ge_u:
3049 {
3050 uint32_t rhs = vm_pop_u32(vm);
3051 uint32_t lhs = vm_pop_u32(vm);
3052 vm_push_u32(vm, lhs >= rhs);
3053 }
3054 break;
3055 case WasmOp_i64_eqz:
3056 {
3057 uint64_t lhs = vm_pop_u64(vm);
3058 vm_push_u32(vm, lhs == 0);
3059 }
3060 break;
3061 case WasmOp_i64_eq:
3062 {
3063 uint64_t rhs = vm_pop_u64(vm);
3064 uint64_t lhs = vm_pop_u64(vm);
3065 vm_push_u32(vm, lhs == rhs);
3066 }
3067 break;
3068 case WasmOp_i64_ne:
3069 {
3070 uint64_t rhs = vm_pop_u64(vm);
3071 uint64_t lhs = vm_pop_u64(vm);
3072 vm_push_u32(vm, lhs != rhs);
3073 }
3074 break;
3075 case WasmOp_i64_lt_s:
3076 {
3077 int64_t rhs = vm_pop_i64(vm);
3078 int64_t lhs = vm_pop_i64(vm);
3079 vm_push_u32(vm, lhs < rhs);
3080 }
3081 break;
3082 case WasmOp_i64_lt_u:
3083 {
3084 uint64_t rhs = vm_pop_u64(vm);
3085 uint64_t lhs = vm_pop_u64(vm);
3086 vm_push_u32(vm, lhs < rhs);
3087 }
3088 break;
3089 case WasmOp_i64_gt_s:
3090 {
3091 int64_t rhs = vm_pop_i64(vm);
3092 int64_t lhs = vm_pop_i64(vm);
3093 vm_push_u32(vm, lhs > rhs);
3094 }
3095 break;
3096 case WasmOp_i64_gt_u:
3097 {
3098 uint64_t rhs = vm_pop_u64(vm);
3099 uint64_t lhs = vm_pop_u64(vm);
3100 vm_push_u32(vm, lhs > rhs);
3101 }
3102 break;
3103 case WasmOp_i64_le_s:
3104 {
3105 int64_t rhs = vm_pop_i64(vm);
3106 int64_t lhs = vm_pop_i64(vm);
3107 vm_push_u32(vm, lhs <= rhs);
3108 }
3109 break;
3110 case WasmOp_i64_le_u:
3111 {
3112 uint64_t rhs = vm_pop_u64(vm);
3113 uint64_t lhs = vm_pop_u64(vm);
3114 vm_push_u32(vm, lhs <= rhs);
3115 }
3116 break;
3117 case WasmOp_i64_ge_s:
3118 {
3119 int64_t rhs = vm_pop_i64(vm);
3120 int64_t lhs = vm_pop_i64(vm);
3121 vm_push_u32(vm, lhs >= rhs);
3122 }
3123 break;
3124 case WasmOp_i64_ge_u:
3125 {
3126 uint64_t rhs = vm_pop_u64(vm);
3127 uint64_t lhs = vm_pop_u64(vm);
3128 vm_push_u32(vm, lhs >= rhs);
3129 }
3130 break;
3131 case WasmOp_f32_eq:
3132 {
3133 float rhs = vm_pop_f32(vm);
3134 float lhs = vm_pop_f32(vm);
3135 vm_push_u32(vm, lhs == rhs);
3136 }
3137 break;
3138 case WasmOp_f32_ne:
3139 {
3140 float rhs = vm_pop_f32(vm);
3141 float lhs = vm_pop_f32(vm);
3142 vm_push_u32(vm, lhs != rhs);
3143 }
3144 break;
3145 case WasmOp_f32_lt:
3146 {
3147 float rhs = vm_pop_f32(vm);
3148 float lhs = vm_pop_f32(vm);
3149 vm_push_u32(vm, lhs < rhs);
3150 }
3151 break;
3152 case WasmOp_f32_gt:
3153 {
3154 float rhs = vm_pop_f32(vm);
3155 float lhs = vm_pop_f32(vm);
3156 vm_push_u32(vm, lhs > rhs);
3157 }
3158 break;
3159 case WasmOp_f32_le:
3160 {
3161 float rhs = vm_pop_f32(vm);
3162 float lhs = vm_pop_f32(vm);
3163 vm_push_u32(vm, lhs <= rhs);
3164 }
3165 break;
3166 case WasmOp_f32_ge:
3167 {
3168 float rhs = vm_pop_f32(vm);
3169 float lhs = vm_pop_f32(vm);
3170 vm_push_u32(vm, lhs >= rhs);
3171 }
3172 break;
3173 case WasmOp_f64_eq:
3174 {
3175 double rhs = vm_pop_f64(vm);
3176 double lhs = vm_pop_f64(vm);
3177 vm_push_u32(vm, lhs == rhs);
3178 }
3179 break;
3180 case WasmOp_f64_ne:
3181 {
3182 double rhs = vm_pop_f64(vm);
3183 double lhs = vm_pop_f64(vm);
3184 vm_push_u32(vm, lhs != rhs);
3185 }
3186 break;
3187 case WasmOp_f64_lt:
3188 {
3189 double rhs = vm_pop_f64(vm);
3190 double lhs = vm_pop_f64(vm);
3191 vm_push_u32(vm, lhs <= rhs);
3192 }
3193 break;
3194 case WasmOp_f64_gt:
3195 {
3196 double rhs = vm_pop_f64(vm);
3197 double lhs = vm_pop_f64(vm);
3198 vm_push_u32(vm, lhs > rhs);
3199 }
3200 break;
3201 case WasmOp_f64_le:
3202 {
3203 double rhs = vm_pop_f64(vm);
3204 double lhs = vm_pop_f64(vm);
3205 vm_push_u32(vm, lhs <= rhs);
3206 }
3207 break;
3208 case WasmOp_f64_ge:
3209 {
3210 double rhs = vm_pop_f64(vm);
3211 double lhs = vm_pop_f64(vm);
3212 vm_push_u32(vm, lhs >= rhs);
3213 }
3214 break;
3215
3216 case WasmOp_i32_clz:
3217 {
3218 uint32_t operand = vm_pop_u32(vm);
3219 uint32_t result = (operand == 0) ? 32 : __builtin_clz(operand);
3220 vm_push_u32(vm, result);
3221 }
3222 break;
3223 case WasmOp_i32_ctz:
3224 {
3225 uint32_t operand = vm_pop_u32(vm);
3226 uint32_t result = (operand == 0) ? 32 : __builtin_ctz(operand);
3227 vm_push_u32(vm, result);
3228 }
3229 break;
3230 case WasmOp_i32_popcnt:
3231 {
3232 uint32_t operand = vm_pop_u32(vm);
3233 uint32_t result = __builtin_popcount(operand);
3234 vm_push_u32(vm, result);
3235 }
3236 break;
3237 case WasmOp_i32_sub:
3238 {
3239 uint32_t rhs = vm_pop_u32(vm);
3240 uint32_t lhs = vm_pop_u32(vm);
3241 vm_push_u32(vm, lhs - rhs);
3242 }
3243 break;
3244 case WasmOp_i32_mul:
3245 {
3246 uint32_t rhs = vm_pop_u32(vm);
3247 uint32_t lhs = vm_pop_u32(vm);
3248 vm_push_u32(vm, lhs * rhs);
3249 }
3250 break;
3251 case WasmOp_i32_div_s:
3252 {
3253 int32_t rhs = vm_pop_i32(vm);
3254 int32_t lhs = vm_pop_i32(vm);
3255 vm_push_i32(vm, lhs / rhs);
3256 }
3257 break;
3258 case WasmOp_i32_div_u:
3259 {
3260 uint32_t rhs = vm_pop_u32(vm);
3261 uint32_t lhs = vm_pop_u32(vm);
3262 vm_push_u32(vm, lhs / rhs);
3263 }
3264 break;
3265 case WasmOp_i32_rem_s:
3266 {
3267 int32_t rhs = vm_pop_i32(vm);
3268 int32_t lhs = vm_pop_i32(vm);
3269 vm_push_i32(vm, lhs % rhs);
3270 }
3271 break;
3272 case WasmOp_i32_rem_u:
3273 {
3274 uint32_t rhs = vm_pop_u32(vm);
3275 uint32_t lhs = vm_pop_u32(vm);
3276 vm_push_u32(vm, lhs % rhs);
3277 }
3278 break;
3279 case WasmOp_i32_or:
3280 {
3281 uint32_t rhs = vm_pop_u32(vm);
3282 uint32_t lhs = vm_pop_u32(vm);
3283 vm_push_u32(vm, lhs | rhs);
3284 }
3285 break;
3286 case WasmOp_i32_xor:
3287 {
3288 uint32_t rhs = vm_pop_u32(vm);
3289 uint32_t lhs = vm_pop_u32(vm);
3290 vm_push_u32(vm, lhs ^ rhs);
3291 }
3292 break;
3293 case WasmOp_i32_shl:
3294 {
3295 uint32_t rhs = vm_pop_u32(vm);
3296 uint32_t lhs = vm_pop_u32(vm);
3297 vm_push_u32(vm, lhs << rhs);
3298 }
3299 break;
3300 case WasmOp_i32_shr_s:
3301 {
3302 uint32_t rhs = vm_pop_u32(vm);
3303 int32_t lhs = vm_pop_i32(vm);
3304 vm_push_i32(vm, lhs >> rhs);
3305 }
3306 break;
3307 case WasmOp_i32_shr_u:
3308 {
3309 uint32_t rhs = vm_pop_u32(vm);
3310 uint32_t lhs = vm_pop_u32(vm);
3311 vm_push_u32(vm, lhs >> rhs);
3312 }
3313 break;
3314 case WasmOp_i32_rotl:
3315 {
3316 uint32_t rhs = vm_pop_u32(vm);
3317 uint32_t lhs = vm_pop_u32(vm);
3318 vm_push_u32(vm, rotl32(lhs, rhs));
3319 }
3320 break;
3321 case WasmOp_i32_rotr:
3322 {
3323 uint32_t rhs = vm_pop_u32(vm);
3324 uint32_t lhs = vm_pop_u32(vm);
3325 vm_push_u32(vm, rotr32(lhs, rhs ));
3326 }
3327 break;
3328
3329 case WasmOp_i64_clz:
3330 {
3331 uint64_t operand = vm_pop_u64(vm);
3332 uint64_t result = (operand == 0) ? 64 : __builtin_clzll(operand);
3333 vm_push_u64(vm, result);
3334 }
3335 break;
3336 case WasmOp_i64_ctz:
3337 {
3338 uint64_t operand = vm_pop_u64(vm);
3339 uint64_t result = (operand == 0) ? 64 : __builtin_ctzll(operand);
3340 vm_push_u64(vm, result);
3341 }
3342 break;
3343 case WasmOp_i64_popcnt:
3344 {
3345 uint64_t operand = vm_pop_u64(vm);
3346 uint64_t result = __builtin_popcountll(operand);
3347 vm_push_u64(vm, result);
3348 }
3349 break;
3350 case WasmOp_i64_add:
3351 {
3352 uint64_t rhs = vm_pop_u64(vm);
3353 uint64_t lhs = vm_pop_u64(vm);
3354 vm_push_u64(vm, lhs + rhs);
3355 }
3356 break;
3357 case WasmOp_i64_sub:
3358 {
3359 uint64_t rhs = vm_pop_u64(vm);
3360 uint64_t lhs = vm_pop_u64(vm);
3361 vm_push_u64(vm, lhs - rhs);
3362 }
3363 break;
3364 case WasmOp_i64_mul:
3365 {
3366 uint64_t rhs = vm_pop_u64(vm);
3367 uint64_t lhs = vm_pop_u64(vm);
3368 vm_push_u64(vm, lhs * rhs);
3369 }
3370 break;
3371 case WasmOp_i64_div_s:
3372 {
3373 int64_t rhs = vm_pop_i64(vm);
3374 int64_t lhs = vm_pop_i64(vm);
3375 vm_push_i64(vm, lhs / rhs);
3376 }
3377 break;
3378 case WasmOp_i64_div_u:
3379 {
3380 uint64_t rhs = vm_pop_u64(vm);
3381 uint64_t lhs = vm_pop_u64(vm);
3382 vm_push_u64(vm, lhs / rhs);
3383 }
3384 break;
3385 case WasmOp_i64_rem_s:
3386 {
3387 int64_t rhs = vm_pop_i64(vm);
3388 int64_t lhs = vm_pop_i64(vm);
3389 vm_push_i64(vm, lhs % rhs);
3390 }
3391 break;
3392 case WasmOp_i64_rem_u:
3393 {
3394 uint64_t rhs = vm_pop_u64(vm);
3395 uint64_t lhs = vm_pop_u64(vm);
3396 vm_push_u64(vm, lhs % rhs);
3397 }
3398 break;
3399 case WasmOp_i64_and:
3400 {
3401 uint64_t rhs = vm_pop_u64(vm);
3402 uint64_t lhs = vm_pop_u64(vm);
3403 vm_push_u64(vm, lhs & rhs);
3404 }
3405 break;
3406 case WasmOp_i64_or:
3407 {
3408 uint64_t rhs = vm_pop_u64(vm);
3409 uint64_t lhs = vm_pop_u64(vm);
3410 vm_push_u64(vm, lhs | rhs);
3411 }
3412 break;
3413 case WasmOp_i64_xor:
3414 {
3415 uint64_t rhs = vm_pop_u64(vm);
3416 uint64_t lhs = vm_pop_u64(vm);
3417 vm_push_u64(vm, lhs ^ rhs);
3418 }
3419 break;
3420 case WasmOp_i64_shl:
3421 {
3422 uint64_t rhs = vm_pop_u64(vm);
3423 uint64_t lhs = vm_pop_u64(vm);
3424 vm_push_u64(vm, lhs << rhs);
3425 }
3426 break;
3427 case WasmOp_i64_shr_s:
3428 {
3429 uint64_t rhs = vm_pop_u64(vm);
3430 int64_t lhs = vm_pop_i64(vm);
3431 vm_push_i64(vm, lhs >> rhs);
3432 }
3433 break;
3434 case WasmOp_i64_shr_u:
3435 {
3436 uint64_t rhs = vm_pop_u64(vm);
3437 uint64_t lhs = vm_pop_u64(vm);
3438 vm_push_u64(vm, lhs >> rhs);
3439 }
3440 break;
3441 case WasmOp_i64_rotl:
3442 {
3443 uint64_t rhs = vm_pop_u64(vm);
3444 uint64_t lhs = vm_pop_u64(vm);
3445 vm_push_u64(vm, rotl64(lhs, rhs ));
3446 }
3447 break;
3448 case WasmOp_i64_rotr:
3449 {
3450 uint64_t rhs = vm_pop_u64(vm);
3451 uint64_t lhs = vm_pop_u64(vm);
3452 vm_push_u64(vm, rotr64(lhs, rhs ));
3453 }
3454 break;
3455
3456 case WasmOp_f32_abs:
3457 {
3458 vm_push_f32(vm, fabsf(vm_pop_f32(vm)));
3459 }
3460 break;
3461 case WasmOp_f32_neg:
3462 {
3463 vm_push_f32(vm, -vm_pop_f32(vm));
3464 }
3465 break;
3466 case WasmOp_f32_ceil:
3467 {
3468 vm_push_f32(vm, ceilf(vm_pop_f32(vm)));
3469 }
3470 break;
3471 case WasmOp_f32_floor:
3472 {
3473 vm_push_f32(vm, floorf(vm_pop_f32(vm)));
3474 }
3475 break;
3476 case WasmOp_f32_trunc:
3477 {
3478 vm_push_f32(vm, truncf(vm_pop_f32(vm)));
3479 }
3480 break;
3481 case WasmOp_f32_nearest:
3482 {
3483 vm_push_f32(vm, roundf(vm_pop_f32(vm)));
3484 }
3485 break;
3486 case WasmOp_f32_sqrt:
3487 {
3488 vm_push_f32(vm, sqrtf(vm_pop_f32(vm)));
3489 }
3490 break;
3491 case WasmOp_f32_add:
3492 {
3493 float rhs = vm_pop_f32(vm);
3494 float lhs = vm_pop_f32(vm);
3495 vm_push_f32(vm, lhs + rhs);
3496 }
3497 break;
3498 case WasmOp_f32_sub:
3499 {
3500 float rhs = vm_pop_f32(vm);
3501 float lhs = vm_pop_f32(vm);
3502 vm_push_f32(vm, lhs - rhs);
3503 }
3504 break;
3505 case WasmOp_f32_mul:
3506 {
3507 float rhs = vm_pop_f32(vm);
3508 float lhs = vm_pop_f32(vm);
3509 vm_push_f32(vm, lhs * rhs);
3510 }
3511 break;
3512 case WasmOp_f32_div:
3513 {
3514 float rhs = vm_pop_f32(vm);
3515 float lhs = vm_pop_f32(vm);
3516 vm_push_f32(vm, lhs / rhs);
3517 }
3518 break;
3519 case WasmOp_f32_min:
3520 {
3521 float rhs = vm_pop_f32(vm);
3522 float lhs = vm_pop_f32(vm);
3523 vm_push_f32(vm, (lhs < rhs) ? lhs : rhs);
3524 }
3525 break;
3526 case WasmOp_f32_max:
3527 {
3528 float rhs = vm_pop_f32(vm);
3529 float lhs = vm_pop_f32(vm);
3530 vm_push_f32(vm, (lhs > rhs) ? lhs : rhs);
3531 }
3532 break;
3533 case WasmOp_f32_copysign:
3534 {
3535 float rhs = vm_pop_f32(vm);
3536 float lhs = vm_pop_f32(vm);
3537 vm_push_f32(vm, copysignf(lhs, rhs));
3538 }
3539 break;
3540 case WasmOp_f64_abs:
3541 {
3542 vm_push_f64(vm, fabs(vm_pop_f64(vm)));
3543 }
3544 break;
3545 case WasmOp_f64_neg:
3546 {
3547 vm_push_f64(vm, -vm_pop_f64(vm));
3548 }
3549 break;
3550 case WasmOp_f64_ceil:
3551 {
3552 vm_push_f64(vm, ceil(vm_pop_f64(vm)));
3553 }
3554 break;
3555 case WasmOp_f64_floor:
3556 {
3557 vm_push_f64(vm, floor(vm_pop_f64(vm)));
3558 }
3559 break;
3560 case WasmOp_f64_trunc:
3561 {
3562 vm_push_f64(vm, trunc(vm_pop_f64(vm)));
3563 }
3564 break;
3565 case WasmOp_f64_nearest:
3566 {
3567 vm_push_f64(vm, round(vm_pop_f64(vm)));
3568 }
3569 break;
3570 case WasmOp_f64_sqrt:
3571 {
3572 vm_push_f64(vm, sqrt(vm_pop_f64(vm)));
3573 }
3574 break;
3575 case WasmOp_f64_add:
3576 {
3577 double rhs = vm_pop_f64(vm);
3578 double lhs = vm_pop_f64(vm);
3579 vm_push_f64(vm, lhs + rhs);
3580 }
3581 break;
3582 case WasmOp_f64_sub:
3583 {
3584 double rhs = vm_pop_f64(vm);
3585 double lhs = vm_pop_f64(vm);
3586 vm_push_f64(vm, lhs - rhs);
3587 }
3588 break;
3589 case WasmOp_f64_mul:
3590 {
3591 double rhs = vm_pop_f64(vm);
3592 double lhs = vm_pop_f64(vm);
3593 vm_push_f64(vm, lhs * rhs);
3594 }
3595 break;
3596 case WasmOp_f64_div:
3597 {
3598 double rhs = vm_pop_f64(vm);
3599 double lhs = vm_pop_f64(vm);
3600 vm_push_f64(vm, lhs / rhs);
3601 }
3602 break;
3603 case WasmOp_f64_min:
3604 {
3605 double rhs = vm_pop_f64(vm);
3606 double lhs = vm_pop_f64(vm);
3607 vm_push_f64(vm, (lhs < rhs) ? lhs : rhs);
3608 }
3609 break;
3610 case WasmOp_f64_max:
3611 {
3612 double rhs = vm_pop_f64(vm);
3613 double lhs = vm_pop_f64(vm);
3614 vm_push_f64(vm, (lhs > rhs) ? lhs : rhs);
3615 }
3616 break;
3617 case WasmOp_f64_copysign:
3618 {
3619 double rhs = vm_pop_f64(vm);
3620 double lhs = vm_pop_f64(vm);
3621 vm_push_f64(vm, copysign(lhs, rhs));
3622 }
3623 break;
3624
3625 case WasmOp_i32_wrap_i64:
3626 {
3627 uint64_t operand = vm_pop_u64(vm);
3628 vm_push_u32(vm, operand);
3629 }
3630 break;
3631 case WasmOp_i32_trunc_f32_s:
3632 {
3633 float operand = vm_pop_f32(vm);
3634 vm_push_i32(vm, truncf(operand));
3635 }
3636 break;
3637 case WasmOp_i32_trunc_f32_u:
3638 {
3639 float operand = vm_pop_f32(vm);
3640 vm_push_u32(vm, truncf(operand));
3641 }
3642 break;
3643 case WasmOp_i32_trunc_f64_s:
3644 {
3645 double operand = vm_pop_f64(vm);
3646 vm_push_i32(vm, trunc(operand));
3647 }
3648 break;
3649 case WasmOp_i32_trunc_f64_u:
3650 {
3651 double operand = vm_pop_f64(vm);
3652 vm_push_u32(vm, trunc(operand));
3653 }
3654 break;
3655 case WasmOp_i64_extend_i32_s:
3656 {
3657 int32_t operand = vm_pop_i32(vm);
3658 vm_push_i64(vm, operand);
3659 }
3660 break;
3661 case WasmOp_i64_extend_i32_u:
3662 {
3663 uint64_t operand = vm_pop_u64(vm);
3664 vm_push_u64(vm, operand);
3665 }
3666 break;
3667 case WasmOp_i64_trunc_f32_s:
3668 {
3669 float operand = vm_pop_f32(vm);
3670 vm_push_i64(vm, truncf(operand));
3671 }
3672 break;
3673 case WasmOp_i64_trunc_f32_u:
3674 {
3675 float operand = vm_pop_f32(vm);
3676 vm_push_u64(vm, truncf(operand));
3677 }
3678 break;
3679 case WasmOp_i64_trunc_f64_s:
3680 {
3681 double operand = vm_pop_f64(vm);
3682 vm_push_i64(vm, trunc(operand));
3683 }
3684 break;
3685 case WasmOp_i64_trunc_f64_u:
3686 {
3687 double operand = vm_pop_f64(vm);
3688 vm_push_u64(vm, trunc(operand));
3689 }
3690 break;
3691 case WasmOp_f32_convert_i32_s:
3692 {
3693 vm_push_f32(vm, vm_pop_i32(vm));
3694 }
3695 break;
3696 case WasmOp_f32_convert_i32_u:
3697 {
3698 vm_push_f32(vm, vm_pop_u32(vm));
3699 }
3700 break;
3701 case WasmOp_f32_convert_i64_s:
3702 {
3703 vm_push_f32(vm, vm_pop_i64(vm));
3704 }
3705 break;
3706 case WasmOp_f32_convert_i64_u:
3707 {
3708 vm_push_f32(vm, vm_pop_u64(vm));
3709 }
3710 break;
3711 case WasmOp_f32_demote_f64:
3712 {
3713 vm_push_f32(vm, vm_pop_f64(vm));
3714 }
3715 break;
3716 case WasmOp_f64_convert_i32_s:
3717 {
3718 vm_push_f64(vm, vm_pop_i32(vm));
3719 }
3720 break;
3721 case WasmOp_f64_convert_i32_u:
3722 {
3723 vm_push_f64(vm, vm_pop_u32(vm));
3724 }
3725 break;
3726 case WasmOp_f64_convert_i64_s:
3727 {
3728 vm_push_f64(vm, vm_pop_i64(vm));
3729 }
3730 break;
3731 case WasmOp_f64_convert_i64_u:
3732 {
3733 vm_push_f64(vm, vm_pop_u64(vm));
3734 }
3735 break;
3736 case WasmOp_f64_promote_f32:
3737 {
3738 vm_push_f64(vm, vm_pop_f32(vm));
3739 }
3740 break;
3741
3742 case WasmOp_i32_extend8_s:
3743 {
3744 int8_t operand = vm_pop_i32(vm);
3745 vm_push_i32(vm, operand);
3746 }
3747 break;
3748 case WasmOp_i32_extend16_s:
3749 {
3750 int16_t operand = vm_pop_i32(vm);
3751 vm_push_i32(vm, operand);
3752 }
3753 break;
3754 case WasmOp_i64_extend8_s:
3755 {
3756 int8_t operand = vm_pop_i64(vm);
3757 vm_push_i64(vm, operand);
3758 }
3759 break;
3760 case WasmOp_i64_extend16_s:
3761 {
3762 int16_t operand = vm_pop_i64(vm);
3763 vm_push_i64(vm, operand);
3764 }
3765 break;
3766 case WasmOp_i64_extend32_s:
3767 {
3768 int32_t operand = vm_pop_i64(vm);
3769 vm_push_i64(vm, operand);
3770 }
3771 break;
3772
3773 default:
3774 panic("unreachable");
3775 }
3776 }
3777 break;
3778
3779 case Op_wasm_prefixed:
3780 {
3781 enum WasmPrefixedOp wasm_prefixed_op = opcodes[pc->opcode];
3782 pc->opcode += 1;
3783 switch (wasm_prefixed_op) {
3784 case WasmPrefixedOp_i32_trunc_sat_f32_s:
3785 panic("unreachable");
3786 case WasmPrefixedOp_i32_trunc_sat_f32_u:
3787 panic("unreachable");
3788 case WasmPrefixedOp_i32_trunc_sat_f64_s:
3789 panic("unreachable");
3790 case WasmPrefixedOp_i32_trunc_sat_f64_u:
3791 panic("unreachable");
3792 case WasmPrefixedOp_i64_trunc_sat_f32_s:
3793 panic("unreachable");
3794 case WasmPrefixedOp_i64_trunc_sat_f32_u:
3795 panic("unreachable");
3796 case WasmPrefixedOp_i64_trunc_sat_f64_s:
3797 panic("unreachable");
3798 case WasmPrefixedOp_i64_trunc_sat_f64_u:
3799 panic("unreachable");
3800 case WasmPrefixedOp_memory_init:
3801 panic("unreachable");
3802 case WasmPrefixedOp_data_drop:
3803 panic("unreachable");
3804
3805 case WasmPrefixedOp_memory_copy:
3806 {
3807 uint32_t n = vm_pop_u32(vm);
3808 uint32_t src = vm_pop_u32(vm);
3809 uint32_t dest = vm_pop_u32(vm);
3810 assert(dest + n <= vm->memory_len);
3811 assert(src + n <= vm->memory_len);
3812 assert(src + n <= dest || dest + n <= src); // overlapping
3813 memcpy(vm->memory + dest, vm->memory + src, n);
3814 }
3815 break;
3816
3817 case WasmPrefixedOp_memory_fill:
3818 {
3819 uint32_t n = vm_pop_u32(vm);
3820 uint8_t value = vm_pop_u32(vm);
3821 uint32_t dest = vm_pop_u32(vm);
3822 assert(dest + n <= vm->memory_len);
3823 memset(vm->memory + dest, value, n);
3824 }
3825 break;
3826
3827 case WasmPrefixedOp_table_init: panic("unreachable");
3828 case WasmPrefixedOp_elem_drop: panic("unreachable");
3829 case WasmPrefixedOp_table_copy: panic("unreachable");
3830 case WasmPrefixedOp_table_grow: panic("unreachable");
3831 case WasmPrefixedOp_table_size: panic("unreachable");
3832 case WasmPrefixedOp_table_fill: panic("unreachable");
3833 default: panic("unreachable");
3834 }
3835 }
3836 break;
3837
3838 }
3839 }
3840}
3841
3842int main(int argc, char **argv) {
3843 char *memory = mmap( NULL, max_memory, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
3844
3845 const char *zig_lib_dir_path = argv[1];
3846 const char *zig_cache_dir_path = argv[2];
3847 const size_t vm_argv_start = 3;
3848 const char *wasm_file = argv[vm_argv_start];
3849
3850 const struct ByteSlice mod = read_file_alloc(wasm_file);
3851
3852 int cwd = err_wrap("opening cwd", open(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
3853 mkdir(zig_cache_dir_path, 0666);
3854 int cache_dir = err_wrap("opening cache dir", open(zig_cache_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
3855 int zig_lib_dir = err_wrap("opening zig lib dir", open(zig_lib_dir_path, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_PATH));
3856
3857 add_preopen(0, "stdin", STDIN_FILENO);
3858 add_preopen(1, "stdout", STDOUT_FILENO);
3859 add_preopen(2, "stderr", STDERR_FILENO);
3860 add_preopen(3, ".", cwd);
3861 add_preopen(4, "/cache", cache_dir);
3862 add_preopen(5, "/lib", zig_lib_dir);
3863
3864 uint32_t i = 0;
3865
3866 if (mod.ptr[0] != 0 || mod.ptr[1] != 'a' || mod.ptr[2] != 's' || mod.ptr[3] != 'm') {
3867 panic("bad magic");
3868 }
3869 i += 4;
3870
3871 uint32_t version = read_u32_le(mod.ptr + i);
3872 i += 4;
3873 if (version != 1) panic("bad wasm version");
3874
3875 uint32_t section_starts[13];
3876 memset(&section_starts, 0, 4 * 13);
3877
3878 while (i < mod.len) {
3879 uint8_t section_id = mod.ptr[i];
3880 i += 1;
3881 uint32_t section_len = read32_uleb128(mod.ptr, &i);
3882 section_starts[section_id] = i;
3883 i += section_len;
3884 }
3885
3886 // Map type indexes to offsets into the module.
3887 struct TypeInfo *types;
3888 {
3889 i = section_starts[Section_type];
3890 uint32_t types_len = read32_uleb128(mod.ptr, &i);
3891 types = arena_alloc(sizeof(struct TypeInfo) * types_len);
3892 for (size_t type_i = 0; type_i < types_len; type_i += 1) {
3893 struct TypeInfo *info = &types[type_i];
3894 if (mod.ptr[i] != 0x60) panic("bad type byte");
3895 i += 1;
3896
3897 info->param_count = read32_uleb128(mod.ptr, &i);
3898 info->param_types = 0;
3899 for (uint32_t param_i = 0; param_i < info->param_count; param_i += 1) {
3900 int64_t param_type = read64_ileb128(mod.ptr, &i);
3901 switch (param_type) {
3902 case -1: case -3: bs_unset(&info->param_types, param_i); break;
3903 case -2: case -4: bs_set(&info->param_types, param_i); break;
3904 default: panic("unexpected param type");
3905 }
3906 }
3907
3908 info->result_count = read32_uleb128(mod.ptr, &i);
3909 info->result_types = 0;
3910 for (uint32_t result_i = 0; result_i < info->result_count; result_i += 1) {
3911 int64_t result_type = read64_ileb128(mod.ptr, &i);
3912 switch (result_type) {
3913 case -1: case -3: bs_unset(&info->result_types, result_i); break;
3914 case -2: case -4: bs_set(&info->result_types, result_i); break;
3915 default: panic("unexpected result type");
3916 }
3917 }
3918 }
3919 }
3920
3921 // Count the imported functions so we can correct function references.
3922 struct Import *imports;
3923 uint32_t imports_len;
3924 {
3925 i = section_starts[Section_import];
3926 imports_len = read32_uleb128(mod.ptr, &i);
3927 imports = arena_alloc(sizeof(struct Import) * imports_len);
3928 for (size_t imp_i = 0; imp_i < imports_len; imp_i += 1) {
3929 struct Import *imp = &imports[imp_i];
3930
3931 struct ByteSlice mod_name = read_name(mod.ptr, &i);
3932 if (mod_name.len == strlen("wasi_snapshot_preview1") &&
3933 memcmp(mod_name.ptr, "wasi_snapshot_preview1", mod_name.len) == 0) {
3934 imp->mod = ImpMod_wasi_snapshot_preview1;
3935 } else panic("unknown import module");
3936
3937 struct ByteSlice sym_name = read_name(mod.ptr, &i);
3938 if (sym_name.len == strlen("args_get") &&
3939 memcmp(sym_name.ptr, "args_get", sym_name.len) == 0) {
3940 imp->name = ImpName_args_get;
3941 } else if (sym_name.len == strlen("args_sizes_get") &&
3942 memcmp(sym_name.ptr, "args_sizes_get", sym_name.len) == 0) {
3943 imp->name = ImpName_args_sizes_get;
3944 } else if (sym_name.len == strlen("clock_time_get") &&
3945 memcmp(sym_name.ptr, "clock_time_get", sym_name.len) == 0) {
3946 imp->name = ImpName_clock_time_get;
3947 } else if (sym_name.len == strlen("debug") &&
3948 memcmp(sym_name.ptr, "debug", sym_name.len) == 0) {
3949 imp->name = ImpName_debug;
3950 } else if (sym_name.len == strlen("debug_slice") &&
3951 memcmp(sym_name.ptr, "debug_slice", sym_name.len) == 0) {
3952 imp->name = ImpName_debug_slice;
3953 } else if (sym_name.len == strlen("environ_get") &&
3954 memcmp(sym_name.ptr, "environ_get", sym_name.len) == 0) {
3955 imp->name = ImpName_environ_get;
3956 } else if (sym_name.len == strlen("environ_sizes_get") &&
3957 memcmp(sym_name.ptr, "environ_sizes_get", sym_name.len) == 0) {
3958 imp->name = ImpName_environ_sizes_get;
3959 } else if (sym_name.len == strlen("fd_close") &&
3960 memcmp(sym_name.ptr, "fd_close", sym_name.len) == 0) {
3961 imp->name = ImpName_fd_close;
3962 } else if (sym_name.len == strlen("fd_fdstat_get") &&
3963 memcmp(sym_name.ptr, "fd_fdstat_get", sym_name.len) == 0) {
3964 imp->name = ImpName_fd_fdstat_get;
3965 } else if (sym_name.len == strlen("fd_filestat_get") &&
3966 memcmp(sym_name.ptr, "fd_filestat_get", sym_name.len) == 0) {
3967 imp->name = ImpName_fd_filestat_get;
3968 } else if (sym_name.len == strlen("fd_filestat_set_size") &&
3969 memcmp(sym_name.ptr, "fd_filestat_set_size", sym_name.len) == 0) {
3970 imp->name = ImpName_fd_filestat_set_size;
3971 } else if (sym_name.len == strlen("fd_filestat_set_times") &&
3972 memcmp(sym_name.ptr, "fd_filestat_set_times", sym_name.len) == 0) {
3973 imp->name = ImpName_fd_filestat_set_times;
3974 } else if (sym_name.len == strlen("fd_pread") &&
3975 memcmp(sym_name.ptr, "fd_pread", sym_name.len) == 0) {
3976 imp->name = ImpName_fd_pread;
3977 } else if (sym_name.len == strlen("fd_prestat_dir_name") &&
3978 memcmp(sym_name.ptr, "fd_prestat_dir_name", sym_name.len) == 0) {
3979 imp->name = ImpName_fd_prestat_dir_name;
3980 } else if (sym_name.len == strlen("fd_prestat_get") &&
3981 memcmp(sym_name.ptr, "fd_prestat_get", sym_name.len) == 0) {
3982 imp->name = ImpName_fd_prestat_get;
3983 } else if (sym_name.len == strlen("fd_pwrite") &&
3984 memcmp(sym_name.ptr, "fd_pwrite", sym_name.len) == 0) {
3985 imp->name = ImpName_fd_pwrite;
3986 } else if (sym_name.len == strlen("fd_read") &&
3987 memcmp(sym_name.ptr, "fd_read", sym_name.len) == 0) {
3988 imp->name = ImpName_fd_read;
3989 } else if (sym_name.len == strlen("fd_readdir") &&
3990 memcmp(sym_name.ptr, "fd_readdir", sym_name.len) == 0) {
3991 imp->name = ImpName_fd_readdir;
3992 } else if (sym_name.len == strlen("fd_write") &&
3993 memcmp(sym_name.ptr, "fd_write", sym_name.len) == 0) {
3994 imp->name = ImpName_fd_write;
3995 } else if (sym_name.len == strlen("path_create_directory") &&
3996 memcmp(sym_name.ptr, "path_create_directory", sym_name.len) == 0) {
3997 imp->name = ImpName_path_create_directory;
3998 } else if (sym_name.len == strlen("path_filestat_get") &&
3999 memcmp(sym_name.ptr, "path_filestat_get", sym_name.len) == 0) {
4000 imp->name = ImpName_path_filestat_get;
4001 } else if (sym_name.len == strlen("path_open") &&
4002 memcmp(sym_name.ptr, "path_open", sym_name.len) == 0) {
4003 imp->name = ImpName_path_open;
4004 } else if (sym_name.len == strlen("path_remove_directory") &&
4005 memcmp(sym_name.ptr, "path_remove_directory", sym_name.len) == 0) {
4006 imp->name = ImpName_path_remove_directory;
4007 } else if (sym_name.len == strlen("path_rename") &&
4008 memcmp(sym_name.ptr, "path_rename", sym_name.len) == 0) {
4009 imp->name = ImpName_path_rename;
4010 } else if (sym_name.len == strlen("path_unlink_file") &&
4011 memcmp(sym_name.ptr, "path_unlink_file", sym_name.len) == 0) {
4012 imp->name = ImpName_path_unlink_file;
4013 } else if (sym_name.len == strlen("proc_exit") &&
4014 memcmp(sym_name.ptr, "proc_exit", sym_name.len) == 0) {
4015 imp->name = ImpName_proc_exit;
4016 } else if (sym_name.len == strlen("random_get") &&
4017 memcmp(sym_name.ptr, "random_get", sym_name.len) == 0) {
4018 imp->name = ImpName_random_get;
4019 } else panic("unknown import name");
4020
4021 uint32_t desc = read32_uleb128(mod.ptr, &i);
4022 if (desc != 0) panic("external kind not function");
4023 imp->type_idx = read32_uleb128(mod.ptr, &i);
4024 }
4025 }
4026
4027 // Find _start in the exports
4028 uint32_t start_fn_idx;
4029 {
4030 i = section_starts[Section_export];
4031 uint32_t count = read32_uleb128(mod.ptr, &i);
4032 for (; count > 0; count -= 1) {
4033 struct ByteSlice name = read_name(mod.ptr, &i);
4034 uint32_t desc = read32_uleb128(mod.ptr, &i);
4035 start_fn_idx = read32_uleb128(mod.ptr, &i);
4036 if (desc == 0 && name.len == strlen("_start") &&
4037 memcmp(name.ptr, "_start", name.len) == 0)
4038 {
4039 break;
4040 }
4041 }
4042 if (count == 0) panic("_start symbol not found");
4043 }
4044
4045 // Map function indexes to offsets into the module and type index.
4046 struct Function *functions;
4047 uint32_t functions_len;
4048 {
4049 i = section_starts[Section_function];
4050 functions_len = read32_uleb128(mod.ptr, &i);
4051 functions = arena_alloc(sizeof(struct Function) * functions_len);
4052 for (size_t func_i = 0; func_i < functions_len; func_i += 1) {
4053 struct Function *func = &functions[func_i];
4054 func->type_idx = read32_uleb128(mod.ptr, &i);
4055 }
4056 }
4057
4058 // Allocate and initialize globals.
4059 uint64_t *globals;
4060 {
4061 i = section_starts[Section_global];
4062 uint32_t globals_len = read32_uleb128(mod.ptr, &i);
4063 globals = arena_alloc(sizeof(uint64_t) * globals_len);
4064 for (size_t glob_i = 0; glob_i < globals_len; glob_i += 1) {
4065 uint64_t *global = &globals[glob_i];
4066 uint32_t content_type = read32_uleb128(mod.ptr, &i);
4067 uint32_t mutability = read32_uleb128(mod.ptr, &i);
4068 if (mutability != 1) panic("expected mutable global");
4069 if (content_type != 0x7f) panic("unexpected content type");
4070 uint8_t opcode = mod.ptr[i];
4071 i += 1;
4072 if (opcode != WasmOp_i32_const) panic("expected i32_const op");
4073 uint32_t init = read32_ileb128(mod.ptr, &i);
4074 *global = (uint32_t)init;
4075 }
4076 }
4077
4078 // Allocate and initialize memory.
4079 uint32_t memory_len;
4080 {
4081 i = section_starts[Section_memory];
4082 uint32_t memories_len = read32_uleb128(mod.ptr, &i);
4083 if (memories_len != 1) panic("unexpected memory count");
4084 uint32_t flags = read32_uleb128(mod.ptr, &i);
4085 (void)flags;
4086 memory_len = read32_uleb128(mod.ptr, &i) * wasm_page_size;
4087
4088 i = section_starts[Section_data];
4089 uint32_t datas_count = read32_uleb128(mod.ptr, &i);
4090 for (; datas_count > 0; datas_count -= 1) {
4091 uint32_t mode = read32_uleb128(mod.ptr, &i);
4092 if (mode != 0) panic("expected mode 0");
4093 enum WasmOp opcode = mod.ptr[i];
4094 i += 1;
4095 if (opcode != WasmOp_i32_const) panic("expected opcode i32_const");
4096 uint32_t offset = read32_uleb128(mod.ptr, &i);
4097 enum WasmOp end = mod.ptr[i];
4098 if (end != WasmOp_end) panic("expected end opcode");
4099 i += 1;
4100 uint32_t bytes_len = read32_uleb128(mod.ptr, &i);
4101 memcpy(memory + offset, mod.ptr + i, bytes_len);
4102 i += bytes_len;
4103 }
4104 }
4105
4106 uint32_t *table = NULL;
4107 {
4108 i = section_starts[Section_table];
4109 uint32_t table_count = read32_uleb128(mod.ptr, &i);
4110 if (table_count > 1) {
4111 panic("expected only one table section");
4112 } else if (table_count == 1) {
4113 uint32_t element_type = read32_uleb128(mod.ptr, &i);
4114 (void)element_type;
4115 uint32_t has_max = read32_uleb128(mod.ptr, &i);
4116 if (has_max != 1) panic("expected has_max==1");
4117 uint32_t initial = read32_uleb128(mod.ptr, &i);
4118 (void)initial;
4119 uint32_t maximum = read32_uleb128(mod.ptr, &i);
4120
4121 i = section_starts[Section_element];
4122 uint32_t element_section_count = read32_uleb128(mod.ptr, &i);
4123 if (element_section_count != 1) panic("expected one element section");
4124 uint32_t flags = read32_uleb128(mod.ptr, &i);
4125 (void)flags;
4126 enum WasmOp opcode = mod.ptr[i];
4127 i += 1;
4128 if (opcode != WasmOp_i32_const) panic("expected op i32_const");
4129 uint32_t offset = read32_uleb128(mod.ptr, &i);
4130 enum WasmOp end = mod.ptr[i];
4131 if (end != WasmOp_end) panic("expected op end");
4132 i += 1;
4133 uint32_t elem_count = read32_uleb128(mod.ptr, &i);
4134
4135 table = arena_alloc(sizeof(uint32_t) * maximum);
4136 memset(table, 0, maximum);
4137
4138 for (uint32_t elem_i = 0; elem_i < elem_count; elem_i += 1) {
4139 table[elem_i + offset] = read32_uleb128(mod.ptr, &i);
4140 }
4141 }
4142 }
4143
4144 struct VirtualMachine vm;
4145 vm.stack = arena_alloc(sizeof(uint64_t) * 10000000),
4146 vm.mod_ptr = mod.ptr;
4147 vm.opcodes = arena_alloc(2000000);
4148 vm.operands = arena_alloc(sizeof(uint32_t) * 2000000);
4149 vm.stack_top = 0;
4150 vm.functions = functions;
4151 vm.types = types;
4152 vm.globals = globals;
4153 vm.memory = memory;
4154 vm.memory_len = memory_len;
4155 vm.imports = imports;
4156 vm.imports_len = imports_len;
4157 vm.args = argv + vm_argv_start;
4158 vm.table = table;
4159
4160 {
4161 uint32_t code_i = section_starts[Section_code];
4162 uint32_t codes_len = read32_uleb128(mod.ptr, &code_i);
4163 if (codes_len != functions_len) panic("code/function length mismatch");
4164 struct ProgramCounter pc;
4165 pc.opcode = 0;
4166 pc.operand = 0;
4167 for (uint32_t func_i = 0; func_i < functions_len; func_i += 1) {
4168 struct Function *func = &functions[func_i];
4169 uint32_t size = read32_uleb128(mod.ptr, &code_i);
4170 uint32_t code_begin = code_i;
4171
4172 struct TypeInfo *type_info = &vm.types[func->type_idx];
4173 func->locals_count = 0;
4174 func->local_types = arena_alloc(sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
4175 func->local_types[0] = type_info->param_types;
4176
4177 for (uint32_t local_sets_count = read32_uleb128(mod.ptr, &code_i);
4178 local_sets_count > 0; local_sets_count -= 1) {
4179 uint32_t set_count = read32_uleb128(mod.ptr, &code_i);
4180 int64_t local_type = read64_ileb128(mod.ptr, &code_i);
4181
4182 uint32_t i = type_info->param_count + func->locals_count;
4183 func->locals_count += set_count;
4184 if ((type_info->param_count + func->locals_count + 31) / 32 > (i + 31) / 32)
4185 func->local_types = arena_realloc(func->local_types, sizeof(uint32_t) * ((type_info->param_count + func->locals_count + 31) / 32));
4186 for (; i < type_info->param_count + func->locals_count; i += 1)
4187 switch (local_type) {
4188 case -1: case -3: bs_unset(func->local_types, i); break;
4189 case -2: case -4: bs_set(func->local_types, i); break;
4190 default: panic("unexpected local type");
4191 }
4192 }
4193
4194 func->entry_pc = pc;
4195 vm_decodeCode(&vm, func, &code_i, &pc);
4196 if (code_i != code_begin + size) panic("bad code size");
4197 }
4198
4199 uint64_t opcode_counts[0x100];
4200 memset(opcode_counts, 0, 0x100);
4201 uint64_t prefixed_opcode_counts[0x100];
4202 memset(prefixed_opcode_counts, 0, 0x100);
4203 bool is_prefixed = false;
4204 for (uint32_t opcode_i = 0; opcode_i < pc.opcode; opcode_i += 1) {
4205 uint8_t opcode = vm.opcodes[opcode_i];
4206 if (!is_prefixed) {
4207 opcode_counts[opcode] += 1;
4208 is_prefixed = opcode == WasmOp_prefixed;
4209 } else {
4210 prefixed_opcode_counts[opcode] += 1;
4211 is_prefixed = false;
4212 }
4213 }
4214 }
4215
4216 vm_call(&vm, start_fn_idx);
4217 vm_run(&vm);
4218
4219 return 0;
4220}