Skip to content
Draft

test #33

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
33d8840
meson: Add wasm64 support to the --cpu flag
ktock Jul 11, 2025
f0fcfef
configure: Enable to propagate -sMEMORY64 flag to Emscripten
ktock Jul 12, 2025
dd1d5ae
dockerfiles: Add support for wasm64 to the wasm Dockerfile
ktock Jul 11, 2025
74f75ef
.gitlab-ci.d: Add build tests for wasm64
ktock Jul 11, 2025
a313580
tcg/wasm: Add tcg-target.h and tcg-target-reg-bits.h
ktock Aug 26, 2025
1582a3f
tcg/wasm: Add register-related definitions
ktock Aug 25, 2025
d935ea0
tcg/wasm: Add constraint definitions
ktock Aug 25, 2025
5baf88b
tcg/wasm: Add relocation callbacks
ktock Aug 25, 2025
f8cb9a6
tcg/wasm: Add and/or/xor instructions
ktock Aug 25, 2025
172f143
tcg/wasm: Add add/sub/mul instructions
ktock Aug 22, 2025
cb7883a
tcg/wasm: Add shl/shr/sar instructions
ktock Aug 21, 2025
9dbeb86
tcg/wasm: Add setcond/negsetcond/movcond instructions
ktock Aug 21, 2025
f4f7a03
tcg/wasm: Add sextract instruction
ktock Aug 21, 2025
a507277
tcg/wasm: Add load and store instructions
ktock Aug 21, 2025
13eb7d5
tcg/wasm: Add mov/movi instructions
ktock Aug 21, 2025
0047344
tcg/wasm: Add ext instructions
ktock Aug 21, 2025
32eaa62
tcg/wasm: Add div/rem instructions
ktock Aug 21, 2025
2cb39a5
tcg/wasm: Add neg/ctpop instructions
ktock Aug 26, 2025
ad0fb42
tcg/wasm: Add rot/clz/ctz instructions
ktock Aug 21, 2025
50b395e
tcg/wasm: Add br/brcond instructions
ktock Aug 21, 2025
f15853e
tcg/wasm: Add exit_tb/goto_tb/goto_ptr instructions
ktock Aug 25, 2025
942c6e4
tcg/wasm: Add call instruction
ktock Aug 21, 2025
85196f1
tcg/wasm: Add qemu_ld/qemu_st instructions
ktock Aug 21, 2025
3db8ec7
tcg/wasm: Add mb instruction
ktock Aug 22, 2025
a3656a3
tcg/wasm: Mark unimplemented instructions
ktock Aug 22, 2025
6cad2aa
tcg/wasm: Add initialization of fundamental registers
ktock Aug 23, 2025
4d80cd3
tcg/wasm: Write wasm binary to TB
ktock Aug 23, 2025
c0d0518
tcg/wasm: Implement instantiation of Wasm binary
ktock Aug 23, 2025
18770eb
tcg/wasm: Allow switching coroutine from a helper
ktock Aug 23, 2025
d7d4fc4
tcg/wasm: Enable instantiation of TBs executed many times
ktock Aug 22, 2025
f49e907
tcg/wasm: Enable TLB lookup
ktock Aug 23, 2025
e54f87b
tcg/wasm: Add tcg_target_init function
ktock Aug 25, 2025
e7333cf
meson.build: enable to build Wasm backend
ktock Aug 22, 2025
bbc6981
meson.build: Propagate optimization flag for linking on Emscripten
ktock Aug 23, 2025
cfa10fb
.gitlab-ci.d: build wasm backend in CI
ktock Aug 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions .gitlab-ci.d/buildtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -787,11 +787,29 @@ coverity:
# Always manual on forks even if $QEMU_CI == "2"
- when: manual

build-wasm:
build-wasm32-32bit:
extends: .wasm_build_job_template
timeout: 2h
needs:
job: wasm-emsdk-cross-container
job: wasm32-32bit-emsdk-cross-container
variables:
IMAGE: emsdk-wasm32-cross
CONFIGURE_ARGS: --static --disable-tools --enable-debug --enable-tcg-interpreter
IMAGE: emsdk-wasm32-32bit-cross
CONFIGURE_ARGS: --static --cpu=wasm32 --disable-tools --enable-debug --enable-tcg-interpreter

build-wasm64-64bit:
extends: .wasm_build_job_template
timeout: 2h
needs:
job: wasm64-64bit-emsdk-cross-container
variables:
IMAGE: emsdk-wasm64-64bit-cross
CONFIGURE_ARGS: --static --cpu=wasm64 --disable-tools --enable-debug

build-wasm64-32bit:
extends: .wasm_build_job_template
timeout: 2h
needs:
job: wasm64-32bit-emsdk-cross-container
variables:
IMAGE: emsdk-wasm64-32bit-cross
CONFIGURE_ARGS: --static --cpu=wasm64 --enable-wasm64-32bit-address-limit --disable-tools --enable-debug
20 changes: 18 additions & 2 deletions .gitlab-ci.d/container-cross.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,23 @@ win64-fedora-cross-container:
variables:
NAME: fedora-win64-cross

wasm-emsdk-cross-container:
wasm32-32bit-emsdk-cross-container:
extends: .container_job_template
variables:
NAME: emsdk-wasm32-cross
NAME: emsdk-wasm32-32bit-cross
BUILD_ARGS: --build-arg TARGET_CPU=wasm32
DOCKERFILE: emsdk-wasm-cross

wasm64-64bit-emsdk-cross-container:
extends: .container_job_template
variables:
NAME: emsdk-wasm64-64bit-cross
BUILD_ARGS: --build-arg TARGET_CPU=wasm64 --build-arg WASM64_MEMORY64=1
DOCKERFILE: emsdk-wasm-cross

wasm64-32bit-emsdk-cross-container:
extends: .container_job_template
variables:
NAME: emsdk-wasm64-32bit-cross
BUILD_ARGS: --build-arg TARGET_CPU=wasm64 --build-arg WASM64_MEMORY64=2
DOCKERFILE: emsdk-wasm-cross
4 changes: 3 additions & 1 deletion .gitlab-ci.d/container-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
- export COMMON_TAG="$CI_REGISTRY/qemu-project/qemu/qemu/$NAME:latest"
- docker login $CI_REGISTRY -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD"
- until docker info; do sleep 1; done
- export DOCKERFILE_NAME=${DOCKERFILE:-$NAME}
script:
- echo "TAG:$TAG"
- echo "COMMON_TAG:$COMMON_TAG"
- docker build --tag "$TAG" --cache-from "$TAG" --cache-from "$COMMON_TAG"
--build-arg BUILDKIT_INLINE_CACHE=1
-f "tests/docker/dockerfiles/$NAME.docker" "."
$BUILD_ARGS
-f "tests/docker/dockerfiles/$DOCKERFILE_NAME.docker" "."
- docker push "$TAG"
after_script:
- docker logout
9 changes: 8 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ F: include/system/os-wasm.h
F: os-wasm.c
F: util/coroutine-wasm.c
F: configs/meson/emscripten.txt
F: tests/docker/dockerfiles/emsdk-wasm32-cross.docker
F: tests/docker/dockerfiles/emsdk-wasm-cross.docker

Alpha Machines
--------------
Expand Down Expand Up @@ -3999,6 +3999,13 @@ F: tcg/tci/
F: tcg/tci.c
F: disas/tci.c

WebAssembly TCG target
M: Kohei Tokunaga <ktokunaga.mail@gmail.com>
S: Maintained
F: tcg/wasm/
F: tcg/wasm.c
F: tcg/wasm.h

Block drivers
-------------
VMDK
Expand Down
14 changes: 13 additions & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ EXTRA_CXXFLAGS=""
EXTRA_OBJCFLAGS=""
EXTRA_LDFLAGS=""

# The value is propagated to Emscripten's "-sMEMORY64" flag.
# https://emscripten.org/docs/tools_reference/settings_reference.html#memory64
wasm64_memory64=1

# Default value for a variable defining feature "foo".
# * foo="no" feature will only be used if --enable-foo arg is given
# * foo="" feature will be searched for, and if found, will be used
Expand Down Expand Up @@ -239,6 +243,10 @@ for opt do
;;
--without-default-features) default_feature="no"
;;
--enable-wasm64-32bit-address-limit) wasm64_memory64="2"
;;
--disable-wasm64-32bit-address-limit) wasm64_memory64="1"
;;
esac
done

Expand Down Expand Up @@ -365,7 +373,6 @@ elif check_define __APPLE__; then
host_os=darwin
elif check_define EMSCRIPTEN ; then
host_os=emscripten
cpu=wasm32
cross_compile="yes"
else
# This is a fatal error, but don't report it yet, because we
Expand Down Expand Up @@ -425,6 +432,8 @@ elif check_define __aarch64__ ; then
cpu="aarch64"
elif check_define __loongarch64 ; then
cpu="loongarch64"
elif check_define EMSCRIPTEN ; then
error_exit "wasm32 or wasm64 must be specified to the cpu flag"
else
# Using uname is really broken, but it is just a fallback for architectures
# that are going to use TCI anyway
Expand Down Expand Up @@ -535,6 +544,9 @@ case "$cpu" in
wasm32)
CPU_CFLAGS="-m32"
;;
wasm64)
CPU_CFLAGS="-m64 -sMEMORY64=$wasm64_memory64"
;;
esac

if test -n "$host_arch" && {
Expand Down
2 changes: 1 addition & 1 deletion include/accel/tcg/getpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define ACCEL_TCG_GETPC_H

/* GETPC is the true target of the return instruction that we'll execute. */
#ifdef CONFIG_TCG_INTERPRETER
#if defined(CONFIG_TCG_INTERPRETER) || defined(EMSCRIPTEN)
extern __thread uintptr_t tci_tb_ptr;
# define GETPC() tci_tb_ptr
#else
Expand Down
4 changes: 2 additions & 2 deletions include/tcg/helper-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#ifndef TCG_HELPER_INFO_H
#define TCG_HELPER_INFO_H

#ifdef CONFIG_TCG_INTERPRETER
#if defined(CONFIG_TCG_INTERPRETER) || defined(EMSCRIPTEN)
#include <ffi.h>
#endif
#include "tcg-target-reg-bits.h"
Expand Down Expand Up @@ -48,7 +48,7 @@ struct TCGHelperInfo {
const char *name;

/* Used with g_once_init_enter. */
#ifdef CONFIG_TCG_INTERPRETER
#if defined(CONFIG_TCG_INTERPRETER) || defined(EMSCRIPTEN)
ffi_cif *cif;
#else
uintptr_t init;
Expand Down
2 changes: 1 addition & 1 deletion include/tcg/tcg.h
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,7 @@ static inline size_t tcg_current_code_size(TCGContext *s)
#define TB_EXIT_IDXMAX 1
#define TB_EXIT_REQUESTED 3

#ifdef CONFIG_TCG_INTERPRETER
#if defined(CONFIG_TCG_INTERPRETER) || defined(EMSCRIPTEN)
uintptr_t tcg_qemu_tb_exec(CPUArchState *env, const void *tb_ptr);
#else
typedef uintptr_t tcg_prologue_fn(CPUArchState *env, const void *tb_ptr);
Expand Down
16 changes: 14 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ qapi_trace_events = []
bsd_oses = ['gnu/kfreebsd', 'freebsd', 'netbsd', 'openbsd', 'dragonfly', 'darwin']
supported_oses = ['windows', 'freebsd', 'netbsd', 'openbsd', 'darwin', 'sunos', 'linux', 'emscripten']
supported_cpus = ['ppc', 'ppc64', 's390x', 'riscv32', 'riscv64', 'x86', 'x86_64',
'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64', 'wasm32']
'arm', 'aarch64', 'loongarch64', 'mips', 'mips64', 'sparc64', 'wasm32', 'wasm64']

cpu = host_machine.cpu_family()

Expand Down Expand Up @@ -393,6 +393,10 @@ elif host_os == 'windows'
if compiler.get_id() == 'clang' and compiler.get_linker_id() != 'ld.lld'
error('On windows, you need to use lld with clang - use msys2 clang64/clangarm64 env')
endif
elif host_os == 'emscripten'
if cpu == 'wasm64' and get_option('wasm64_32bit_address_limit')
qemu_common_flags += '-DWASM64_MEMORY64_2'
endif
endif

# Choose instruction set (currently x86-only)
Expand Down Expand Up @@ -874,6 +878,12 @@ elif host_os == 'openbsd'
# Disable OpenBSD W^X if available
emulator_link_args = cc.get_supported_link_arguments('-Wl,-z,wxneeded')
endif
elif host_os == 'emscripten'
# Emscripten uses the optimization flag also during the link time.
# https://emscripten.org/docs/optimizing/Optimizing-Code.html#how-emscripten-optimizes
if get_option('optimization') != 'plain'
emulator_link_args += ['-O' + get_option('optimization')]
endif
endif

###############################################
Expand Down Expand Up @@ -918,7 +928,7 @@ if have_tcg
endif
elif host_arch == 'wasm32'
if not get_option('tcg_interpreter')
error('WebAssembly host requires --enable-tcg-interpreter')
error('wasm32 host requires --enable-tcg-interpreter')
endif
elif get_option('tcg_interpreter')
warning('Use of the TCG interpreter is not recommended on this host')
Expand All @@ -934,6 +944,8 @@ if have_tcg
tcg_arch = 'i386'
elif host_arch == 'ppc64'
tcg_arch = 'ppc'
elif host_arch == 'wasm64'
tcg_arch = 'wasm'
endif
add_project_arguments('-iquote', meson.current_source_dir() / 'tcg' / tcg_arch,
language: all_languages)
Expand Down
3 changes: 3 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -386,3 +386,6 @@ option('rust', type: 'feature', value: 'disabled',
description: 'Rust support')
option('strict_rust_lints', type: 'boolean', value: false,
description: 'Enable stricter set of Rust warnings')

option('wasm64_32bit_address_limit', type: 'boolean', value: false,
description: 'Restrict wasm64 address space to 32-bit (default is to use the whole 64-bit range).')
5 changes: 5 additions & 0 deletions scripts/meson-buildoptions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ meson_options_help() {
printf "%s\n" ' dtrace/ftrace/log/nop/simple/syslog/ust)'
printf "%s\n" ' --enable-tsan enable thread sanitizer'
printf "%s\n" ' --enable-ubsan enable undefined behaviour sanitizer'
printf "%s\n" ' --enable-wasm64-32bit-address-limit'
printf "%s\n" ' Restrict wasm64 address space to 32-bit (default'
printf "%s\n" ' is to use the whole 64-bit range).'
printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-'
printf "%s\n" ' firmware]'
printf "%s\n" ' --iasl=VALUE Path to ACPI disassembler'
Expand Down Expand Up @@ -571,6 +574,8 @@ _meson_option_parse() {
--disable-vte) printf "%s" -Dvte=disabled ;;
--enable-vvfat) printf "%s" -Dvvfat=enabled ;;
--disable-vvfat) printf "%s" -Dvvfat=disabled ;;
--enable-wasm64-32bit-address-limit) printf "%s" -Dwasm64_32bit_address_limit=true ;;
--disable-wasm64-32bit-address-limit) printf "%s" -Dwasm64_32bit_address_limit=false ;;
--enable-werror) printf "%s" -Dwerror=true ;;
--disable-werror) printf "%s" -Dwerror=false ;;
--enable-whpx) printf "%s" -Dwhpx=enabled ;;
Expand Down
11 changes: 11 additions & 0 deletions tcg/aarch64/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3514,6 +3514,17 @@ static void tcg_out_tb_start(TCGContext *s)
tcg_out_bti(s, BTI_J);
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
{
int i;
Expand Down
11 changes: 11 additions & 0 deletions tcg/arm/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3441,6 +3441,17 @@ static void tcg_out_tb_start(TCGContext *s)
/* nothing to do */
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

typedef struct {
DebugFrameHeader h;
uint8_t fde_def_cfa[4];
Expand Down
11 changes: 11 additions & 0 deletions tcg/i386/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -4759,6 +4759,17 @@ static void tcg_out_tb_start(TCGContext *s)
/* nothing to do */
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
{
memset(p, 0x90, count);
Expand Down
11 changes: 11 additions & 0 deletions tcg/loongarch64/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2658,6 +2658,17 @@ static void tcg_out_tb_start(TCGContext *s)
/* nothing to do */
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
{
for (int i = 0; i < count; ++i) {
Expand Down
5 changes: 5 additions & 0 deletions tcg/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ if get_option('tcg_interpreter')
method: 'pkg-config')
tcg_ss.add(libffi)
tcg_ss.add(files('tci.c'))
elif host_os == 'emscripten'
libffi = dependency('libffi', version: '>=3.0', required: true,
method: 'pkg-config')
specific_ss.add(libffi)
specific_ss.add(files('wasm.c'))
endif

tcg_ss.add(when: libdw, if_true: files('debuginfo.c'))
Expand Down
11 changes: 11 additions & 0 deletions tcg/mips/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2745,6 +2745,17 @@ static void tcg_out_tb_start(TCGContext *s)
/* nothing to do */
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

static void tcg_target_init(TCGContext *s)
{
tcg_target_detect_isa();
Expand Down
11 changes: 11 additions & 0 deletions tcg/ppc/tcg-target.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2859,6 +2859,17 @@ static void tcg_out_tb_start(TCGContext *s)
}
}

static int tcg_out_tb_end(TCGContext *s)
{
/* nothing to do */
return 0;
}

static void tcg_out_label_cb(TCGContext *s, TCGLabel *l)
{
/* nothing to do */
}

static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
{
tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, arg);
Expand Down
Loading