tcc.c:main() free all & etc...

tcc.c:
- be nice to leak checkers
tcctools.c:
- remove unused TCCState params
tccrun.c:
- call bound_exit() after signals to let it free mem
tccelf.c:
- use section_add() instead of section_ptr_add() when
  more appropriate
tccpp.c:
- use size_t to align tal_header naturally
- 'POINTER_SIZE' and 'PTR_SIZE' in the same source is confusing
- "char file_name[TAL_DEBUG_FILE_LEN + 1];" looks silly.
- next_nomacro(): skip UTF8 BOM at BOF
tccgen.c:
- get rid of STMT_EXPR clause on top of block
- warn with useless type like 'int;'
- move skip()'s in block() for better error line-info
- BIT_SIZE bits are meaningful only with VT_BITFIELD
  (not with enums for example)
workflow/test-win32:
- build with MSVC using build-tcc.bat also
alloca.S:
- fix 'off by one' problem on win32 (must touch current page
  too because the 'push %edx' at the end could touch the next page)
- must not align greater than 4 when used for struct args
  (i386-gen.c:gfunc_call())
libtcc.c:
- accept -g1dwarf (dwarf output, only line info)
This commit is contained in:
grischka
2025-08-06 10:44:50 +02:00
parent 8845b6cd45
commit deb7a3fc73
17 changed files with 187 additions and 162 deletions

View File

@@ -31,7 +31,7 @@ jobs:
test-x86_64-win32:
runs-on: windows-2025
timeout-minutes: 4
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- name: make & test tcc (x86_64-win32)
@@ -44,10 +44,22 @@ jobs:
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-x86_64-gcc"
echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: amd64
- name: build with MSVC (x86_64-win32)
shell: cmd
run: |
echo ::group:: run build-tcc.bat
cd win32
call build-tcc.bat -t 64 -c cl
echo ::endgroup::
.\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe
.\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c
test-i386-win32:
runs-on: windows-2025
timeout-minutes: 4
timeout-minutes: 6
steps:
- uses: actions/checkout@v4
- name: make & test tcc (i386-win32)
@@ -59,7 +71,19 @@ jobs:
set CHERE_INVOKING=yes
C:\msys64\usr\bin\bash -l -c "pacman -S --noconfirm mingw-w64-i686-gcc"
echo ::endgroup::
C:\msys64\usr\bin\bash -l -c "./configure && make all && make test -k"
C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
- uses: ilammy/msvc-dev-cmd@v1
with:
arch: x86
- name: build with MSVC (i386-win32)
shell: cmd
run: |
echo ::group:: run build-tcc.bat
cd win32
call build-tcc.bat -t 32 -c cl
echo ::endgroup::
.\tcc -I.. libtcc.dll -v ../tests/libtcc_test.c -o libtest.exe && .\libtest.exe
.\tcc -I.. libtcc.dll -run ../tests/libtcc_test.c
test-armv7-linux:
runs-on: ubuntu-22.04

View File

@@ -417,6 +417,7 @@ ST_FUNC void gfunc_call(int nb_args)
/* allocate the necessary size on stack */
#ifdef TCC_TARGET_PE
if (size >= 4096) {
save_reg(TREG_EDX);
r = get_reg(RC_EAX);
oad(0x68, size); // push size
/* cannot call normal 'alloca' with bound checking */

View File

@@ -17,13 +17,13 @@ _(__bound_alloca):
mov %eax, %ecx
test %eax,%eax
jz p6
add $15+1,%eax
and $-16,%eax
add $3 + 1,%eax
and $-4,%eax
#ifdef _WIN32
p4:
cmp $4096,%eax
jbe p5
jb p5
test %eax,-4096(%esp)
sub $4096,%esp
sub $4096,%eax
@@ -33,7 +33,6 @@ p5:
#endif
sub %eax,%esp
and $-16,%esp
mov %esp,%eax
push %edx
@@ -72,12 +71,11 @@ _(__bound_alloca_nr):
#else
pop %rdx
mov %rdi,%rax
and %eax,%eax
jz p3
mov %rax,%rsi # size, a second parm to the __bound_new_region
add $15 + 1,%rax # add one extra to separate regions
and $-16,%rax
jz p3
sub %rax,%rsp
mov %rsp,%rdi # pointer, a first parm to the __bound_new_region

View File

@@ -15,14 +15,14 @@ _(alloca):
_(__alloca):
pop %edx
pop %eax
add $15,%eax
and $-16,%eax
add $3,%eax
and $-4,%eax
jz p3
#ifdef _WIN32
p1:
cmp $4096,%eax
jbe p2
jb p2
test %eax,-4096(%esp)
sub $4096,%esp
sub $4096,%eax
@@ -30,7 +30,6 @@ p1:
p2:
#endif
sub %eax,%esp
and $-16,%esp
mov %esp,%eax
p3:
push %edx
@@ -55,7 +54,7 @@ _(alloca):
#ifdef _WIN32
p1:
cmp $4096,%rax
jbe p2
jb p2
test %rax,-4096(%rsp)
sub $4096,%rsp
sub $4096,%rax

View File

@@ -804,7 +804,6 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
s1->error_set_jmp_enabled = 1;
if (setjmp(s1->error_jmp_buf) == 0) {
s1->nb_errors = 0;
if (fd == -1) {
int len = strlen(str);
@@ -1816,8 +1815,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
const TCCOption *popt;
const char *optarg, *r;
const char *run = NULL;
int x;
int tool = 0, arg_start = 0, not_empty = 0, optind = 1;
int optind = 1, empty = 1, x;
char **argv = *pargv;
int argc = *pargc;
@@ -1836,21 +1834,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
continue;
}
optind++;
if (tool) { /* ignore all except -v and @listfile */
s->verbose += !strcmp(r, "-v");
continue;
}
if (r[0] != '-' || r[1] == '\0') { /* file or '-' (stdin) */
args_parser_add_file(s, r, s->filetype);
not_empty = 1;
empty = 0;
dorun:
if (run) {
/* tcc -run <file> <args...> */
if (tcc_set_options(s, run))
if (tcc_set_options(s, run) < 0)
return -1;
arg_start = optind - 1; /* argv[0] will be <file> */
break;
x = 0;
goto extra_action;
}
continue;
}
@@ -1923,14 +1916,16 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
case TCC_OPTION_g:
s->do_debug = 2;
s->dwarf = CONFIG_DWARF_VERSION;
g_redo:
if (strstart("dwarf", &optarg)) {
s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
} else if (0 == strcmp("stabs", optarg)) {
s->dwarf = 0;
} else if (isnum(*optarg)) {
x = *optarg - '0';
x = *optarg++ - '0';
/* -g0 = no info, -g1 = lines/functions only, -g2 = full info */
s->do_debug = x > 2 ? 2 : x == 0 && s->do_backtrace ? 1 : x;
goto g_redo;
#ifdef TCC_TARGET_PE
} else if (0 == strcmp(".pdb", optarg)) {
s->dwarf = 5, s->do_debug |= 16;
@@ -2030,7 +2025,6 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
}
break;
case TCC_OPTION_W:
s->warn_none = 0;
if (optarg[0] && set_flag(s, options_W, optarg) < 0)
goto unsupported_option;
break;
@@ -2141,29 +2135,24 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
case TCC_OPTION_ar:
x = OPT_AR;
extra_action:
arg_start = optind - 1;
if (not_empty)
if (NULL == argv[0]) /* from tcc_set_options() */
return -1;
if (!empty && x)
return tcc_error_noabort("cannot parse %s here", r);
tool = x;
break;
--optind;
*pargc = argc - optind;
*pargv = argv + optind;
return x;
default:
unsupported_option:
tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
break;
}
not_empty = 1;
empty = 0;
}
if (s->link_optind < s->link_argc)
return tcc_error_noabort("argument to '-Wl,%s' is missing", s->link_argv[s->link_optind]);
if (NULL == argv[0]) /* from tcc_set_options() */
return 0;
if (arg_start) {
*pargc = argc - arg_start;
*pargv = argv + arg_start;
return tool;
}
if (not_empty)
if (!empty)
return 0;
if (s->verbose == 2)
return OPT_PRINT_DIRS;

43
tcc.c
View File

@@ -283,51 +283,51 @@ static unsigned getclock_ms(void)
#endif
}
int main(int argc0, char **argv0)
int main(int argc, char **argv)
{
TCCState *s, *s1;
int ret, opt, n = 0, t = 0, done;
unsigned start_time = 0, end_time = 0;
const char *first_file;
int argc; char **argv;
int argc0 = argc;
char **argv0 = argv;
FILE *ppfp = stdout;
redo:
argc = argc0, argv = argv0;
s = s1 = tcc_new();
opt = tcc_parse_args(s, &argc, &argv);
if (opt < 0)
return 1;
if (n == 0) {
ret = 0;
if (opt == OPT_HELP) {
fputs(help, stdout);
if (!s->verbose)
return 0;
++opt;
}
if (opt == OPT_HELP2) {
fputs(help2, stdout);
return 0;
}
if (opt == OPT_M32 || opt == OPT_M64)
return tcc_tool_cross(s, argv, opt);
if (s->verbose)
if (s->verbose)
goto help2;
} else if (opt == OPT_HELP2) {
help2: fputs(help2, stdout);
} else if (opt == OPT_M32 || opt == OPT_M64) {
ret = tcc_tool_cross(argv, opt);
} else if (s->verbose)
printf("%s", version);
if (opt == OPT_AR)
return tcc_tool_ar(s, argc, argv);
ret = tcc_tool_ar(argc, argv);
#ifdef TCC_TARGET_PE
if (opt == OPT_IMPDEF)
return tcc_tool_impdef(s, argc, argv);
ret = tcc_tool_impdef(argc, argv);
#endif
if (opt == OPT_V)
return 0;
if (opt == OPT_PRINT_DIRS) {
/* initialize search dirs */
set_environment(s);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
print_search_dirs(s);
return 0;
}
if (opt < 0) err:
ret = 1;
if (opt) {
tcc_delete(s);
return ret;
}
if (s->nb_files == 0) {
@@ -345,7 +345,7 @@ redo:
tcc_error_noabort("cannot specify output file with -c many files");
}
if (s->nb_errors)
return 1;
goto err;
if (s->do_bench)
start_time = getclock_ms();
}
@@ -419,7 +419,6 @@ redo:
tcc_print_stats(s, end_time - start_time);
tcc_delete(s);
if (!done)
goto redo;
if (ppfp && ppfp != stdout)

9
tcc.h
View File

@@ -95,13 +95,12 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define O_BINARY 0
#endif
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#ifdef __clang__ // clang -fsanitize compains about: NULL+value
#define offsetof(type, field) __builtin_offsetof(type, field)
#endif
#ifdef __clang__ // clang -fsanitize compains about: NULL+value
#undef offsetof
#define offsetof(type, field) __builtin_offsetof(type, field)
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#ifndef countof

View File

@@ -318,8 +318,7 @@ ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
{
size_t offset = section_add(sec, size, 1);
// clang -fsanitize compains about: NULL+value
return sec->data ? sec->data + offset : (void *)offset;
return sec->data + offset;
}
#ifndef ELF_OBJ_ONLY
@@ -1598,7 +1597,7 @@ ST_FUNC void tcc_add_btstub(TCCState *s1)
s = data_section;
/* Align to PTR_SIZE */
section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
section_add(s, 0, PTR_SIZE);
o = s->data_offset;
/* create a struct rt_context (see tccrun.c) */
if (s1->dwarf) {
@@ -2837,7 +2836,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
int textrel, got_sym, dt_flags_1;
file_type = s1->output_type;
s1->nb_errors = 0;
ret = -1;
interp = dynstr = dynamic = NULL;
sec_order = NULL;
@@ -3030,7 +3028,6 @@ static int elf_output_obj(TCCState *s1, const char *filename)
{
Section *s;
int i, ret, file_offset;
s1->nb_errors = 0;
/* Allocate strings for section names */
alloc_sec_names(s1, 1);
file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;
@@ -3049,6 +3046,7 @@ static int elf_output_obj(TCCState *s1, const char *filename)
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
{
s->nb_errors = 0;
if (s->test_coverage)
tcc_tcov_add_file(s, filename);
if (s->output_type == TCC_OUTPUT_OBJ)
@@ -3254,21 +3252,19 @@ invalid:
s->sh_entsize = sh->sh_entsize;
sm_table[i].new_section = 1;
found:
size = sh->sh_size;
/* align start of section */
s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
offset = section_add(s, size, sh->sh_addralign);
if (sh->sh_addralign > s->sh_addralign)
s->sh_addralign = sh->sh_addralign;
sm_table[i].offset = s->data_offset;
sm_table[i].offset = offset;
sm_table[i].s = s;
/* concatenate sections */
size = sh->sh_size;
if (sh->sh_type != SHT_NOBITS) {
if (sh->sh_type != SHT_NOBITS && size) {
unsigned char *ptr;
lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
ptr = section_ptr_add(s, size);
ptr = s->data + offset;
full_read(fd, ptr, size);
} else {
s->data_offset += size;
}
#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
/* align code sections to instruction lenght */
@@ -3310,6 +3306,9 @@ invalid:
}
}
if (!symtab)
goto done;
/* resolve symbols */
old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
@@ -3405,7 +3404,7 @@ invalid:
break;
}
}
done:
ret = 0;
the_end:
tcc_free(symtab);

View File

@@ -2963,13 +2963,13 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
(t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
type.t |= VT_UNSIGNED;
} else {
int t1_bit = BIT_SIZE(t1) <= 31 ? VT_BITFIELD : 0;
int t2_bit = BIT_SIZE(t2) <= 31 ? VT_BITFIELD : 0;
/* integer operations */
type.t = VT_INT | (VT_LONG & (t1 | t2));
/* convert to unsigned if it does not fit in an integer */
if ((t1 & (VT_BTYPE | VT_UNSIGNED | t1_bit)) == (VT_INT | VT_UNSIGNED) ||
(t2 & (VT_BTYPE | VT_UNSIGNED | t2_bit)) == (VT_INT | VT_UNSIGNED))
if (((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)
&& (!(t1 & VT_BITFIELD) || BIT_SIZE(t1) == 32))
|| ((t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED)
&& (!(t2 & VT_BITFIELD) || BIT_SIZE(t2) == 32)))
type.t |= VT_UNSIGNED;
}
if (dest)
@@ -5615,6 +5615,8 @@ ST_FUNC void unary(void)
as statement expressions can't ever be entered from the
outside, so any reactivation of code emission (from labels
or loop heads) can be disabled again after the end of it. */
/* default return value is (void) */
vpushi(0), vtop->type.t = VT_VOID;
block(STMT_EXPR);
/* If the statement expr can be entered, then we retain the current
nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
@@ -7036,12 +7038,6 @@ static void block(int flags)
struct scope o;
Sym *s;
if (flags & STMT_EXPR) {
/* default return value is (void) */
vpushi(0);
vtop->type.t = VT_VOID;
}
again:
t = tok;
/* If the token carries a value, next() might destroy it. Only with
@@ -7057,8 +7053,8 @@ again:
new_scope_s(&o);
skip('(');
gexpr();
skip(')');
a = gvtst(1, 0);
skip(')');
block(0);
if (tok == TOK_ELSE) {
d = gjmp(0);
@@ -7076,8 +7072,8 @@ again:
d = gind();
skip('(');
gexpr();
skip(')');
a = gvtst(1, 0);
skip(')');
b = 0;
lblock(&a, &b);
gjmp_addr(d);
@@ -7105,8 +7101,6 @@ again:
while (tok != '}') {
decl(VT_LOCAL);
if (tok != '}') {
if (flags & STMT_EXPR)
vpop();
block(flags | STMT_COMPOUND);
}
}
@@ -7208,9 +7202,9 @@ again:
skip(TOK_WHILE);
skip('(');
gexpr();
c = gvtst(0, 0);
skip(')');
skip(';');
c = gvtst(0, 0);
gsym_addr(c, d);
gsym(a);
prev_scope_s(&o);
@@ -7228,9 +7222,9 @@ again:
new_scope_s(&o);
skip('(');
gexpr();
skip(')');
if (!is_integer_btype(vtop->type.t & VT_BTYPE))
tcc_error("switch value not an integer");
skip(')');
sw->sv = *vtop--; /* save switch value */
a = 0;
b = gjmp(0); /* jump to first case */
@@ -8294,6 +8288,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
if (type->t & VT_VLA) {
int a;
if (has_init)
tcc_error("variable length array cannot be initialized");
if (NODATA_WANTED)
goto no_alloc;
@@ -8513,6 +8510,27 @@ static void do_Static_assert(void)
skip(';');
}
#ifdef TCC_TARGET_PE
static void pe_check_linkage(CType *type, AttributeDef *ad)
{
if (!ad->a.dllimport && !ad->a.dllexport)
return;
if (type->t & VT_STATIC)
tcc_error("cannot have dll linkage with static");
if (type->t & VT_TYPEDEF) {
const char *m = ad->a.dllimport ? "im" : "ex";
tcc_warning("'dll%sport' attribute ignored for typedef", m);
ad->a.dllimport = 0;
ad->a.dllexport = 0;
} else if (ad->a.dllimport) {
if ((type->t & VT_BTYPE) == VT_FUNC)
ad->a.dllimport = 0;
else
type->t |= VT_EXTERN;
}
}
#endif
/* 'l' is VT_LOCAL or VT_CONST to define default storage type
or VT_CMP if parsing old style parameter list
or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
@@ -8559,17 +8577,17 @@ static int decl(int l)
}
if (tok == ';') {
if ((btype.t & VT_BTYPE) == VT_STRUCT) {
v = btype.ref->v;
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
tcc_warning("unnamed struct/union that defines no instances");
next();
continue;
}
if (IS_ENUM(btype.t)) {
next();
continue;
}
if ((btype.t & VT_BTYPE) == VT_STRUCT
&& (btype.ref->v & ~SYM_STRUCT) < SYM_FIRST_ANOM)
; /* struct decl with named tag */
else if (IS_ENUM(btype.t))
; /* enum decl */
else
tcc_warning("useless type defines no instances");
if (l == VT_JMP)
return 1;
next();
continue;
}
while (1) { /* iterate thru each declaration */
@@ -8637,20 +8655,7 @@ static int decl(int l)
}
#ifdef TCC_TARGET_PE
if (ad.a.dllimport || ad.a.dllexport) {
if (type.t & VT_STATIC)
tcc_error("cannot have dll linkage with static");
if (type.t & VT_TYPEDEF) {
tcc_warning("'%s' attribute ignored for typedef",
ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") :
(ad.a.dllexport = 0, "dllexport"));
} else if (ad.a.dllimport) {
if ((type.t & VT_BTYPE) == VT_FUNC)
ad.a.dllimport = 0;
else
type.t |= VT_EXTERN;
}
}
pe_check_linkage(&type, &ad);
#endif
if (tok == '{') {
if (l != VT_CONST)
@@ -8700,6 +8705,7 @@ static int decl(int l)
}
break;
} else {
has_init = 0;
if (l == VT_CMP) {
/* find parameter in function parameter list */
for (sym = func_vt.ref->next; sym; sym = sym->next)
@@ -8747,9 +8753,9 @@ static int decl(int l)
/* not lvalue if array */
r |= VT_LVAL;
}
has_init = (tok == '=');
if (has_init && (type.t & VT_VLA))
tcc_error("variable length array cannot be initialized");
if (tok == '=')
has_init = 1;
if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
|| (type.t & VT_BTYPE) == VT_FUNC
@@ -8789,7 +8795,7 @@ static int decl(int l)
}
if (tok != ',') {
if (l == VT_JMP)
return 1;
return has_init ? v : 1;
skip(';');
break;
}

32
tccpp.c
View File

@@ -117,16 +117,6 @@ ST_FUNC void expect(const char *msg)
#define USE_TAL
#ifdef _MSC_VER
# if defined _M_AMD64 || defined _M_ARM64 || defined _M_ARM64EC || defined _M_IA64 || defined _M_X64
# define POINTER_SIZE 8
# else
# define POINTER_SIZE 4
# endif
#else
# define POINTER_SIZE sizeof(void *)
#endif
#ifndef USE_TAL
#define tal_free(al, p) tcc_free(p)
#define tal_realloc(al, p, size) tcc_realloc(p, size)
@@ -143,7 +133,6 @@ ST_FUNC void expect(const char *msg)
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
#define TAL_DEBUG_PARAMS , const char *file, int line
#define TAL_DEBUG_FILE_LEN 40
#endif
#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
@@ -167,13 +156,16 @@ typedef struct TinyAlloc {
} TinyAlloc;
typedef struct tal_header_t {
ALIGNED(POINTER_SIZE) unsigned size;
size_t size; /* word align */
#ifdef TAL_DEBUG
int line_num; /* negative line_num used for double free check */
char file_name[TAL_DEBUG_FILE_LEN + 1];
char file_name[40];
#endif
} tal_header_t;
#define TAL_ALIGN(size) \
(((size) + (sizeof (size_t) - 1)) & ~(sizeof (size_t) - 1))
/* ------------------------------------------------------------------------- */
static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size)
@@ -208,7 +200,7 @@ tail_call:
tal_header_t *header = (tal_header_t *)p;
if (header->line_num > 0) {
fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n",
header->file_name, header->line_num, header->size);
header->file_name, header->line_num, (int)header->size);
}
p += header->size + sizeof(tal_header_t);
}
@@ -256,7 +248,7 @@ static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_
tal_header_t *header;
void *ret;
int is_own;
unsigned adj_size = (size + POINTER_SIZE - 1) & -POINTER_SIZE;
unsigned adj_size = TAL_ALIGN(size);
TinyAlloc *al = *pal;
tail_call:
@@ -266,9 +258,8 @@ tail_call:
header = (tal_header_t *)al->p;
header->size = adj_size;
#ifdef TAL_DEBUG
{ int ofs = strlen(file) - TAL_DEBUG_FILE_LEN;
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN);
header->file_name[TAL_DEBUG_FILE_LEN] = 0;
{ int ofs = strlen(file) + 1 - sizeof header->file_name;
strcpy(header->file_name, file + (ofs > 0 ? ofs : 0));
header->line_num = line; }
#endif
ret = al->p + sizeof(tal_header_t);
@@ -2986,6 +2977,11 @@ maybe_newline:
tok = c;
p++;
break;
case 0xEF: /* UTF8 BOM ? */
if (p[1] == 0xBB && p[2] == 0xBF && p == file->buffer) {
p += 3;
goto redo_no_start;
}
default:
if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */
goto parse_ident_fast;

View File

@@ -312,6 +312,7 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, unsigned ptr_diff)
addr_t mem, addr;
if (NULL == ptr) {
s1->nb_errors = 0;
#ifdef TCC_TARGET_PE
pe_output_file(s1, NULL);
#else
@@ -495,10 +496,6 @@ static void bt_link(TCCState *s1)
{
#ifdef CONFIG_TCC_BACKTRACE
rt_context *rc;
#ifdef CONFIG_TCC_BCHECK
void *p;
#endif
if (!s1->do_backtrace)
return;
rc = tcc_get_symbol(s1, "__rt_info");
@@ -511,6 +508,7 @@ static void bt_link(TCCState *s1)
rc->prog_base &= 0xffffffff00000000ULL;
#ifdef CONFIG_TCC_BCHECK
if (s1->do_bounds_check) {
void *p;
if ((p = tcc_get_symbol(s1, "__bound_init")))
((void(*)(void*,int))p)(rc->bounds_start, 1);
}
@@ -599,6 +597,13 @@ static void rt_exit(rt_frame *f, int code)
s = rt_find_state(f);
rt_post_sem();
if (s && s->run_lj) {
#ifdef CONFIG_TCC_BCHECK
if (f->fp) { /* called from signal */
void *p = tcc_get_symbol(s, "__bound_exit");
if (p)
((void (*)(void))p)();
}
#endif
if (code == 0)
code = RT_EXIT_ZERO;
((void(*)(void*,int))s->run_lj)(s->run_jb, code);

View File

@@ -54,7 +54,7 @@ static int ar_usage(int ret) {
return ret;
}
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
ST_FUNC int tcc_tool_ar(int argc, char **argv)
{
static const ArHdr arhdr_init = {
"/ ",
@@ -360,7 +360,7 @@ the_end:
#ifdef TCC_TARGET_PE
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
ST_FUNC int tcc_tool_impdef(int argc, char **argv)
{
int ret, v, i;
char infile[260];
@@ -487,9 +487,9 @@ the_end:
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
ST_FUNC int tcc_tool_cross(char **argv, int option)
{
tcc_error_noabort("-m%d not implemented.", option);
fprintf(stderr, "tcc -m%d not implemented\n", option);
return 1;
}
@@ -546,7 +546,7 @@ static int execvp_win32(const char *prog, char **argv)
#define execvp execvp_win32
#endif /* _WIN32 */
ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
ST_FUNC int tcc_tool_cross(char **argv, int target)
{
char program[4096];
char *a0 = argv[0];
@@ -565,7 +565,7 @@ ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
if (strcmp(a0, program))
execvp(argv[0] = program, argv);
tcc_error_noabort("could not run '%s'", program);
fprintf(stderr, "tcc: could not run '%s'\n", program);
return 1;
}

View File

@@ -79,7 +79,7 @@ endif
all test :
@echo ------------ version ------------
@ASAN_OPTIONS=detect_leaks=0 $(TCC_LOCAL) -v
@$(TCC_LOCAL) -v
@$(MAKE) --no-print-directory -s clean
@$(MAKE) --no-print-directory -s -r _all

View File

@@ -102,7 +102,6 @@ GEN-ALWAYS =
112_backtrace.test 113_btdll.test 126_bound_global.test: FILTER += \
-e 's;[0-9A-Fa-fx]\{5,\};........;g' \
-e 's;0x[0-9A-Fa-f]\{1,\};0x?;g'
112_backtrace.test: LEAK=ASAN_OPTIONS=detect_leaks=0
# this test creates two DLLs and an EXE
113_btdll.test: T1 = \
@@ -137,7 +136,7 @@ all test tests2.all: $(filter-out $(SKIP),$(TESTS))
@echo Test: $*...
@$(call T1,$<) $(T3)
T1 = $(LEAK) $(TCC) $(FLAGS) $(T2) $(ARGS)
T1 = $(TCC) $(FLAGS) $(T2) $(ARGS)
T2 = $(if $(NORUN),$1 -o $(basename $@).exe && ./$(basename $@).exe,-run $1)
T3 = $(FILTER) >$*.output 2>&1 || true \
&& diff -Nbu $(filter %.expect,$^) $*.output \

View File

@@ -132,6 +132,10 @@ if %TX%==32 echo>> ..\config.h #ifdef TCC_TARGET_I386
echo>> ..\config.h #define CONFIG_TCC_CROSSPREFIX "%PX%-"
echo>> ..\config.h #endif
@rem echo>> ..\config.h #define CONFIG_TCC_PREDEFS 1
@rem %CC% -DC2STR ..\conftest.c -o c2str.exe
@rem .\c2str.exe ../include/tccdefs.h ../tccdefs_.h
for %%f in (*tcc.exe *tcc.dll) do @del %%f
@if _%TCC_C%_==__ goto compiler_2parts
@@ -200,8 +204,9 @@ exit /B %ERRORLEVEL%
.\tcc -B. -m%1 -c ../lib/alloca.S
.\tcc -B. -m%1 -c ../lib/alloca-bt.S
.\tcc -B. -m%1 -c ../lib/stdatomic.c
.\tcc -B. -m%1 -c ../lib/atomic.S
.\tcc -B. -m%1 -c ../lib/builtin.c
.\tcc -B. -m%1 -ar lib/%2libtcc1.a libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o alloca.o alloca-bt.o stdatomic.o builtin.o
.\tcc -B. -m%1 -ar lib/%2libtcc1.a libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o
.\tcc -B. -m%1 -c ../lib/bcheck.c -o lib/%2bcheck.o -bt -I..
.\tcc -B. -m%1 -c ../lib/bt-exe.c -o lib/%2bt-exe.o
.\tcc -B. -m%1 -c ../lib/bt-log.c -o lib/%2bt-log.o

View File

@@ -376,10 +376,16 @@ extern "C" {
_CRTIMP int __cdecl _set_error_mode(int _Mode);
void __cdecl srand(unsigned int _Seed);
double __cdecl strtod(const char *_Str,char **_EndPtr);
float __cdecl strtof(const char *nptr, char **endptr);
#if !defined __NO_ISOCEXT /* in libmingwex.a */
#if __TINYC__
__CRT_INLINE float __cdecl strtof (const char *p, char ** e) { return strtod(p, e); }
__CRT_INLINE long double __cdecl strtold(const char *p, char ** e) { return strtod(p, e); }
#else
float __cdecl strtof (const char * __restrict__, char ** __restrict__);
long double __cdecl strtold(const char * __restrict__, char ** __restrict__);
#endif
#else
float __cdecl strtof(const char *nptr, char **endptr);
#endif /* __NO_ISOCEXT */
_CRTIMP double __cdecl _strtod_l(const char *_Str,char **_EndPtr,_locale_t _Locale);
long __cdecl strtol(const char *_Str,char **_EndPtr,int _Radix);

View File

@@ -859,7 +859,7 @@ extern "C" {
}
#endif
#ifndef !defined (InterlockedAnd64)
#ifndef InterlockedAnd64
#define InterlockedAnd64 InterlockedAnd64_Inline
__CRT_INLINE LONGLONG InterlockedAnd64_Inline (LONGLONG volatile *Destination,LONGLONG Value) {