diff --git a/arm-gen.c b/arm-gen.c index 81fa185a..b132e3e3 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1396,6 +1396,20 @@ void gfunc_call(int nb_args) float_abi = def_float_abi; } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ +#ifdef __arm__ + void *sp; + + asm("sub sp, sp, %1\n" + "\tmov %0, sp" + : "=r" (sp) + : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); + memcpy(sp, var, cnt * sizeof(char *)); + asm("mov pc, %0" : : "r" (prog_main)); +#endif +} + /* generate function prolog of type 't' */ void gfunc_prolog(Sym *func_sym) { diff --git a/arm64-gen.c b/arm64-gen.c index 03ae56c3..8e7e2f36 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -1167,6 +1167,25 @@ ST_FUNC void gfunc_call(int nb_args) tcc_free(t); } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ +#if defined(__aarch64__) +#if defined(__TINYC__) + // FIXME: immplement arm64 assembler + fprintf(stderr, "tcc -nostdlib -run not implement for arm64\n"); +#else + void *sp; + + asm("sub sp, sp, %1\n" + "\tmov %0, sp" + : "=r" (sp) + : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); + memcpy(sp, var, cnt * sizeof(char *)); + asm("br %0" : : "r" (prog_main)); +#endif +#endif +} + static unsigned long arm64_func_va_list_stack; static int arm64_func_va_list_gr_offs; static int arm64_func_va_list_vr_offs; diff --git a/i386-gen.c b/i386-gen.c index c8d8af53..b9da31cd 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -504,6 +504,24 @@ ST_FUNC void gfunc_call(int nb_args) vtop--; } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ +#ifdef __i386__ +#ifdef TCC_TARGET_PE + fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n"); +#else + void *sp; + + asm("sub %1, %%esp\n" + "\tmov %%esp, %0" + : "=r" (sp) + : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); + memcpy(sp, var, cnt * sizeof(char *)); + asm("jmp *%0" : : "r" (prog_main)); +#endif +#endif +} + #ifdef TCC_TARGET_PE #define FUNC_PROLOG_SIZE (10 + USE_EBX) #else diff --git a/riscv64-gen.c b/riscv64-gen.c index c0db5613..2226802c 100644 --- a/riscv64-gen.c +++ b/riscv64-gen.c @@ -769,6 +769,20 @@ done: tcc_free(info); } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ +#ifdef __riscv + void *sp; + + asm("sub sp, sp, %1\n" + "\tmv %0, sp" + : "=r" (sp) + : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); + memcpy(sp, var, cnt * sizeof(char *)); + asm("jalr %0" : : "r" (prog_main)); +#endif +} + static int func_sub_sp_offset, num_va_regs, func_va_list_ofs; ST_FUNC void gfunc_prolog(Sym *func_sym) diff --git a/tcc.h b/tcc.h index 410a5d8f..310409df 100644 --- a/tcc.h +++ b/tcc.h @@ -1797,6 +1797,7 @@ ST_FUNC const char *dlerror(void); ST_FUNC void *dlsym(void *handle, const char *symbol); #endif ST_FUNC void tcc_run_free(TCCState *s1); +ST_FUNC void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var); #endif /* ------------ tcctools.c ----------------- */ diff --git a/tccrun.c b/tccrun.c index 8ef0b659..8e9da653 100644 --- a/tccrun.c +++ b/tccrun.c @@ -249,8 +249,30 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) fflush(stderr); ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym)); - if (0 == ret) - ret = prog_main(argc, argv, envp); + if (0 == ret) { + if (s1->nostdlib) { + int n = 1; + char **p, **e = envp; + + /* create sysv memory layout: argc, argv[], NULL, envp[], NULL */ + if (envp) + while (*e++) + n++; + p = tcc_malloc((argc + n + 2) * sizeof(char **)); + p[0] = (char *) (size_t) argc; + memcpy(p + 1, argv, argc * sizeof(char *)); + p[argc + 1] = NULL; + if (envp) + memcpy(p + argc + 2, envp, n * sizeof(char *)); + else + p[argc + 2] = NULL; + /* Probably never returns */ + tcc_run_start(prog_main, argc + n + 2, p); + tcc_free(p); + } + else + ret = prog_main(argc, argv, envp); + } else if (RT_EXIT_ZERO == ret) ret = 0; diff --git a/x86_64-gen.c b/x86_64-gen.c index c679db28..d3b07bb9 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -933,6 +933,10 @@ void gfunc_call(int nb_args) vtop--; } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ + fprintf(stderr, "tcc -nostdlib -run not implement for TCC_TARGET_PE\n"); +} #define FUNC_PROLOG_SIZE 11 @@ -1434,6 +1438,20 @@ void gfunc_call(int nb_args) vtop--; } +void tcc_run_start(int (*prog_main)(int, char **, char **), int cnt, char **var) +{ +#ifdef __x86_64__ + void *sp; + + asm("subq %1, %%rsp\n" + "\tmovq %%rsp, %0" + : "=r" (sp) + : "r" ((((size_t) cnt + 1) & -2) * sizeof(char *))); + memcpy(sp, var, cnt * sizeof(char *)); + asm("jmp *%0" : : "r" (prog_main)); +#endif +} + #define FUNC_PROLOG_SIZE 11 static void push_arg_reg(int i) {