Commit Graph

357 Commits

Author SHA1 Message Date
grischka
38ab5f65b3 tccgen: more of scope hacks
* case 1: local scope of 'ff'
  int main() {
    int ff = 123;
    {
      int ff(int):
      ff(456)
    }}

* case 2: linkage of a static extern symbol
  (older gcc did allow that)
  static int ff(int);
  int main() {
    int ff(int):
    ff(456)
  }

Also:
- cleanup enum, let sym_push() handle redefinition
- just mark incomplete array base types, unshare only
  when needed (in decl_initializer_alloc())
- fix sizeof empty array (= 0) : int ii[] = {};
- rename 'Sym' members used by __attribute__((cleanup(f)))
2025-09-08 17:23:18 +02:00
herman ten brugge
e6ea0d0424 tccgen: fix several problems
Fix 'void func2(char *(*md)(char *md))' declaration.
Fix global array and local extern array problems.
Fix scope problem with old function declaration.
Fix 'typedef int t[]' declaration. Empty size should remain.
2025-08-30 07:13:49 +02:00
grischka
acb2a909dd tccgen.c: fix two scope problems
... see tests

Also:
- tccgen.c: cleanup _Generic a little
- libtcc.c: cleanup mem-debug a little
- arm-link.c: read/write only once
- tcc.h: another fix for clang offsetof
- tccdbg.c:
  * stabs: handle forward struct/enum decls
  * stabs: fix anonymous struct members (must not have a .L123 name)
  * avoid strncpy()
2025-08-22 19:14:44 +02:00
grischka
2662b7b43c tccgen: local scope for types of function parameters
int foo(struct xxx {int x[3];} *p) { ...

We want 'xxx' be visible only inside the function. To get that,
the patch removes the 'sym_push(param)' in xxx-gen.c, and instead
(in tccgen.c:gen_function()) pushes all symbols that were newly
defined during parsing of the parameter list in post_type().

Also,
- decl_initializer_alloc():
  patch existing globals earlier, which updates flex arrays too
- let patch_type() do the 'redefinition' check and FUNC_OLD update
2025-08-18 21:06:03 +02:00
grischka
deb7a3fc73 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)
2025-08-18 20:43:52 +02:00
herman ten brugge
8845b6cd45 Make signed/unsigned bitfields the same as gcc/clang 2025-08-18 16:22:00 +02:00
herman ten brugge
199e135142 arm double to (unsigned) long long conversion
Bug found with openssl test suite.
2025-08-17 08:49:29 +02:00
herman ten brugge
19fdef46f9 Allow mixing old/new function prototypes
This fixes another external testsuite failure
2025-08-15 09:59:11 +02:00
herman ten brugge
37e1c88d78 Convert float to double for old function code. 2025-08-10 22:02:44 +02:00
herman ten brugge
087cf2e579 x86_64 bound checking failure
The code:
void mul(double *p)
{
    *p *= 2.0;
}

failed on x86_64 because register was not loaded after
bound checking call.
Also printed size when pointer indir failes.
2025-08-10 21:55:48 +02:00
herman ten brugge
fa9795406d Do not read past array end in struct return 2025-08-07 11:32:09 +02:00
herman ten brugge
311218ee5f Allow testsuite to be build with CC -fsanitize
Makefile: Add sani-test* targets + help
tcc.h: redefine offsetof for clang -fsanitize
tccelf.c: section_ptr_add: allow clang -fsanitize
          tcc_add_btstub/tcc_load_object_file: revert previous change.
tccpp.c: Fix -fsanitize problem by casting to unsigned.
tests/Makefile: tcc -v leaks memory (a lot of returns in main() leak memory)
tests/tests2/Makefile: testcase 112 aborts and leaks memory. Disable leak test.
2025-08-05 16:47:11 +02:00
herman ten brugge
7c23c48a93 Riscv struct saving
While adding some testcases for attribute cleanup I found a
bug in the riscv code. It modifies the sv->c.i in load_symofs.
If a structure contains more then one element only the
first is stored correctly. This only happens on a large
stack frame.
Fixed by saving/restoring sv->c.i.
2025-07-17 06:50:15 +02:00
grischka
9670d10294 fix github CI & stuff
workflows/build.yml:
- win32/64: install mingw32/64 gcc on msys (because the default
  gcc installed elsewhere seems to use ucrt, producing incompatible
  fp printf formats.)
tccgen.c:
- cleanup funcs: save any lvalues from return expressions.  Also use
  get_temp_local_var() which however was causing a problem on i386
  because its gfunc_call() removes the arguments from vstack and by
  that defeats the 'in-use'  tracking of get_temp_local_var().  Fixed by:
i386/arm/arm64/x86_64-gen.c:
- in gfunc_call(): save_regs before anything else, fixes
  problems seen in arm64/i386
tccpp.c:
- allow arm asm specific use of '#' in macros
libtcc.c:
- organize -M options, and:
tccpe.c:
- move the subsystem option parsing from libtcc.c
tccelf.c:
- improved error handling in tcc_load_ldscript()
lib/atomic.S:
- TCC_TARGET_... not defined when building the lib
- endbrNN security feature not supported by TCC
tests/tests2/136_atomic_gcc_style.c:
- never use standard assert() in tests
2025-07-16 21:32:21 +02:00
herman ten brugge
717a510a19 Enable atomic test for all targets 2025-07-14 15:37:13 +02:00
kbkpbot
0c12363fd3 arm64: Save func results before struct args
In gfunc_call(), structure members are loaded into registers during
argument handling.
This operation may overwrite previous function call results stored in
registers (e.g., s0). To prevent this, we must save function call
results to the stack before processing structure arguments.
2025-07-11 22:13:30 +08:00
herman ten brugge
59aecdb539 Another hex float fix
Hex floating point number did fail when a lot of digits are present.
See testcase 70.
2025-05-28 21:33:30 +02:00
herman ten brugge
b6a16e3be4 Save registers around attribute cleanup
This makes attribute cleanup code work the same as gcc and also
makes bound checking a very little bit faster.

tcc.h:
  Add save_return_reg(CType *) and restore_return_reg(CType *)
  Change gfunc_epilog() to gfunc_epilog(Sym *)

arm-gen.c:
arm64-gen.c:
c67-gen.c:
i386-gen.c:
il-gen.c:
riscv64-gen.c:
x86_64-gen.c:
  Move save and restore register around bound_local_delete call
  to save_return_reg and restore_return_reg.
  Pass func_type from gfunc_epilog to gen_bounds_epilog.

tccgen.c:
  Call save_return_reg/restore_return_reg in try_call_scope_cleanup
  when RETURN is found.

tccrun.c:
  Fix warning when bound checking not used.

tests/tests2/101_cleanup.c
tests/tests2/101_cleanup.expect
  Extra checks attribute cleanup save/restore registers.

tests/tests2/Makefile:
  Fix when bound checking not used.
2025-05-22 16:58:12 +02:00
kbkpbot
36ff4f52b5 Add GCC-style atomic builtins: __atomic_*_n
This commit adds GCC-compatible atomic builtins to stdatomic.h for
better compatibility with code relying on GCC's atomic primitives.

1. ​**​New Macros​**​:
   - `__atomic_compare_exchange_n`.
   - `__atomic_load_n`.
   - `__atomic_store_n`.

2. ​**​Motivation​**​:
   - Improves compatibility with codebases using GCC's atomic builtins
     directly.
   - Simplifies atomic operations by allowing direct value passing
     (instead of pointers), enhancing code readability.
   - Aligns TCC's atomic support closer to GCC/Clang for cross-compiler
     projects.

3. ​**​Testing​**​:
   - Verified with basic test cases (integer CAS, load/store) on x86.
   - Confirmed no regressions in existing atomic operations.

- This change does not affect existing C11 `atomic_*` APIs.
- Struct types are intentionally unsupported in `_n` variants due to
  complexity.
2025-04-19 08:05:27 +08:00
grischka
006174449e cleanups & stuff
libtcc.c:
- free 'elfint' string
- acceot  -O and -Os
- accept -gstabs (to override dwarf when default)
- better -Wp,...

tccpp.c:
- #line cleanup
  also warn with "extra tokens after directive"

tccgen.c & xxx_gen.c:
- force CPU flags to register earlier

tccelf.c:
- tcc_load_object: align size only for code sections
  data/bss objects are always put with their specfic type align
      (in decl_initializer_alloc())
  x86/64 doesn't need aligned code
  from c6afdff7ab

tccpe.c:
- enable dllimport for "_imp__<sym>" also from assembler

x86_64-gen.c & lib/libtcc1.c:
- simpler fneg without libtcc1 reference

tests2/134_double_to_signed.c:
- a tcc compiled by msvc won't pass this test
2025-03-11 22:56:01 +01:00
kbkpbot
eef2db71a9 revert commit b8b6a5fd7b
As it will cause printf("%llu\n", (unsigned long long)1e19); output
9223372036854775808
instead of
10000000000000000000
2024-12-30 12:19:01 +08:00
kbkpbot
af1cfd9e82 fix x86_64/i386 gfunc_call, when arg is VT_STRUCT, need fetch cpu flag before generating any code 2024-12-26 12:30:07 +08:00
grischka
f24727b6bb tcc -freverse-funcargs (reverse evaluation)
patch originally made to prove correctness (comparing stages)
with tinycc compiling gcc 2.95.3 which would assign registers
differently (but still correctly) when compiled with tcc without
this option).

Also: fixes get_temp_local_var() which on 32-bit systems
happened to return a temporary location that was still
in use because its offset was changed on the vstack
(incremented by four in gv() to load the second register
of a long long).

Also: optimize vrot-t/b (slightly) by using one memmove
instead of moving elements one by one in a loop.
2024-11-17 21:04:29 +01:00
grischka
c717bac6e3 tccgen: show useful line number with duplicate switch-case
- output correct line number with "error: duplicate case value"
- libtcc.c:error1(): support specific line numbers with "%i:"
       tcc_error("%i:message ...", line_num, ...);
Also:
- simplify signed/unsigned switch compare
- optimize implicit case ranges such as
      case 1: case 2: case 3: ...
- simplify llong constant propagation in gen_opic()
- rename Sym.ncl to Sym.cleanup_func
2024-11-17 20:56:12 +01:00
herman ten brugge
f0cd0fbe1b Print bound region when bound checking error occurs 2024-11-09 08:34:10 +01:00
grischka
45cff8f03f tccelf.c: write section headers before sections
also avoid zero lenght PT_LOAD segments (which some musl
loaders seem to dislike)

Also:
- tccasm.c: support .section with flags: .section .xyz,"wx"
  (fixes e4d874d88a)
- tccgen,c:  add __builtin_unreachable()
- tccdefs.h: #define __has_attribute(x) 0
- tcc.c: tidy help for -std
- tcctools.c/execvp_win32: quote strings more correctly
- x86_64-gen.c:win32: set unwind begin-address to function-start
- github action: add aarch64-osx (M1) & i386-win32
- configure: consider 32-bit build on MSYS64 native
2024-10-13 23:55:32 +02:00
Guest0x0
b8b6a5fd7b fix UB in constant folding of double -> signed integer conversion 2024-09-14 06:17:23 +00:00
Jonathan M. Wilbur
1cee0908d2 fix: tests broken by use of assembly 2024-07-31 04:31:48 -04:00
Jonathan M. Wilbur
f15008da05 fix: previous two commits 2024-07-31 04:15:45 -04:00
grischka
6b78e561c8 div fixes
- Makefile: don't produce unknown targets
- libtcc.c: tcc_set_linker(): improve parser
- tcc.h: tcc_internal_error(): don't record __FILE__ (for privacy reasons)
- tccgen.c:
  - reject pointer + float operation
  - use 'int level' for builtin_frame/return_address
  - save_regs(): remove VT_ARRAY (confuses riscv64-gen)
- tccpe.c: store just basename of loaded dlls (rather than full path)
- tccpp.c: remove unused TAL defines
- *-link.c: add missing ST_FUNC
- i386-gen.c: fix thiscall
- riscv64-asm.c/arm-asm.c: stay simple C89
  - avoid .designators, decl after statement
  - avoid multiple instances of same static const objects
  - use skip() instead of next() & expect()
  - use cstr_printf() instead of snprintf() & cstr_cat()
  - tcc_error(), expect(): never return
2024-06-11 14:26:34 +02:00
grischka
9d2068c630 tccrun: add option CONFIG_RUNMEM_RO=2
/* 0 = .text rwx  other rw (memory: min 2 pages) */
/* 1 = .text rx   other rw (memory: min 3 pages) */
/* 2 = .text rx  .rdata ro  .data/.bss rw (memory: min 4 pages) */

tcc -vv -run ... shows some info.
Also when compiled with -DMEM_DEBUG:
tcc -bench -run ... shows some memory usage
2024-03-03 21:39:53 +01:00
grischka
c88b19966c tccrun: exit() via rt_longjmp()
- new LIBTCC API tcc_setjmp() to allow longjmps & signals
  from compiled code back to libtcc per TCCState
- new LIBTCC API tcc_set_backtrace_func() to handle backtrace output
- move c/dtor/atexit stuff to runtime (lib/runmain.c)
- move bt-log.o into libtcc1.a
- add timeouts to github action (beware, it did happen to hang
  infinitely in the signal handler at some point)
2024-02-15 18:45:49 +01:00
grischka
7b9f19eaab tccpp: macro cleanup
- remove TOK_NOSUBST, mark the token itself instead
- get_tok_str(); mask out SYM_FIELD & update uses
- next(): optimize (~5% faster with tcc -E)
- tok_flags: remove some redundancy
- parse_define(): do not remove spaces around '##' and after '#'
    and mark macros with '##' as MACRO_JOIN to avoid unnecessary
    call to macro_twosharps(mstr):
- next_nomacro(): removed, next_nomacro1(): renamed to next_nomacro()
- next_argstream(): cleanup & new function peek_file()
- macro_subst_tok(): handle special macros (__DATE__ etc.)
  like normal macros if they are #defined
- -DPP_DEBUG : more structured output
- pp_error(): better preprocessor expression error message
- tcctok.h: sort basic keywords (somehow)
- testspp/Makefile: generate .expect with 'make testspp.##+'
- tcc.c: tcc -E -o file : put unixy LFs also on windows
2024-02-09 18:38:14 +01:00
grischka
da0d43903b review recent commits
tccpp.c:
 - revert "Preprocessor fix + new testcase"
   Fix was not a fix and nobody could understand the test.
   This reverts 6379f2ee76
 - better fix and add new test (pp/18.c)

tccgen.c:
 - remove global variables 'in_sizeof', 'constant_p'
 - rework comma expression (gexpr())
 - merge func/data 'alias_target' codes
   (See 08c777053c)
 - move call to do_Static_assert()
 - better error: "expression expected before '%s'"
 - fix "statement after label"
    - remove unnecessary second parameter to block()
    - remove unnecessary call to decl()
    - revert changes to old C89 test file
    See 7f0a28f6ca

tccelf.c:
 - rework "...make undefined global symbol STT_NOTYPE"
   (See f44060f8fc)
 - move tccelf_add_crtbegin() from libtcc.c

tcctest:
 - unfix K&R fix (keep old look of K&R functions)

tccrun.c:
 - exit(0) returns 0

libtcc.c:
 - move #defines for -dumpmachine
 - more explicit error "file not found"
   (as opposed to error while loading file)

tccpe.c, x86_64-gen.c, i386-asm.c, tccasm.c:
 - use R_X86_64_PLT32 for functions on x86_64-win32

tccdefs.h
 - empty #defines for _Nonnull, __has_builtin(), etc.

configure:
 - Simpler "macOS .dylib ... VERSION letters."
   (See 6b967b1285)

Makefile:
 - macOS version also
 - add cross searchpaths for packages

build.yml:
 - disable codesign on macos-11 (doesn't seem to work)
2024-02-04 18:18:40 +01:00
herman ten brugge
bbe2e5a421 Allow declarations in case statement
This now works:

 case 1:
    int z = 123;
    break;
2024-01-16 07:51:56 +01:00
herman ten brugge
c13bbb5cb5 Add type promotion in comma expression and update testcase 94 2024-01-06 07:54:34 +01:00
Rob Pilling
fb164e0ab4 Error out for incomplete type initialisation 2023-11-26 09:29:06 +00:00
Reimar Döffinger
36f53cdc3b Revert "tests: Add support for codesigning command."
This reverts commit ece74ceaaf.

codesigning is already supported via --config-codesign.
This patch actually broke testing for tcc builds with
that set.
2023-10-30 19:08:57 +01:00
Reimar Döffinger
ece74ceaaf tests: Add support for codesigning command.
Allows running the tests out-of-the-box on macOS.
Also delete *.dylib in tests2 dir on "make clean".
One remaining issue on macOS 14.1 is that the
-undefined warning option no longer works,
thus breaking test3 and test1b.
2023-10-29 17:06:59 +01:00
herman ten brugge
31206a5bb8 Fix tests/tests2/Makefile for win32 2023-09-07 20:19:42 +02:00
herman ten brugge
9bb9a04b5f Small fixes
The testcases 22_floating_point and 24_math_library did not work with
make tcov-test
Add -lm for these in tests/tests2/Makefile

gcc -fanalyzer complains about tcc_malloc and tcc_realloc because
malloc(0) and realloc(ptr, 0) is not tested correctly.
2023-09-07 20:05:51 +02:00
grischka
086870addd configury update & bump VERSION to 0.9.28rc
configure:
- option --targetos=... for cross build
- cleanup

win32/build-tcc.bat:
- option -b <bindir>
- make 'libtcc1.a' and cross-prefix-libtcc1.a
  (same convention as with makefile)

Makefile:
- streamline tcov-tests, help, etc.

workflow/build.xml: simplify
- using "windows-2019" runner (instead of windows-latest)
  because its msys seems more complete and has no problems
  with the 96_nodata_wanted.test either.

Changelog,TODO,USES,tcc-doc.texi: update
2023-09-06 22:42:52 +02:00
herman ten brugge
ff2a372a9a Add tcov support in Makefile
The following targets are added:
testc / testc2.all / testc2.37 / testc2.37+ / testc2.37-
testcpp.all / make testcpp.17
This allows to check that the testcase(s) test the code modified.
See Makefile tests/pp/Makefile tests/tests2/Makefile

lib/tcov.c: Fix while loops with fgets.

tcc.h: Fix tcc_p compilation with latest gcc

tests/tests2/22_floating_point.*: Better test floating point
2023-08-31 11:09:49 +02:00
herman ten brugge
b50a0bdf31 Add bound checking for test 132 2023-08-30 16:44:44 +02:00
herman ten brugge
598134fff6 Undo part of incr_offset patch.
The incr_offset offset code was not working with bounds checking.
So I reverted part of tccgen.c.
See new test code 132.

Also added some debugging code that prints location of
bounds checking calls. Needed this to find the problem.
See lib/bcheck.c, lib/bt-dll.c, lib/bt-exe.c, lib/bt-log.c, tccrun.c
2023-08-30 16:10:39 +02:00
grischka
c29420ab0d tccgen: update "Fix invalid load generated by gfunc_return()"
tccgen.c:
- new function incr_offset(int) to increment a lvalue
- use it in gv/vstore to load/store from/to two-word types
- use it to advance the pointer to struct fields
- use it to load/store structs passed in registers
- structs: always assume that reg-classes of registers are 2^n
- adjust stack space when regsize > sizeof the_struct

x86_64-gen.c:
- return regsize=16 for VT_QLONG/QFLOAT

i386-gen.c:
- pass structs of size(8) as two VT_INT rather than one VT_LLONG
  (both should work now)

fixes a82aff3337
fixes fd6d2180c5 (slightly)
2023-07-31 12:22:15 +02:00
herman ten brugge
fd6d2180c5 Align stack when returning structs.
The stack was not aligned when a returned structure was stored on stack.
This resulted in destoying of previous values stored on stack.
See testcase 119 (tst_struct_return_align) where value d is overwritten.
2023-07-31 09:24:06 +02:00
herman ten brugge
5b28165fbf Fix test 131 for 32 bits targets 2023-07-05 19:28:58 +02:00
Yao Zi
a82aff3337 Fix invalid load generated by gfunc_return()
On backends that rely on gfunc_return() to handle structures
  returned in registers (like RISC-V), gfunc_return() may generate
  invalid loads for structures without VT_LOCAL and VT_LVAL. This
  commit fixes it and adds a regression test
  (131_return_struct_in_reg)
2023-07-02 04:02:36 +08:00
herman ten brugge
30fd24abd4 Allow different names for pragma once
pragma once can now be used with
test.h
./test.h

and other references to the same file just like gcc/clang.

On linux we can use stat and st_ino to check for the same file.
On windows the st_ino does not work so we calculate a file hash
if the size of the file differs and then compare the hash.
2023-06-25 20:23:58 +02:00