From 51cc82085a54cb4a6f4ccf9c3fa55ae31bf4dabf Mon Sep 17 00:00:00 2001 From: tyfkda Date: Fri, 25 Oct 2024 21:53:32 +0900 Subject: [PATCH] Get command line options only if necessary Rename `main` function according to argument count: * 0: `__main_void` * 2: `__main_argc_argv` The entry point (`_start` function) calls `__main_void` function. If user defines `main` as zero arguments, then it is called. If user defines `main` as two arguments, `__main_void` defined in library code is called then user defined `main` function is called. # Conflicts: # src/wcc/traverse.c --- libsrc/_wasm/crt0/__main_void.c | 24 ++++++++++++++++++++++++ libsrc/_wasm/crt0/_start.c | 19 ++----------------- src/wcc/traverse.c | 33 ++++++++++----------------------- 3 files changed, 36 insertions(+), 40 deletions(-) create mode 100644 libsrc/_wasm/crt0/__main_void.c diff --git a/libsrc/_wasm/crt0/__main_void.c b/libsrc/_wasm/crt0/__main_void.c new file mode 100644 index 000000000..c37434cb4 --- /dev/null +++ b/libsrc/_wasm/crt0/__main_void.c @@ -0,0 +1,24 @@ +#include "alloca.h" + +#include "../wasi.h" + +extern int __main_argc_argv(int, char**); + +__attribute__((weak)) +int __main_void(void) { + char **argv; + int argc, len; + int r = args_sizes_get(&argc, &len); + if (r == 0) { + argv = alloca(sizeof(char*) * (argc + 1) + len); + char *str = ((char*)argv) + sizeof(char*) * (argc + 1); + args_get(argv, str); + } else { // Ignore error. + argc = 1; + argv = alloca(sizeof(char*) * (argc + 1)); + argv[0] = "*"; + } + argv[argc] = NULL; + + return __main_argc_argv(argc, argv); +} diff --git a/libsrc/_wasm/crt0/_start.c b/libsrc/_wasm/crt0/_start.c index 61aa2d21f..a6d195931 100644 --- a/libsrc/_wasm/crt0/_start.c +++ b/libsrc/_wasm/crt0/_start.c @@ -1,4 +1,3 @@ -#include "alloca.h" // alloca #include "stdlib.h" // exit #include "../wasi.h" @@ -6,25 +5,11 @@ extern void __wasm_call_ctors(void); void _start(void) { -#define main __main_argc_argv - extern int main(int, char**); - char **argv; - int argc, len; - int r = args_sizes_get(&argc, &len); - if (r == 0) { - argv = alloca(sizeof(char*) * (argc + 1) + len); - char *str = ((char*)argv) + sizeof(char*) * (argc + 1); - args_get(argv, str); - } else { // Ignore error. - argc = 1; - argv = alloca(sizeof(char*) * (argc + 1)); - argv[0] = "*"; - } - argv[argc] = NULL; + extern int __main_void(void); __wasm_call_ctors(); - int ec = main(argc, argv); + int ec = __main_void(); exit(ec); #undef main } diff --git a/src/wcc/traverse.c b/src/wcc/traverse.c index 1c1ade4b3..8855a66ff 100644 --- a/src/wcc/traverse.c +++ b/src/wcc/traverse.c @@ -709,36 +709,23 @@ static void modify_func_name(Function *func) { const Name *newname = NULL; switch (func->params->len) { case 0: - { // Add two parameters. - assert(func->scopes->len > 0); - Scope *scope = func->scopes->data[0]; - const Name *name1 = alloc_label(); - Type *type1 = &tyInt; - vec_push((Vector*)func->params, scope_add(scope, name1, type1, 0)); - vec_push((Vector*)functype->func.params, type1); - - Type *type2 = ptrof(ptrof(&tyChar)); - const Name *name2 = alloc_label(); - vec_push((Vector*)func->params, scope_add(scope, name2, type2, 0)); - vec_push((Vector*)functype->func.params, type2); - } - // Fallthrough. + newname = alloc_name("__main_void", NULL, false); + break; case 2: - { - newname = alloc_name("__main_argc_argv", NULL, false); - VarInfo *vi = scope_find(global_scope, newname, NULL); - if (vi != NULL) { - const Token *token = func->body_block != NULL ? func->body_block->token : NULL; - parse_error(PE_NOFATAL, token, "`%.*s' function already defined", NAMES(newname)); - return; - } - } + newname = alloc_name("__main_argc_argv", NULL, false); break; default: error("main function must take no argument or two arguments"); break; } + VarInfo *vi = scope_find(global_scope, newname, NULL); + if (vi != NULL) { + const Token *token = func->body_block != NULL ? func->body_block->token : NULL; + parse_error(PE_NOFATAL, token, "`%.*s' function already defined", NAMES(newname)); + return; + } + // Rename two arguments `main` to `__main_argc_argv`. VarInfo *org_varinfo = scope_find(global_scope, main_name, NULL); assert(org_varinfo != NULL);