Skip to content

Commit

Permalink
Add __wasix_init and __wasix_resume to support partial evaluation tools
Browse files Browse the repository at this point in the history
  • Loading branch information
Arshia001 committed Aug 22, 2024
1 parent c20a27d commit 71b368d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 12 deletions.
2 changes: 2 additions & 0 deletions expected/wasm32-wasi-threads/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@ __wasilibc_tls_align
__wasilibc_tls_size
__wasilibc_unlinkat
__wasilibc_utimens
__wasix_init
__wasix_resume
__wasm_call_dtors
__wasm_signal
__wcscoll_l
Expand Down
2 changes: 2 additions & 0 deletions expected/wasm32-wasi/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ __wasilibc_tls_align
__wasilibc_tls_size
__wasilibc_unlinkat
__wasilibc_utimens
__wasix_init
__wasix_resume
__wasm_call_dtors
__wasm_signal
__wcscoll_l
Expand Down
2 changes: 2 additions & 0 deletions expected/wasm64-wasi/defined-symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ __wasilibc_tls_align
__wasilibc_tls_size
__wasilibc_unlinkat
__wasilibc_utimens
__wasix_init
__wasix_resume
__wasm_call_dtors
__wasm_signal
__wcscoll_l
Expand Down
95 changes: 83 additions & 12 deletions libc-bottom-half/crt/crt1-command.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,40 @@ extern void __wasm_call_ctors(void);
extern int __main_void(void);
extern void __wasm_call_dtors(void);

// We use `volatile` here to prevent the store to `started` from being
// sunk past any subsequent code, and to prevent any compiler from
// optimizing based on the knowledge that `_start` is the program
// entrypoint.
#ifdef _REENTRANT
static volatile _Atomic int __wasix_started = 0;
static volatile _Atomic int __wasix_resumed = 0;
#else
static volatile int __wasix_started = 0;
static volatile int __wasix_resumed = 0;
#endif

__attribute__((export_name("_start")))
void _start(void) {
// Commands should only be called once per instance. This simple check
// ensures that the `_start` function isn't started more than once.
//
// We use `volatile` here to prevent the store to `started` from being
// sunk past any subsequent code, and to prevent any compiler from
// optimizing based on the knowledge that `_start` is the program
// entrypoint.
#ifdef _REENTRANT
static volatile _Atomic int started = 0;
int expected = 0;
if (!atomic_compare_exchange_strong(&started, &expected, 1)) {
__builtin_trap();
int resume_expected = 0;
if (!atomic_compare_exchange_strong(&__wasix_started, &expected, 1)) {
__builtin_trap();
}
if (!atomic_compare_exchange_strong(&__wasix_resumed, &resume_expected, 1)) {
__builtin_trap();
}
#else
static volatile int started = 0;
if (started != 0) {
__builtin_trap();
if (__wasix_started != 0) {
__builtin_trap();
}
__wasix_started = 1;
if (__wasix_resumed != 0) {
__builtin_trap();
}
started = 1;
__wasix_resumed = 1;
#endif

#ifdef _REENTRANT
Expand All @@ -51,3 +64,61 @@ void _start(void) {
__wasi_proc_exit(r);
}
}

// This function acts as the top "half" of _start, up until the call to
// __main_void. This is useful when a module needs to do initialization
// separately, e.g. when using partial evaluation tools. When used with
// __wasix_resume, they perform the same logic as calling _start once.
__attribute__((export_name("__wasix_init")))
void __wasix_init(void) {
#ifdef _REENTRANT
int expected = 0;
if (!atomic_compare_exchange_strong(&__wasix_started, &expected, 1)) {
__builtin_trap();
}
#else
if (__wasix_started != 0) {
__builtin_trap();
}
__wasix_started = 1;
#endif

#ifdef _REENTRANT
__wasi_init_tp();
#endif

__wasm_call_ctors();
}

// This is the bottom "half" of _start, which can be called after
// __wasix_init to continue executing the module normally. This
// function also checks the value of __wasix_started to make sure
// __wasix_init was called beforehand.
__attribute__((export_name("__wasix_resume")))
void __wasix_resume(void) {
#ifdef _REENTRANT
if (atomic_load(&__wasix_started) != 1) {
__builtin_trap();
}
int expected = 0;
if (!atomic_compare_exchange_strong(&__wasix_resumed, &expected, 1)) {
__builtin_trap();
}
#else
if (__wasix_started != 1) {
__builtin_trap();
}
if (__wasix_resumed != 0) {
__builtin_trap();
}
__wasix_resumed = 1;
#endif

int r = __main_void();

__wasm_call_dtors();

if (r != 0) {
__wasi_proc_exit(r);
}
}

0 comments on commit 71b368d

Please sign in to comment.