Compare commits

..

No commits in common. "34eed88a70fc8238cd5b623cc96b8bf0e40392ed" and "cb41cbfe717e4c00d7bb70035cda5ee5f0ff9341" have entirely different histories.

15 changed files with 119 additions and 286 deletions

View File

@ -14,7 +14,7 @@ jobs:
run: ./configure && make && make test -k
test-x86_64-osx:
runs-on: macos-15-intel
runs-on: macos-13
timeout-minutes: 2
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
@ -22,7 +22,7 @@ jobs:
run: ./configure && make && make test -k
test-aarch64-osx:
runs-on: macos-15
runs-on: macos-14
timeout-minutes: 2
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

View File

@ -367,7 +367,7 @@ IR = $(IM) mkdir -p $2 && cp -r $1/. $2
IM = @echo "-> $2 : $1" ;
BINCHECK = $(if $(wildcard $(PROGS) *-tcc$(EXESUF)),,@echo "Makefile: nothing found to install" && exit 1)
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
# install progs & libs
install-unx:

View File

@ -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)
{

View File

@ -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;

View File

@ -1,6 +1,6 @@
#include <tcclib.h>
int fib(int n)
int fib(n)
{
if (n <= 2)
return 1;
@ -18,6 +18,6 @@ int main(int argc, char **argv)
}
n = atoi(argv[1]);
printf("fib(%d) = %d\n", n, fib(n));
printf("fib(%d) = %d\n", n, fib(n, 2));
return 0;
}

View File

@ -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

View File

@ -50,13 +50,13 @@ Nat = $(if $X,no,)
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
$(Nat)COMMON_O += runmain.o run_nostdlib.o tcov.o
$(Nat)COMMON_O += runmain.o tcov.o
$(Cbt)COMMON_O += bt-exe.o bt-log.o
$(Cbt)WIN_O += bt-dll.o
$(Cbc)COMMON_O += bcheck.o
# not in libtcc1.a
EXTRA_O = runmain.o run_nostdlib.o bt-exe.o bt-dll.o bt-log.o bcheck.o
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
OBJ-i386 = $(I386_O) $(LIN_O)
OBJ-x86_64 = $(X86_64_O) $(LIN_O)

View File

@ -1,94 +0,0 @@
/* ------------------------------------------------------------- */
/* support for run_nostdlib() */
// FIXME: implement arm64 assembler
#if defined(__aarch64__)
#define USE_ARM64_ASM
static void *alloca_arm64(unsigned long);
__asm__(
#ifdef __leading_underscore
"_alloca_arm64:\n\t"
#else
"alloca_arm64:\n\t"
#endif
".int 0x91003c00\n\t" // add x0, x0, #15
".int 0x927cec00\n\t" // and x0, x0, #-16
".int 0xcb2063ff\n\t" // sub sp, sp, x0
".int 0x910003e0\n\t" // mov x0, sp
".int 0xd65f03c0" // ret
);
static void goto_arm64(void *start);
__asm__(
#ifdef __leading_underscore
"_goto_arm64:\n\t"
#else
"goto_arm64:\n\t"
#endif
".int 0xd61f0000" // br x0
);
#endif
void _run_nostdlib(void *start, int argc, char **argv, char **envp)
{
#if !defined(_WIN32)
int i, n = 1;
unsigned long l;
char **sp, **e = envp;
if (envp)
while (*e++)
n++;
l = (((unsigned long) argc + n + 2 + 1) & -2) * sizeof(char *);
/* nostdlib so avoid alloca() */
/* also code below will be removed because compiler detects dead store */
#if defined(USE_ARM64_ASM)
sp = alloca_arm64(l);
#else
#if defined(__aarch64__)
__asm__("sub sp, sp, %1\n"
"\tmov %0, sp"
#elif defined(__arm__)
__asm__("sub sp, sp, %1\n"
"\tmov %0, sp"
#elif defined(__i386__)
__asm("sub %1, %%esp\n"
"\tmov %%esp, %0"
#elif defined(__riscv)
__asm__("sub sp, sp, %1\n"
"\tmv %0, sp"
#elif defined(__x86_64__)
__asm__("subq %1, %%rsp\n"
"\tmovq %%rsp, %0"
#endif
: "=r" (sp)
: "r" (l));
#endif
/* create sysv memory layout: argc, argv[], NULL, envp[], NULL */
sp[0] = (char *) (__SIZE_TYPE__) argc;
for (i = 0; i < argc; i++)
sp[i + 1] = argv[i];
sp[argc + 1] = (char *) 0;
if (envp)
for (i = 0; i < n; i++)
sp[i + argc + 2] = envp[i];
else
sp[argc + 2] = (char *) 0;
#endif
/* goto *start does not work for clang. Use assembly. */
#if defined(USE_ARM64_ASM)
goto_arm64(start);
#else
#if defined(__aarch64__)
__asm__("br %0" : : "r" (start));
#elif defined(__arm__)
__asm__("mov pc, %0" : : "r" (start));
#elif defined(__i386__)
__asm__("jmp *%0" : : "r" (start));
#elif defined(__riscv)
__asm__("jalr %0" : : "r" (start));
#elif defined(__x86_64__)
__asm__("jmp *%0" : : "r" (start));
#endif
#endif
}

View File

@ -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)

1
tcc.h
View File

@ -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 ----------------- */

23
tccpp.c
View File

@ -2550,7 +2550,7 @@ static void parse_number(const char *p)
}
}
} else {
unsigned long long n = 0, n1 = 0;
unsigned long long n, n1;
int lcount, ucount, ov = 0;
const char *p1;
@ -2561,6 +2561,7 @@ static void parse_number(const char *p)
b = 8;
q++;
}
n = 0;
while(1) {
t = *q++;
/* no need for checks except for base 10 / 8 errors */
@ -2574,23 +2575,13 @@ static void parse_number(const char *p)
t = t - '0';
if (t >= b)
tcc_error("invalid digit");
n1 = n;
n = n * b + t;
if (!ov) {
/* detect overflow */
if (n1 >= 0x1000000000000000ULL && n / b != n1)
ov = 1;
else
n1 = n;
}
/* detect overflow */
if (n1 >= 0x1000000000000000ULL && n / b != n1)
ov = 1;
}
#ifdef TCC_CUT_ON_INTEGER_LITERAL_OVERFLOW
/* On integer literal overflow use the most significant digits before
the overflow happened. Effectively this cuts the 0x1000000000000000
from above down to 0x10000000 and allows to bootstrap tcc with 32 bit
arithmetic. */
if (ov)
n = n1;
#endif
/* Determine the characteristics (unsigned and/or 64bit) the type of
the constant must have according to the constant suffix(es) */
lcount = ucount = 0;

View File

@ -206,10 +206,9 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
const char *top_sym;
jmp_buf main_jb;
#if defined(__APPLE__)
extern char ***_NSGetEnviron(void);
char **envp = *_NSGetEnviron();
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#if defined(__APPLE__) || defined(__FreeBSD__)
char **envp = NULL;
#elif defined(__OpenBSD__) || defined(__NetBSD__)
extern char **environ;
char **envp = environ;
#else
@ -222,7 +221,6 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
tcc_add_symbol(s1, "__rt_exit", rt_exit);
if (s1->nostdlib) {
tcc_add_support(s1, "run_nostdlib.o");
s1->run_main = top_sym = s1->elf_entryname ? s1->elf_entryname : "_start";
} else {
tcc_add_support(s1, "runmain.o");
@ -253,12 +251,24 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
ret = tcc_setjmp(s1, main_jb, tcc_get_symbol(s1, top_sym));
if (0 == ret) {
if (s1->nostdlib) {
void (*run_nostdlib)(void *start, int argc, char **argv, char **envp);
int n = 1;
char **p, **e = envp;
run_nostdlib = (void *)get_sym_addr(s1, "_run_nostdlib", 1, 1);
if ((addr_t)-1 == (addr_t)run_nostdlib)
return -1;
run_nostdlib(prog_main, argc, argv, envp); /* never returns */
/* 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);

View File

@ -1,155 +0,0 @@
#!/usr/local/bin/tcc -run -nostdlib
// Not working on windows and apple because of different API.
#include <unistd.h>
#include <sys/syscall.h>
#if defined __x86_64__
__asm__ ("syscall:\n\t"
"mov %rdi,%rax\n\t"
"mov %rsi,%rdi\n\t"
"mov %rdx,%rsi\n\t"
"mov %rcx,%rdx\n\t"
"mov %r8,%r10\n\t"
"mov %r9,%r8\n\t"
"mov 0x8(%rsp),%r9\n\t"
"syscall\n\t"
"ret");
__asm__ (".global _start\n\t"
"_start:\n\t"
"mov 0(%rsp), %rdi\n\t"
"lea 8(%rsp), %rsi\n\t"
"jmp print");
#elif defined __i386__
__asm__ ("syscall:\n\t"
"push %ebp\n\t"
"push %edi\n\t"
"push %esi\n\t"
"push %ebx\n\t"
"mov 0x2c(%esp),%ebp\n\t"
"mov 0x28(%esp),%edi\n\t"
"mov 0x24(%esp),%esi\n\t"
"mov 0x20(%esp),%edx\n\t"
"mov 0x1c(%esp),%ecx\n\t"
"mov 0x18(%esp),%ebx\n\t"
"mov 0x14(%esp),%eax\n\t"
// "call *%gs:0x10\n\t"
".byte 0x65,0xff,0x15,0x10,0x00,0x00,0x00\n\t"
"pop %ebx\n\t"
"pop %esi\n\t"
"pop %edi\n\t"
"pop %ebp\n\t"
"ret");
__asm__ (".global _start\n\t"
"_start:\n\t"
"pop %esi\n\t"
"mov %esp, %ecx\n\t"
"and $0xfffffff0,%esp\n\t"
"push %ecx\n\t"
"push %esi\n\t"
"call print");
#elif defined __arm__
__asm__ ("syscall:\n\t"
"mov r12, sp\n\t"
"push {r4, r5, r6, r7}\n\t"
"mov r7, r0\n\t"
"mov r0, r1\n\t"
"mov r1, r2\n\t"
"mov r2, r3\n\t"
"ldm r12, {r3, r4, r5, r6}\n\t"
"svc 0x00000000\n\t"
"pop {r4, r5, r6, r7}\n\t"
"mov pc, lr");
__asm__ (".global _start\n\t"
"_start:\n\t"
"pop {r0}\n\t"
"mov r1, sp\n\t"
"bl print");
#elif defined __aarch64__
__asm__ ("syscall:\n\t"
".int 0x2a0003e8\n\t" // mov w8, w0
".int 0xaa0103e0\n\t" // x0, x1
".int 0xaa0203e1\n\t" // mov x1, x2
".int 0xaa0303e2\n\t" // mov x2, x3
".int 0xaa0403e3\n\t" // mov x3, x4
".int 0xaa0503e4\n\t" // mov x4, x5
".int 0xaa0603e5\n\t" // mov x5, x6
".int 0xaa0703e6\n\t" // mov x6, x7
".int 0xd4000001\n\t" // svc #0x0
".int 0xd65f03c0"); // ret
__asm__ (".global _start\n\t"
"_start:\n\t"
".int 0xf94003e0\n\t" // ldr x0, [sp]
".int 0x910023e1\n\t" // add x1, sp, #08
".reloc .,R_AARCH64_CALL26,print\n\t"
".int 0x94000000"); // bl print
#elif defined __riscv
__asm__ ("syscall:\n\t"
"mv t1,a0\n\t"
"mv a0,a1\n\t"
"mv a1,a2\n\t"
"mv a2,a3\n\t"
"mv a3,a4\n\t"
"mv a4,a5\n\t"
"mv a5,a6\n\t"
"mv a6,a7\n\t"
"mv a7,t1\n\t"
"ecall\n\t"
"ret");
__asm__ (".global _start\n\t"
"_start:\n\t"
"ld a0,0(sp)\n\t"
"addi a1,sp,8\n\t"
"jal print");
#endif
unsigned long strlen(const char *s)
{
unsigned long len = 0;
while (*s++)
len++;
return len;
}
static void pr_num(int num)
{
char val[20], *p = &val[20];
*--p = '\0';
do {
int a = num, b = 0;
while (a >= 10) {
a -= 10;
b++;
}
*--p = a + '0';
num = b;
} while (num);
syscall(SYS_write, 1, p, strlen(p));
}
static void pr_str(int n, char *s)
{
pr_num(n);
syscall(SYS_write, 1, ": ", 2);
syscall(SYS_write, 1, s, strlen(s));
syscall(SYS_write, 1, "\n", 1);
}
void print(int argc, char **argv) {
int i;
char **envp = &argv[argc + 1];
syscall(SYS_write, 1, "argc: ", 6);
pr_num(argc);
syscall(SYS_write, 1, "\n", 1);
syscall(SYS_write, 1, "argv[]\n", 7);
for (i = 0; i < argc; i++)
pr_str(i, argv[i]);
syscall(SYS_write, 1, "envp[]\n", 7);
i = 0;
while (*envp)
pr_str(i++, *envp++);
syscall(SYS_exit, 0);
}

View File

@ -1173,10 +1173,6 @@ void char_short_test()
the presence of undefined behaviour (like __csf is). */
var1 = csf(unsigned char,0x89898989);
var4 = csf(signed char,0xabababab);
#ifdef __clang__
/* on macos 15 arm64 this prints -1987475063 instead of 137 */
var1 &= 0xff;
#endif
printf("promote char/short funcret %d "LONG_LONG_FORMAT"\n", var1, var4);
printf("promote char/short fumcret VA %d %d %d %d\n",
csf(unsigned short,0xcdcdcdcd),

View File

@ -933,6 +933,11 @@ 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
/* generate function prolog of type 't' */
@ -1433,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) {