mirror of
https://github.com/TinyCC/tinycc.git
synced 2025-11-16 04:24:45 +00:00
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:
30
.github/workflows/build.yml
vendored
30
.github/workflows/build.yml
vendored
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
45
libtcc.c
45
libtcc.c
@@ -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
43
tcc.c
@@ -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
9
tcc.h
@@ -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
|
||||
|
||||
25
tccelf.c
25
tccelf.c
@@ -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);
|
||||
|
||||
96
tccgen.c
96
tccgen.c
@@ -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
32
tccpp.c
@@ -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;
|
||||
|
||||
13
tccrun.c
13
tccrun.c
@@ -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);
|
||||
|
||||
12
tcctools.c
12
tcctools.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user