3729 Commits

Author SHA1 Message Date
inostensibl
fad812360b tccgen: fix void expression side effect regression
From 7e01b20362

reduced from an app that builds/runs with gcc or clang.
2026-05-09 22:11:58 -04:00
Meng Zhuo
2888e49f39 riscv64-gen: implement gen_clear_cache
Emit fence + fence.i (Zifencei extension) for I/D cache
synchronization, needed for tcc -run mode on RISC-V.
Zifencei is required by the RISC-V Linux ABI and present
on all Linux-capable cores, though technically not part
of the RV64G base ISA.
2026-05-07 16:07:53 +08:00
Meng Zhuo
c77339ab41 riscv64: emit .riscv.attributes section in ELF output 2026-05-07 11:44:46 +08:00
Meng Zhuo
7f764f340f riscv64-asm: complete AMO aq/rl suffixes for all ops
Add 48 tokens + handlers + dispatch cases for all AMO aq/rl
variants (amoswap, amoand, amoor, amoxor, amomax, amomaxu,
amomin, amominu; each x {.w,.d} x {.aq,.rl,.aqrl}).

GNU-compatible 2-dot naming via DEF_ASM_WITH_SUFFIXES.
Correct funct5 values: amoswap=0x01, amoand=0x0C, amoor=0x08,
amoxor=0x04, amomax=0x14, amomaxu=0x1C, amomin=0x10, amominu=0x18.

Extend 141_riscv_asm amo_main() with 10 representative aq/rl
variants covering all ops x ordering suffix combinations.

Verified against riscv64-linux-gnu-as 2.44.
2026-05-07 11:44:46 +08:00
Meng Zhuo
a672babc6f tests: fix 141_riscv_asm AMO crash, restore full test coverage
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.
2026-05-07 11:44:18 +08:00
grischka
44977b0de8 tcctest: restore & combine
Revert 199369bb17
- generating test.ref with tcc makes little sense.
- combine riscv_asm & conversion tests into only two files.
  (too many files are bad ...)
2026-05-06 18:52:01 +02:00
grischka
6daf1617ef configure & tcc.h: include & lib searchpath cleanup
configure:
- remove CONFIG_USE_LIBGCC, --with-libgcc
- remove CONFIG_LDDIR
- remove CONFIG_USR_INCLUDE
- add -q switch for quiet (=no) output

tcc.h:
- remove /usr/local/include&lib search paths

arm-gen.c:
- remove default_elfinterp() function

tccelf.c:
- setup the ELF-interp in tccelf_new()
2026-05-06 13:46:42 +02:00
grischka
923fba83f1 general: long double issues
tccgen.c:
- init_putv(): improve long double cross constants
  now in separate function including some basic conversions

arm-gen.c:
- switch to using TCC_USING_DOUBLE_FOR_LDOUBLE
  now it actually never will see VT_LDOUBLE

lib/lib-arm64.c:
- simplify by using unions

tccpp.c:
- reduce amounts of #ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
2026-05-06 13:46:38 +02:00
grischka
7e01b20362 tccgen: void values, etc...
originally, this was meant to avoid 'void' values leak
to the gen-xxx.c generators which would otherwise try
to load void from/to registers.  Also catch invalid types
such as 'unsigned bool' eariler.

tccgen.c:
- expr_cond()/gexpr(): ignore VT_VOID
- gen_cast(): set float reg with static initializers to make
  backends happier with invalid input
- init_putv():
  improve static compound literal initializers
Also:
- ignore "missing prototype" and "might return no value"
  for old style K&R functions

tcc.c, libtcc.c:
- tcc_set_output_type(): return errors from loading crt1.o

tcc.h/tccpp.c:
- fix horrible longstanding mistake with sizeof SValue.tab.
  Must have place for sizeof (long double) rather than the
  target's LDOUBLE_SIZE.

tccdefs.h:
- add a fake __[u]int128_t for all platforms

arm-gen.c:
- gen_cvt_ftof() must load to reg always

arm64-gen.c:
- simplify arm64_pcs() a bit

i386/x86_64-gen.c:
- do not assume char is signed (for cross compilation arm->x86)

tccelf/macho linker message:
- instead of
      "undefined symbol 'X'"
  now say
      "unresolved reference to 'X'"
  which makes it more clear that it is a _linker_error_.

tccasm.c:
- .align/p2align: use 'nop's in exec sections
2026-05-06 13:46:27 +02:00
Meng Zhuo
016087c954 riscv64-asm: implement AMO, fcvt rounding, and fcvt encoding fixes
AMO (A-extension):
  18 base instructions: amoadd/swap/and/or/xor/max/maxu/min/minu .w/.d
  6 aq/rl suffixes: amoadd.w.aq/.rl/.aqrl, amoadd.d.aq/.rl/.aqrl
  Correct funct5 (GNU as verified):
    amoadd=0x00 amoswap=0x01 amoxor=0x04
    amoand=0x0C  amoor=0x08  amomax=0x14
    amomaxu=0x1C amomin=0x10 amominu=0x18
  R-type opcode 0x2F, aq/rl in bits [26:25]

FCVT rounding modes (GNU operand syntax):
  fcvt.w.s rd, rs1 [, rtz/rne/rup] -- optional 3rd operand
  asm_fcvt_opcode() handler with asm_fcvt_rm() helper
  Keywords rne=0, rtz=1, rdn=2, rup=3, rmm=4

FCVT encoding fixes:
  fcvt.s.d: funct7 0x40->0x20
  fcvt.d.s: funct7 0x42->0x21

Tests: 144 CSR, 145 F/D cmp+cvt, 146 AMO, 147 fcvt round.
All verified against riscv64-linux-gnu-as 2.44 on Spacemit X100.
2026-05-06 19:18:17 +08:00
Meng Zhuo
f8011ea9b7 riscv64-asm: implement CSR pseudo-instructions
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.
2026-05-06 18:33:15 +08:00
Meng Zhuo
199369bb17 tests: generate test.ref with TCC instead of host CC
The promote char/short funcret test in tcctest.c invokes
undefined behavior (narrow return without extension). GCC
produces one set of values, TCC with PROMOTE_RET produces
correct ABI-compliant values. Generate the reference with
TCC so self-tests are consistent.
2026-05-06 14:43:30 +08:00
Meng Zhuo
3935c3bb55 riscv64-asm: add basic F/D extension instructions (fadd/fsub/fmul/fdiv)
Adds the 8 most essential floating-point arithmetic instructions:
fadd.s/d, fsub.s/d, fmul.s/d, fdiv.s/d, for both single and double
precision.  These complement the existing fsgnj/fmax/fmin/fsqrt set.
Comparison (feq/flt/fle) and conversion (fcvt) instructions remain
as future work.
2026-05-06 12:30:34 +08:00
Meng Zhuo
273978b927 riscv64-asm: implement pseudo-instructions sext.w, fmv, fneg
sext.w: addiw rd, rs, 0 (sign-extend 32-bit word)
fmv.s/fmv.d: fsgnj.s/d rd, rs, rs (float register move)
fneg.s/fneg.d: fsgnjn.s/d rd, rs, rs (float register negate)

These were defined in riscv64-tok.h but had no handler code.
CSR pseudo-instructions (csrr, csrw, csrci, csrsi, csrwi) skipped
for now — they require CSR operand parsing in binary mode.
2026-05-06 12:30:34 +08:00
Meng Zhuo
2a33daedca tccasm: extend .reloc directive for RISCV64 relocation types
Previously, .reloc unconditionally errored on RISCV64 — only ARM64
had permission to use R_AARCH64_CALL26.  Now supports common RISCV64
relocations: R_RISCV_CALL, CALL_PLT, BRANCH, JAL, PCREL_HI20,
PCREL_LO12_I/S, 32_PCREL, 32, 64.

Restructured to use string-to-reloc-type mapping, shared across all
targets.
2026-05-06 12:30:34 +08:00
Meng Zhuo
3257afa160 riscv64-link: add R_RISCV_RELATIVE case in relocate()
arm64-link.c has R_AARCH64_RELATIVE handling.  Without this case,
incoming R_RISCV_RELATIVE relocations from object files fall through
to the 'FIXME: handle reloc type' default path.

P1.7 (NEED_BUILD_GOT guards) is not needed: NEED_RELOC_TYPE and
NEED_BUILD_GOT are always defined in the build context (tcc.h:1608).
2026-05-06 12:30:34 +08:00
Meng Zhuo
419b527657 riscv64-asm: implement far branches via expansion
For branch targets that are external/static symbols (where the
offset cannot be determined at assembly time), expand to:
  b<inverse> .+8       # skip if condition false
  auipc t0, %pcrel_hi  # load target upper bits
  jalr x0, %pcrel_lo(t0)  # jump

This handles the ±4 KiB B-type limitation without requiring
linker relaxation (R_RISCV_RELAX).  Local immediates within
range still use the compact B-type encoding.
2026-05-06 12:30:34 +08:00
Meng Zhuo
5c2240a896 riscv64-asm: remove long long 'not implemented' errors in inline asm
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.
2026-05-06 12:30:34 +08:00
Meng Zhuo
366569eb7a riscv64-asm: fix neg/negw pseudo-instruction encoding
neg/negw were incorrectly using asm_emit_i (I-type/xori) with an
immediate of 1, producing 'xori rd, rs, 1' instead of the intended
'sub rd, x0, rs'.  Fixed to use asm_emit_r (R-type) with proper
SUB/SUBW opcode (0x33/0x3B, func3=0, func7=0x20).

The old code generated wrong machine code for these pseudo-instructions.
negw now also correctly uses OP-32 (0x3B) for 32-bit subtraction.
2026-05-06 12:30:34 +08:00
Meng Zhuo
ff917c09aa riscv64: implement gen_cvt_sxtw with addiw instruction
Replaces the empty stub that relied on 'RV64 registers are always
sign-extended' assumption.  Now emits addiw rd, rs, 0 for proper
32-to-64 bit sign extension, matching arm64's sxtw behavior.

Verified on Spacemit X100: tests2 pass (125_atomic_misc has a
pre-existing intermittent segfault, not caused by this change).
2026-05-06 12:30:34 +08:00
Meng Zhuo
9f0915a506 riscv64: implement gen_cvt_csti for narrow int promotion
Add sign/zero extension for char/short to int casts using
slli+srai (signed) or slli+srli/andi (unsigned) sequences.
Also adds RISCV64 to the gen_cvt_csti fast-path conditional
in tccgen.c:3466, matching arm64/i386/x86_64.

Verified on Spacemit X100: all tests2 pass, no regressions.
2026-05-06 12:30:34 +08:00
Meng Zhuo
69c8e92566 riscv64: add PROMOTE_RET for narrow return ABI compliance
Other mature backends (i386, x86_64, arm64) all define PROMOTE_RET,
which forces explicit sign/zero extension of narrow return types at the
caller side.  Without it, riscv64 relied on the assumption that RV64
registers are always sign-extended, which may not hold when interfacing
with non-TCC compilers.

Verified on Spacemit X100 (riscv64): self-compilation is self-consistent
across 3 layers.  test3 reference mismatch is expected — the test
intentionally invokes UB via type-punned function pointers (csf macro).
2026-05-06 12:30:34 +08:00
grischka
30afb50e64 arm64-win32 review: fix problems and pass tests
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).
2026-05-04 12:51:10 +02:00
Benjamin Oldenburg
576cd2a923 arm64-win32 support: symbolic op-code constants
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: 8b5ab1bb0141e66887bfbc4051688a3e478701a2

Also here: https://repo.or.cz/tinycc.git/shortlog/refs/mob/mob_bold84/win_arm64_clean

This and the previous 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
2026-05-04 12:50:42 +02:00
Benjamin Oldenburg
44e6853cb1 arm64-win32 support: target PE & varargs 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
5c728d6506 arm64-win32 support: improve HFA & struct 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
90d17c9748 arm64-win32 support: use arm64_sub_sp() 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
99713bcbfa arm64-win32 support: use arm64_sym() 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
303badef22 arm64-win32 support: fix scaled mask 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
41bcb4a78f arm64-win32 support : linker & -run 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
f459aff5f6 arm64-win32 support : arm64 assembler 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
ea823189d6 arm64-win32 support : tests 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
03d58b0746 arm64-win32 support : runtime 2026-05-04 12:49:53 +02:00
Benjamin Oldenburg
ff5d3b4874 arm64-win32 support : configure & Makefiles
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: 8b5ab1bb0141e66887bfbc4051688a3e478701a2

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
2026-05-04 12:49:25 +02:00
grischka
d9a6d9aec0 reverts (11/2025 - 04/2026)
Revert "Add support to debug libtcc code"
- not fully developed experimental feature
This reverts commit 1fe3e3bff5.
This reverts commit 4768b11737.

Revert "tests: add test for x86_64 xor REX prefix bug in load()"
- AI generated nonsense test
This reverts commit d5ecb52a71.

Revert "tccpp.c: Improve integer constant overflow warning"
- Too long and confusing messages and comments for feature
  with questionable benefit.
This reverts commit 085bdf8997.

riscv64-link:
- cleanup "pair pcrel lo relocations by hi address"
  From fada98b1ce

tccgen.c:
- Simplify "Cast signed pointer offset to ptrdiff_t before performing arithmetic"
  From 5ad52cc1ed

libtcc.c:
- Revert "tcc options: document behavior and clashes (no-op)"
  a bit more information than one would like to have I think.
  (why try to understand that comments plus the extra
  script if one can as well just read the code itself ;)
  From 234e2dd2bf

tccdefs.h:
- Revert "Move lib/va_list.c into include/tccdefs.h"
  Lets not fill tccdefs.h with too much inline code
  Also, -nostdlib -run is no longer supported
  From fa6a6bfbbd

arm64-gen.c:
- cleanup "Implement TOK_NEG for floats natively"
  Also, make it "no lvalue" in tccgen.c/x86-64-gen.c
  From c39eaf10cf

lib/lib-arm64.c:
- cleanup "Remove libc dependency from lib-arm64"
  using unions is much faster than some made up memcpy()
  From 8c61b91de8
2026-05-03 11:09:45 +02:00
H-language
a66ac623b2 win32: add missing AttachConsole export to kernel32.def
AttachConsole has been exported from kernel32.dll since Windows XP
but was absent from TCC's import definitions, causing
"undefined symbol 'AttachConsole'" at link time for code that uses it.
2026-05-01 09:58:03 +12:00
Cyan Ogilvie
4768b11737 tccrun: fix OOB read in elf_output_obj after tcc_relocate with -g
When -g is set, cleanup_sections() preserves all sections after relocate,
including the SHT_RELX relocation sections. cleanup_symbols() drops all
STB_LOCAL symbols from the symbol table, which renumbers the remaining
globals. The kept relas still hold r_info indices from the pre-cleanup
numbering, but nothing rewrites them. A later elf_output_obj() call ends
up in sort_syms() / update_relocs(), which allocates old_to_new_syms[]
sized for the post-cleanup (smaller) symtab and then indexes it with the
stale (larger) sym_index values from those rela entries, reading past
the end of the array.

Fix: when do_debug is set, build an old->new index map while re-adding
globals, then walk every retained SHT_RELX section linked to the symtab
and rewrite its r_info entries. Locals (and the undef sym at 0) map to
0 by tcc_mallocz, so relocations against dropped locals now refer to
SHN_UNDEF - the best we can do without preserving the locals themselves.

Reproducible with libtcc_debug.c if the program contains enough static
helpers / string literals for the symtab to actually shrink; observed
under valgrind in jitc (https://github.com/cyanogilvie/jitc) when
compiling re2c-generated state machines with -g.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 15:37:49 -03:00
Petr Skocik
b39da9f6fa Fix false warnings with readonly atomics
Code like:

    #include <stdatomic.h>
    _Atomic const int ai; int aiGet(void){ return atomic_load(&ai); }

has been raising "warning: assignment of read-only location".

This is due to `__typeof__ (*ptr) tmp;` not rvalue-converting the target
type.
2026-04-28 08:40:53 +02:00
Petr Skocik
5675177b7f allow $ at nonstarting positions in asm symbols under -fdollars-in-identifiers
e.g., asm("foo$bar: ret;");
2026-04-28 08:36:09 +02:00
Reini Urban
543d84c668 .gitignore: Add tests/libtcc_test_xor_rex 2026-04-26 14:56:39 +02:00
Detlef Riekenberg
9b8765d8ba Revert commits from OpenCode-AI and a partial regression fix
This reverts the crap from an unknown committer "OpenCode[AI]", that added an extension to TinyCC,
which is incompatible to the C standard and not available in any other mainstream C compiler:

* Revert "No More ; needed"
This reverts commit 6547ea47d6

* Revert "Add AGENTS.md"
This reverts commit 898f496dc9.

This also reverts a regression fix by "Zuhaitz.dev", which fixed a small part of the OpenCode-AI chaos:
* Revert "tccgen: Fix optional semicolon regression"
This reverts commit 169628a6ab

--
Regards ... Detlef
2026-04-20 01:42:41 +02:00
Anon
7b92d2dcd2 Fix warning 2026-04-16 13:16:17 -07:00
Zuhaitz-dev
169628a6ab tccgen: Fix optional semicolon regression 2026-04-16 17:24:21 +01:00
Cyan Ogilvie
8ecfd0a722 Relicensing TinyCC 2026-04-16 10:45:24 -03:00
Cyan Ogilvie
690fb14015 x86_64-gen: fix missing REX prefix for xor zero into r8-r15
load() used a raw o() call to emit xor-zero which lost bit 3 of the
register number via REG_VALUE():

    o(0xc031 + REG_VALUE(r) * 0x900);

For r >= 8, this emitted the wrong instruction (e.g. xor %ebx,%ebx
for TREG_R11 instead of xor %r11d,%r11d), clobbering the wrong
register.

Use orex() to emit the REX prefix, consistent with all adjacent
branches in load().
2026-04-16 10:42:16 -03:00
Cyan Ogilvie
d5ecb52a71 tests: add test for x86_64 xor REX prefix bug in load()
When load() in x86_64-gen.c generates a zero constant for a 64-bit
register, it uses:

    o(0xc031 + REG_VALUE(r) * 0x900);

REG_VALUE(r) masks to (r & 7), losing bit 3, and no orex() call
emits the REX prefix needed for registers r8-r15.  For TREG_R11
(used by gcall_or_jmp for indirect calls), this emits
"xor %ebx,%ebx" (31 db) instead of "xor %r11d,%r11d" (45 31 db),
clobbering the wrong register.

The test compiles an indirect call through a null function pointer
((void(*)(void))0)() via libtcc, then inspects the generated machine
code for the incorrect encoding.
2026-04-16 10:42:16 -03:00
OpenCode[AI]
6547ea47d6 No more ; needed 2026-04-15 20:56:01 -07:00
OpenCode[AI]
898f496dc9 Add AGENTS.md 2026-04-15 20:28:42 -07:00
Stefan
98765e5ebc libtcc.c: Change parameter name of tcc_set_realloc
In libtcc.h there is void tcc_set_realloc(TCCReallocFunc *my_realloc).
Name the parameter in the function definition in libtcc.c accordingly.
2026-03-28 15:44:20 +01:00
Stefan
085bdf8997 tccpp.c: Improve integer constant overflow warning
Improve the warning about an integer constant overflow with the used
overflown value and the potentially aimed value.

This helps spotting the 0 to much in 0x80000000000000000.
2026-03-28 15:31:21 +01:00