Move the TinyCC/Windows ARM64 Interlocked workaround from the semlock call site into the bundled WinAPI header. This keeps tcc.h using the normal Interlocked API while avoiding unresolved Interlocked imports when tcc -run self-compiles on Windows ARM64.
Update lib/bt-exe.c as well so its ARM64 runtime object does not define a second InterlockedExchange fallback now provided by winnt.h.
- tccmacho.c: add STT_TLS to convert_symbol() for Mach-O output
- tests/tests2/Makefile: skip 144_tls on Win32 (no pthread.h) and
remove arm from TLS arch list (QEMU user-mode cannot emulate
MRC p15 TLS register access)
Replace raw-register AMO asm with proper inline-asm constraints
for all three operands (rd, rs2, rs1). Use long long for .d-word
AMO variants with pre-set values (xd=0xCAFEBABECAFEBABE,
val=0xDEADBEEFDEADBEEF) to avoid uninitialized-data issues.
Restore csr_pseudo_main printf output and re-enable amo_main()
in the test (was commented out as 'crash on qemu').
Use GEN = $(GEN-TCC) since GCC and TCC produce different fcsr
initial values on riscv64.
Revert 199369bb17
- generating test.ref with tcc makes little sense.
- combine riscv_asm & conversion tests into only two files.
(too many files are bad ...)
Add handlers for csrr, csrw, csrwi, csrsi, csrci as pseudo-instructions:
csrr rd, csr -> csrrs rd, csr, x0
csrw csr, rs -> csrrw x0, csr, rs
csrwi csr, uimm -> csrrwi x0, csr, uimm
csrsi csr, uimm -> csrrsi x0, csr, uimm
csrci csr, uimm -> csrrci x0, csr, uimm
Tokens were already defined in riscv64-tok.h. Tested on
Spacemit X100 using fcsr (0x003) which is accessible in user mode.
cycle/instret CSRs are privileged and not accessible from Linux
user mode on this hardware.
On RV64, long long (64-bit) fits in a single general-purpose register.
The existing load/store calls already handle 64-bit values correctly.
The 'not implemented' errors were vestigial from 32-bit architectures
where long long requires a register pair.
Removing these errors allows inline asm to accept 64-bit integer operands
on RV64, which is important since this is the native register width.
tccpe.c:
- fix arm64 unwind codes (to make native set/longjmp() work)
sizeof(RUNTIME_FUNCTION) is 8 on arm64 in the first place
no need to note stack slots if we don't save any registers anyway
arm64-gen.c:
- fix long double reg-move
- fix arm64_hfa() for structs with float arrays
- gfunc_prolog(): setup stackframe eariler (simplifies unwind codes)
- new function gv_addr(RC);
win32/include/setjmp.h:
- provide correct definition for setjmo() (frameoffset = 224)
tccasm.c:
- support ".quad" with symbol & relocation
- support ".size"
- fix ". - symbol" arithmetic
win32/lib/crt1.c and win32/include/stdlib.h:
- do not write to __argc/__argv which reside in msvcrt.dll
(msvcrt.dll on arm64 does not like that, crashes on unload)
tcc.c,libtcc.c:
- new functions tcc_fopen/fclose to avoid different stdio unstances
in tcc.exe & libtcc.dll
tests & github workflow:
- add test-win32.bat to run tests with a tcc compiled by build-tcc.bat
- add msvcrt_start.c for gcc/clang to use the same runtime as tcc
the problem is that newer gcc as well as clang and cl are
linking to newer runtimes (such as UCRT) that have partially
different printf format behavior which makes tcctest fail.
the solution here is to force these compilers to link with
msvcrt.dll just like tcc.
Also, there is no gcc on arm64-win32 currently at all.
Anyway, this approach to running the github CI tests
does not require msys2. But It does rely on gnumake
as well as on some 'sh' shell though which seems to be
installed somewhere (maybe it is the one from git).
from: https://github.com/bold84/tinycc
Author: Benjamin Oldenburg <benjamin.oldenburg@ordis.co.th> 2026-04-04 16:29:28
Committer: Benjamin Oldenburg <benjamin.oldenburg@ordis.co.th> 2026-04-04 16:29:28
Branch: win_arm64_clean
Commit: 8b5ab1bb01
Also here: https://repo.or.cz/tinycc.git/shortlog/refs/mob/mob_bold84/win_arm64_clean
This and the followup commits on mob is selected parts
of that original branch. So it is not everything.
It is not, for example:
- unrelated whitespace changes in many files
- a "pin msvcrt.dll" feature in tccpe.c (why that)
- a native getenv() replacement in tcc.c (why that)
- larger changes to the win32/lib runtime and tccrun.c (not needed)
- a very gcc specific detail for struct alignent in tccgen.c
- a custom set/longjmp implementation/replacement (not needed)
- lots of rather basic test files in the win32 folder
- a 'tests/asm' folder with some files (one file renamed to 140_test...c)
- a .docs folder with one file
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 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.
This reverts commit ece74ceaaf.
codesigning is already supported via --config-codesign.
This patch actually broke testing for tcc builds with
that set.
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.
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.
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
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
Update tccrun.c to detect rebase for dwarf debug info.
Enabled testcase 126 on macos.
Add prologue_end/epilogue_begin supoort in tcc.h, tccdbg.c, tccgen.c.
Make code more compatible with gcc. Change
__atomic_store
__atomic_load
__atomic_exchange
__atomic_compare_exchange
Also add (include/stdatomic.h, lib/stdatomic.c):
atomic_thread_fence
atomic_signal_fence
atomic_is_lock_free
And gcc extensions (tcctok.h, tccgen.c, lib/stdatomic.c):
__atomic_fetch_nand
__atomic_and_fetch
__atomic_sub_fetch
__atomic_or_fetch
__atomic_xor_fetch
__atomic_and_fetch
__atomic_nand_fetch
Add new file lib/atomic.S with assembly code for __atomic_compare_exchange_n
for arm/arm64/riscv. Also update lib/Makefile.
Update testcode in 124_atomic_counter and 125_atomic_misc to test new functions.
Also update tests/tests2/Makefile to run tests on arm/arm64/riscv.
On an armeabi-v7a device (phone) in the termux app with
clang & make installed this passes all the tests.
Can be used as a cross compiler to create "native apps" as well.
Example 'config-extra.mak' for the cross arm-eabi-tcc:
SYSROOT = <path_to_android_ndk...>/sysroot/usr
TRIPLET = arm-linux-androideabi
ANDRVER = 32
ROOT-arm-eabi = $(SYSROOT)
CRT-arm-eabi = {R}/lib/$(TRIPLET)/$(ANDRVER)
LIB-arm-eabi = {B};{R}/lib/$(TRIPLET)/$(ANDRVER);{R}/lib/$(TRIPLET)
INC-arm-eabi = {B}/lib/include;{R}/include/$(TRIPLET);{R}/include
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
DEF-arm-eabi += -DTARGETOS_ANDROID -DCONFIG_TCC_PIE -DCONFIG_NEW_DTAGS
DEF-arm-eabi += -DCONFIG_TCC_ELFINTERP=\"/system/bin/linker\"
# on unix replace ';' by ':'.
$ ./configure && make cross-arm-eabi && make install
See commit e588b65390.
Was not "wrong" really, just different. But appears to be outdated.
Now disabled by default (top of tccpp.c: ACCEPT_LF_IN_STRINGS)
Also, in skipped code, just warn.
Also: cleanup "Optimize small structure copying on x86_64"
(commit 3715f1d7ee)
- remove some copy&paste coding (tccgen.c)
- RSI/RDI need to be preserved on windows
- simply don't use under bcheck (this is tinycc)
it.Commit 3715f1d makes the error message of bound check on x86_64
different from other platforms,which breaks the test process.But that
commit exactly works well.
The new gcc12 release does not support stabs any more.
This was a good reason to add support for dwarf.
The stabs code still works and is used if configure option --dwarf
is not used.
Tested on x86_64, i386, arm, arm64, riscv64 with dwarf-5.
Some debuggers may not support dwarf-5. Try using older dwarf versions
i that case.
The tccmacho.c code probably need some support for dwarf.
arm-gen.c, arm64-gen.c, i386-gen.c, riscv64-gen.c, x86_64-gen.
- fix get_sym_ref symbol size
arm-link.c, arm64-link.c, i386-link.c, riscv64-link.c, x86_64-link.c
- add R_DATA_32U
libtcc.c:
- parse -gdwarf option
tcc.c:
- add dwarf option
tcc.h:
- add dwarf option and sections
tccelf.c:
- init dwarf sections
- avoid adding sh_addr for dwarf sections
- remove dwarf relocs for output dll
- add dwarf sections for tccrun
tccgen.c:
- add dwarf defines + global data
- add dwarf_* functions
- mix dwarf code with stabs code
- a trick is used to emit function name in .debug_line section so
only this section has to be parsed instead of .debug_info and
.debug_abbrev.
- fix init debug_modes
tccrun.c:
- add dwarf sections in rt_context
- init them in tcc_run
- add new dwarf code rt_printline_dwarf to find file/function
dwarf.h:
- New file
tcc-doc.texi:
- document dwarf
configure:
- add dwarf option
lib/Makefile
- change -gstabs into -gdwarf
lib/bt-exe.c, tests/tests2/Makefile, tests/tests2/126_bound_global:
- Add __bound_init call
- Add new testcase to test it
- remove any error messages that were just for debugging the
templates really
- don't use c99 in tcc (array designators etc.)
- remove memory model type (cannot be an own type really)
and move memory model defines from built-in to stdatomics.h
- apply normal casts to non-pointer atomic_function arguments
- tidy the library support
- add some tests for errors/warnings
Also:
- Makefile: move GIT_HASH stuff from CFLAGS to DEFINES and into
main section (away from what is included by tests for example)
- tccelf.c/tccgen.c: avoid some warnings with newer GCC
netbsd does not allow text relocations in text segment.
tcc.h:
- Add data_ro_section
- Fix typo rela.plt
tccelf.c:
- Add data_ro_section
- Make bounds_section/lbounds_section rw
- Add GNU_RELRO section for data_ro_section/bounds_section/lbounds_section
- Fix relocation for __dso_handle in atexit()
tccgen.c:
- Use data_ro_section
x86_64-gen.c:
- Use R_X86_64_PC32 instead of R_X86_64_64 for bounds checking
tests/Makefile, tests/tests2/Makefile
- Enable dll tests for netbsd
This implements support for FreeBSD on aarch64
This partial implements support on FreeBSD(32). This still needs fixing
i386_gen.c because small structures on this target are passed in registers.
Add aligned 16 to __int128_t for FreeBSD
Support __i386__ on FreeBSD/NetBSD
Fix testcase 115 on FreeBSD/NetBSD
Disable testcase 116 on *BSD* because TLS_FUNC/TLS_VAR not set in bcheck.c
Remove FreeBSD/FreeBSD_kernel code from tccelf.c
Fix crtbegin/crtend
Use dlsym on all bsd targets
Check .eh_frame on all bsd targets
Disable test3 on FreeBSD and NetBSD and use test1 instead because dlsym not working (WIP)
Disable dlltest and 113_btdll on NetBSD because text relocations are not allowed
Disable 115_bound_setjmp on NetBSD because longjmp is renamed into __longjmp14
Currently tcc does not use lazy binding. It puts all relocations in the RELX
section and solve them all at startup.
This was not working on bsd.
tcc.h:
- New RELPLT_SECTION_FMT for plt relocations
- New entry relocplt in struct Section
tccelf.c:
- put_elf_reloca: put R_JMP_SLOT in relocplt section
- build_got_entries*: Use two passes because R_JMP_SLOT and R_GLOB_DAT
can not be intermixed on some targets (arm, arm64)
- layout_sections: Calculate correct size relocplt section for DT_ values.
Make sure relocplt is last
- fill_dynamic: Add DT_ values when got is filled
move DT_VERSYM because dynamic linker cannot handle it standone
- Add note section for NetBSD
arm-link.c/arm64-link.c/i386-link.c/riscv64-link.c/x86_64-link.c:
- fill got table with pointer to plt section or symbol value in case
of TCC_OUTPUT_MEMORY
arm-link.c/arm64-link.c:
- fix offset first plt entry
i386-link.c/x86_64-link.c:
- use correct reloc entry
- use relofs - sizeof (ElfW_Rel) because the reloc is already done
lib/bcheck.c:
- no __libc_freeres on FreeBSD and NetBSD
tests/Makefile:
- Add -fno-stack-protector for OpenBSD
tests/tests2/Makefile:
- disable 106_pthread/114_bound_signal
- The compiler should not use these
- However tccrun.c & libtcc1.a files should use these
Also:
- use s1->loaded_dlls for loaded dlls instead of dlopens
- alpine musl: fully supported now and tested
- ./configure ...
--config-backtrace=no : disable backtraces
--config-bcheck=no : disable bcheck
- tests:dlltest: enable by default
- tccrun.c : simplify mmaps
- __builtin_alloca : always use asm-alias (instead of #define)
- tccpe.c : use write32le
tccgen.c:
- Fix 'tcc -b conftest.s'
- Add offset during bound checking for struct return
lib/bcheck.c:
- Check overlap when reusing vla/alloca
arm-gen.c:
arm64-gen.c:
riscv64-gen.c:
lib/alloca86-bt.S:
- add space for vla/alloca during bound checking
tests/tests2/Makefile:
tests/tests2/121_struct_return:
tests/tests2/122_vla_reuse:
- New test cases with bound checking enabled to test vla and struct return