// The linker synthesizes this to call constructors.
__wasm_call_ctors();
- // Call `__original_main` which will either be the application's
- // zero-argument `main` function (renamed by the compiler) or a libc
- // routine which populates `argv` and `argc` and calls the application's
- // two-argument `main`.
+ // Call `__original_main` which will either be the application's zero-argument
+ // `__original_main` function or a libc routine which calls `__main_void`.
+ // TODO: Call `main` directly once we no longer have to support old compilers.
int r = __original_main();
// Call atexit functions, destructors, stdio cleanup, etc.
__log_data
__logf_data
__lseek
+__main_argc_argv
+__main_void
__math_divzero
__math_divzerof
__math_invalid
#include <wasi/api.h>
-#include <wasi/libc.h>
extern void __wasm_call_ctors(void);
extern int __original_main(void);
extern void __prepare_for_exit(void);
// The linker synthesizes this to call constructors.
__wasm_call_ctors();
- // Call `__original_main` which will either be the application's
- // zero-argument `main` function (renamed by the compiler) or a libc
- // routine which populates `argv` and `argc` and calls the application's
- // two-argument `main`.
+ // Call `__original_main` which will either be the application's zero-argument
+ // `__original_main` function or a libc routine which calls `__main_void`.
+ // TODO: Call `main` directly once we no longer have to support old compilers.
int r = __original_main();
// Call atexit functions, destructors, stdio cleanup, etc.
--- /dev/null
+// New compilers define `__main_argc_argv`. If that doesn't exist, we
+// may get called here. Old compilers define `main` expecting an
+// argv/argc, so call that.
+// TODO: Remove this layer when we no longer have to support old compilers.
+int __wasilibc_main(int argc, char *argv[]) asm("main");
+
+__attribute__((weak, nodebug))
+int __main_argc_argv(int argc, char *argv[]) {
+ return __wasilibc_main(argc, argv);
+}
--- /dev/null
+#include <wasi/api.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+// The user's `main` function, expecting arguments.
+int __main_argc_argv(int argc, char *argv[]);
+
+// If the user's `main` function expects arguments, the compiler will rename
+// it to `__main_argc_argv`, and this version will get linked in, which
+// initializes the argument data and calls `__main_argc_argv`.
+__attribute__((weak, nodebug))
+int __main_void(void) {
+ __wasi_errno_t err;
+
+ // Get the sizes of the arrays we'll have to create to copy in the args.
+ size_t argv_buf_size;
+ size_t argc;
+ err = __wasi_args_sizes_get(&argc, &argv_buf_size);
+ if (err != __WASI_ERRNO_SUCCESS) {
+ _Exit(EX_OSERR);
+ }
+
+ // Add 1 for the NULL pointer to mark the end, and check for overflow.
+ size_t num_ptrs = argc + 1;
+ if (num_ptrs == 0) {
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Allocate memory for storing the argument chars.
+ char *argv_buf = malloc(argv_buf_size);
+ if (argv_buf == NULL) {
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Allocate memory for the array of pointers. This uses `calloc` both to
+ // handle overflow and to initialize the NULL pointer at the end.
+ char **argv = calloc(num_ptrs, sizeof(char *));
+ if (argv == NULL) {
+ free(argv_buf);
+ _Exit(EX_SOFTWARE);
+ }
+
+ // Fill the argument chars, and the argv array with pointers into those chars.
+ // TODO: Remove the casts on `argv_ptrs` and `argv_buf` once the witx is updated with char8 support.
+ err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf);
+ if (err != __WASI_ERRNO_SUCCESS) {
+ free(argv_buf);
+ free(argv);
+ _Exit(EX_OSERR);
+ }
+
+ // Call `__main_argc_argv` with the arguments!
+ return __main_argc_argv(argc, argv);
+}
-#include <wasi/api.h>
-#include <wasi/libc.h>
-#include <stdlib.h>
-#include <sysexits.h>
+// Old compilers define `__original_main`. If that doesn't exist, we
+// get called here. New compilers define `__main_void`. If that doesn't
+// exist, we'll try something else.
+// TODO: Remove this layer when we no longer have to support old compilers.
+int __main_void(void);
-// The user's `main` function, expecting arguments.
-int main(int argc, char *argv[]);
-
-// If the user's `main` function expects arguments, the compiler won't emit
-// an `__original_main` function so this version will get linked in, which
-// initializes the argument data and calls `main`.
__attribute__((weak))
int __original_main(void) {
- __wasi_errno_t err;
-
- // Get the sizes of the arrays we'll have to create to copy in the args.
- size_t argv_buf_size;
- size_t argc;
- err = __wasi_args_sizes_get(&argc, &argv_buf_size);
- if (err != __WASI_ERRNO_SUCCESS) {
- _Exit(EX_OSERR);
- }
-
- // Add 1 for the NULL pointer to mark the end, and check for overflow.
- size_t num_ptrs = argc + 1;
- if (num_ptrs == 0) {
- _Exit(EX_SOFTWARE);
- }
-
- // Allocate memory for storing the argument chars.
- char *argv_buf = malloc(argv_buf_size);
- if (argv_buf == NULL) {
- _Exit(EX_SOFTWARE);
- }
-
- // Allocate memory for the array of pointers. This uses `calloc` both to
- // handle overflow and to initialize the NULL pointer at the end.
- char **argv = calloc(num_ptrs, sizeof(char *));
- if (argv == NULL) {
- free(argv_buf);
- _Exit(EX_SOFTWARE);
- }
-
- // Fill the argument chars, and the argv array with pointers into those chars.
- // TODO: Remove the casts on `argv_ptrs` and `argv_buf` once the witx is updated with char8 support.
- err = __wasi_args_get((uint8_t **)argv, (uint8_t *)argv_buf);
- if (err != __WASI_ERRNO_SUCCESS) {
- free(argv_buf);
- free(argv);
- _Exit(EX_OSERR);
- }
-
- // Call main with the arguments!
- return main(argc, argv);
+ return __main_void();
}