Use the existing array-aware qualifier helper when propagating qualifiers from a const or volatile aggregate to a selected field. This keeps address-of array members from spuriously warning while preserving warnings for discarded qualifiers and read-only writes.
Add regression coverage for pointer-to-array returns, array decay, and writes through const array members.
Replace hardcoded VsDevCmd.bat Enterprise path with vswhere.exe +
vcvarsall.bat for dynamic VS discovery across editions and runner
image versions. Architecture args: amd64, x86, amd64_arm64.
Split x86_64/i386 win32 jobs into separate build and test steps.
For arm64: keep build+test in one step (needs vcvarsall for lib.exe).
Prepend standalone LLVM bin to PATH so clang targets ARM64 natively
instead of VS's clang-cl inheriting the x64-hosted cross-compile env.
Wire gen_clear_cache to __riscv64_clear_cache builtin, emitting
fence.i for instruction cache synchronization.
Add lib/riscvflush.c to provide __clear_cache for JIT bootstrap.
Extend tccrun.c I-cache flush guard to include RISC-V targets.
Add gen_clear_cache declaration to tcc.h riscv64 section.
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.
Windows/arm64 exposes Interlocked* operations as compiler intrinsics rather than kernel32 exports. When tcc -run self-compiles tcc.c, calls to InterlockedCompareExchange or InterlockedExchange can therefore remain as unresolved imports in the in-memory linker.
Route the TinyCC arm64 path through the existing __atomic helpers while keeping Interlocked* for other Windows compilers. The compile-lock initialization state machine remains unchanged.
Report VirtualProtect failures with a Windows-specific -run diagnostic.
On Win64, also treat RtlAddFunctionTable failure as an error so unwind
registration problems are visible.
Add PE linker switches to set and clear DYNAMIC_BASE, NX_COMPAT,
HIGH_ENTROPY_VA and TERMINAL_SERVER_AWARE without changing x86/x64
defaults. HIGH_ENTROPY_VA is limited to 64-bit PE targets and implies
DYNAMIC_BASE; clearing DYNAMIC_BASE also clears HIGH_ENTROPY_VA.
When DYNAMIC_BASE is requested for an executable, emit base relocations
and clear RELOCS_STRIPPED so Windows ASLR can relocate the image. Keep
the existing ARM64 default hardening flags.
Invoke cv2pdb with _spawnvp on Windows so output paths are passed
as argv entries instead of through cmd.exe.
For non-Windows PE cross builds, keep the system() fallback but
shell-quote the executable name and size the PDB path dynamically.
Use interlocked state transitions around the lazily initialized Windows
CRITICAL_SECTION so concurrent first-time callers cannot race into a
double initialization.
- 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)
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.
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 ...)
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
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
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.
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.
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.
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.
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.
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).
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.
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.
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.
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).
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.
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).
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 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
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
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
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.
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>
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.
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
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().
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.
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.
Track R_RISCV_PCREL_HI20/GOT_HI20 relocations by address and resolve LO12 relocations against the referenced HI, instead of only using the last seen HI.
Also reset/free the per-link relocation map in TCCState.
Moving the u128_t struct may invoke calls to memcpy/memmove when
compiled with tinycc, which would depend on libc.
For example, some configure scripts get confused if they fail to build
test programs involving long doubles. I'm not sure if this is the root
cause, though.
This reverts commit 41fa74fc84.
Reasons for the revert:
1. The commit message is lacking and the use case is not obvious.
At the very least a concrete example of use case should be given
(likely cross-building tcc on platform X for running on platform Y),
followed by an issue description in such use case, and fix descr.
(e.g. "On platform X, when running ./configure ... && make ..., the
build fails because whatever. this commit does Y and fixes it").
2. assign_opt is used incorrectly: 1st arg must be --OPTNAME=VALUE
but it's not. The only thing it does is unconditional host_cc=gcc
if --cross-prefix=... is used - no need for "assign_opt" at all.
3. cross-building tcc currently has several triggers: build/target
cpu differ, or build/target OS differ, or --cross-prefix=... is
used, but that commit only covers the --cross-prefix=... case.
It's possible that it's intentional to only cover one case, but
if so then it's not explained why.
4. The var name host_cc is likely incorrect and probably meant to be
"native_cc", judging by the assigned value "gcc".
5. "gcc" is used unconditionally in such case, without any way to use
a different native compiler (assuming that's indeed the goal).
A better approach is likely supporting --native-cc=... option which
defaults to $cc (which already defaults to "gcc") _before_
$cross_prefix is added in-front.
workflow:
- revert 'pinact for security' for readability
from 831c3fa184
tccpp.c:
- remove code that allows tcc to parse numbers incorrectly (*)
from 829c848520
tccgen.c:
- Revert "Relaxed the 'incompatible pointer type' warning a bit" (*)
from d9ec17d334.
tccrun.c:
- remove support for -nostdlib -run
for simplicity, we require "main" with tcc -run always
tccpp.c:
- Revert "Free all preprocessor memmory in case of error."
from c96f0cad61
Remove TinyAlloc->limit instead. Thus it can do also bigger
allocs. Big TokenStrings (like 200kb+ when compiling tcc)
may come from inline functions or from large initializers.
Makefile/configure:
- use --config-pie for configuring tcc output only
- use -fPIC with clang-x86_64 to avoid 32-bit relocs
libtcc.c:
- fix "tcc file.c -run" i.e. -run as last argument
i386-gen.c:
- PIC refactor
(*) sorry, but code in tcc should have a minimum of generic relevance
I tried several gdb/lldb options to debug libtcc generated code.
But gdb/lldb complained that they could not load symbols or
that module does not exist. There was also another problem. The
code itself was in memory (string) and gdb/lldb do not have
functions to acces it.
So I came up with a new api for debugging libtcc code.
First you enable debugging with: tcc_set_options(s, "-g")
Then compile the code with: tcc_compile_string_file(s, program, "<file>.c")
Then call tcc_relocate().
And finaly write the object file to disk: elf_output_obj(s, "<file>.o")
Now you can start the debugger and put an breakpoint after the
elf_output_obj() code. Then use gdb command add-symbol-file <file>.o
and from there on you can set breakpoints in the libtcc generated code.
You can also step/print variables/...
I could not find a simular function in lldb yet.
When debugging is done you remove the tcc_set_options(s, "-g").
All other code can remain because tcc_compile_string_file and
elf_output_obj do not output any file any more is debug is not set.
See also tests/libtcc_debug.c
Some targets (netbsd) require that code is
compiled with -fPIE.
i386-gen.c:
Lot of changes to load/store code
i386-link.c:
Set PCRELATIVE_DLLPLT depending on configuration
tccelf.c:
Change some relocations and add get_pc_thunk.o
Makefile lib/Makefile lib/get_pc_thunk.S:
Add new file get_pc_thunk.o
According to AAPCS64, when an argument requires 16-byte alignment
and is passed on the stack, the stack address must be rounded up
to the next 16-byte boundary.
TCC previously failed to perform this alignment check in gen_va_arg,
leading to data corruption when a 16-byte aligned argument followed
an 8-byte argument on the stack.
Note: This issue is most prominent on Mach-O/Apple Silicon where
variadic arguments are passed entirely on the stack. Testing shows
this fix resolves the failure on macOS while remaining compatible
with Linux/ARM64 (e.g., Raspberry Pi).
Modified gen_va_arg to perform a round-up (addr + 15) & ~15 when
align == 16.
When accessing a global symbol with an addend > 0xffffff, the AArch64
backend incorrectly encoded an 'add xr, xt, #0' (Add Immediate)
instead of 'add xr, xr, xt' (Add Register).
This resulted in the base address of the symbol being overwritten
by the offset value rather than being summed with it.
Fixes the issue where (sym + 0x1000000) would resolve to 0x1000000
instead of the correct memory address.
When calculating the difference between two pointers (TOK_PDIV), the
AArch64 and RISC-V64 backends used unsigned division
instructions (udiv/divu).
This patch moves TOK_PDIV to use signed division instructions (sdiv/div)
for both backends, ensuring correct behavior as per the C standard.
x86_64-link.c:
Check relocations R_X86_64_32/R_X86_64_32S. These relocations
can become to large if not configured with '--disable-static'
or '--config-pie' and code is run with -run -ltcc.
This only happens on x86_64.
tccdbg.c:
1) Add some .debug (dummy) sections when dwarf is used. These
sections are otherwise not relocated correctly for R_DATA_32DW.
2) Fix stab problem when reloc is applied twice.
I found some problems with a testcase from mailing list.
On x86_64 an overflow on reloc R_X86_64_32 occurred that was
not reported when using -run -ltcc.
The problem could be solved by compiling tcc with -fPIE, -pie
or --disable-static.
Makefile, configure, libtcc.c, x86_64-link.c:
- add --config-pie to configure help. Ignore -pie in libtcc.c
and check reloc overflow in x86_64-link.c
arm64-gen.c:
- Fix reading from constant like '*(int *)0x7fffb7f1280c'
elf.h, riscv64-link.c:
- fix for -run -ltcc. Ignore reloc R_RISCV_SET_ULEB128 and
R_RISCV_SUB_ULEB128 that are used in .debug_loclists section.
Add the define TCC_CUT_ON_INTEGER_LITERAL_OVERFLOW to use the most
significant digits of an integer literal before its parsing led to an
overflow.
When compiling tcc with another compiler, which is not able to handle
64 bit arithmetic, it is beneficial to use the last value before an
integer literal overflows. Parsing 0x1000000000000000 then results in
0x10000000. The mescc from GNU Mes is able to compile a first tcc on a
32 bit system without 64 bit arithmetic. This change allows this first
tcc to compile a second tcc with complete 64 bit arithmetic.
Placing the definition of "pure" prior to TOK_DEFINE would cause it to
be treated as a keyword by tccgen. This breaks building gcc, in which
"pure" is used as a struct field name.
The -run option did not support -nostdlib correctly.
The argc/argc/envp are now passed on stack according to sysv.
This implementation does not work for TCC_TARGET_PE.
Also arm64 does not work when running tcc compiled with itself.
This is because arm64 assembly is not implemented yet.
The following test code is used to check the code:
#include <unistd.h>
#include <sys/syscall.h>
void _start() {
syscall(SYS_write, 1, "hello world\n", 12);
syscall(SYS_exit, 0);
}
Run this with:
./tcc -nostdlib -lc -run a.c
make tcc_c
./tcc_c -nostdlib -lc -run a.c
Do not emit that warning when the source struct (recursively) contains destination struct as the first member. For example, in this case the warning would have been emitted before, and is not anymore:
struct base {
int a;
};
struct derived {
struct base base;
int b;
};
struct derived derived;
struct base *base = &derived;
I personally use that pattern in my code (in a bit more elaborate form) and so this change removes the warnings for those use cases, while still retaining it for everything else. Feel free to CC me on the mailing list if you have questions, suggestions or complaints.
When tcc -run is used with input file from stdin, then run_main's
stdin (which is tcc's stdin) is already EOF after we've read it.
If the program operates exclusively on stdin, then it cannot be used.
This commit adds an option -rstdin FILE which sets run_main's stdin.
Can also be used in such case to set run_main's stdin to the tty,
using -rstdin /dev/tty (posix) or -rstdin con (windows).
The tcc options behavior is non trivial, and it's also susceptible
to ambiguities - which do exist (but currently are not painful).
- Add a script 'optclash' which detects clashes/ambiguities.
- Document the parsing behaviour and current clashes/resolutions
as comments in libtcc.c .
tcc.h, tccgen.c:
Add and use IS_BT_ARRAY
tccpp.c:
free memory when size is 0 in realloc code
tccdbg.c:
move common code to seperate function remove_type_info
- include/stddef.h, tcctest.c
Revert "tests/tcctest.c: include stdint.h"
This reverts commit 8f23997ca7
We don't want tcctest.c to rely on system include files
- libtcc.c:
Revert "libtcc.c: Remove unused defines free and realloc"
To be unused is the point why they do exist
This reverts commit 2f88764100.
- tcc.c:
fix formatting of commit e73529865d
- tccpp.c:
parse_include(): print skipped include files too (with tcc -vv[v] file)
next_nomacro(): faster L"str" parsing
- tccgen.c: fix c2y if declaration:
* accept like GCC: if (int a = 0, b, c = x; c)
* accept as "TCC extension": if (int a = 0, b, c = x)
* "speak tcc" with symbol/function names
- README:
cleanup
There are install shell scripts around, often derived from X11 like
contained in glibc or Gash sources, which require to separate -m from
its value. Therefore add a space behind 'install -m' in the Makefile.
GAS selects default attributes for a section based on its name and makes
the sections .text, .init, .fini executable. The crti.s and crtn.s files
of musl rely on these defaults and don't set the "x" flag for the .init
and .fini sections. Unfortunately TCC does not care for .init and .fini
section defaults in assembler or C code. Fix this for assembler code.
Handle 'register long r10 __asm__("%r10")' without %, too. Using GCC
the % is optional. The musl source code does not use the % prefix.
The GCC source code uses both variants.
despite being defined in tcc's own stddef.h, intended to be included by
libtcc.h, libtcc.h actually included the libc's standard include
tested on musl
* 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)))
wanted by gdb to have global variables info on windows
Also:
tcc.h:
- move dwarf inline fns
- use dwarf as default for 64-bit platforms. GDB can't handle
locals info from stabs on 64-bit correctly (also not from gcc).
tccpe.c:
- use 's1' instead of 'pe->s1'
tccdbg.c:
- fix locals info problem on Windows where (unsigned long) s->value
is uint32_t and would not cast to long long correctly.
- tweak dwarf to have line info at begin of functions, otherwise
"gdb b main, r, n" would say "no line number info, single step..."
(see also objdump --dwarf=decodedline ...)
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.
... 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()
Currently debug size is big because some types are output multiple times.
Function scope was not treated correctly.
Rename anon(ymous) into forw(ard).
Compact string table by reusing names.
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
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)
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.
I updated the tests/gcctestsuite.sh a bit.
before:
3329 test(s) ok.
210 test(s) skipped.
168 test(s) failed.
28 test(s) exe failed.
after:
3331 test(s) ok.
299 test(s) skipped.
79 test(s) failed.
26 test(s) exe failed.
I found some small problems:
include/tccdefs.h: Add alloca definition for i386 and x86_64
lib/alloca.S/lib/alloca-bt.S: align i386 alloca to 16 bytes.
i386_gen.c vla code and gcc do the same.
x86_64-gen.c: fix typo in comment
arm-link.c: remove some casts
tccelf.c: code style and remove code
tccpp.c: use correct pointer size so cross compiling works
riscv64-gen.c: make code more readable
I tried to fix all remaining warnings/errors reported by -fsanitize.
The riscv64-gen.c is a bit large because it contained a lot of warnings.
I forgot some arm-link.c changes in last commit.
The other changes are all small fixes to avoid warnings/errors.
Tested code with:
clang -fsanitize=address,undefined,nullability -pie -fPIE -Iinclude -I. -g tcc.c -o tcc.tcc -lm -ldl -lpthread
./tcc.tcc -Iinclude -I. -b -g tcc.c -o tcc.tcc1 -lm -ldl -lpthread
Also checked on i386/x86_64 with -fsanitize=memory (others not supported).
arm-link.c: use read32le/write32le/add32le to avoid unaligned access
tcc.h i386-asm.c: fix signed left shift
lib/bcheck.c: Add _Atomic
libtcc.c: Correct MEM_DEBUG_CHECK3 to avoid unaligned access
riscv64-link.c: Fix R_RISCV_SET16
tccpp.c: Align tal_header_t to avoid unaligned access
tccgen.c x86_64-gen.c: avoid use of uninitialized value
There are still warnings reported:
tccgen.c:4031:13: runtime error: member access within null pointer of type 'TCCState' (aka 'struct TCCState')
tccelf.c:321:22: runtime error: applying zero offset to null pointer
tccelf.c:1132:23: runtime error: applying non-zero offset 169184 to null pointer
A lot of left shift of negative value warnings.
I ignored these for the moment.
Also the -run option does no work well with -fsanitize. It gets confused
because it does not detect that the generated code in memory is used
without -fsanitize option.
There are a lot more -fsanitize options. I did not find serious problems
with them.
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.
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
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.
The functions fetch_and_add_arm, fetch_and_add_arm64 and
fetch_and_add_riscv64 where removed with atomic change.
Replace the code in bcheck.c with call to atomic_fetch_add.
Use asm implements for i386/x86_64/arm/aarch64/riscv:
__atomic_load_[1,2,4,8]
__atomic_store_[1,2,4,8]
__atomic_compare_exchange_[1,2,4,8]
__atomic_test_and_set_[1,2,4,8]
atomic_thread_fence
atomic_signal_fence
atomic_flag_test_and_set
atomic_flag_test_and_set_explicit
atomic_flag_clear
atomic_flag_clear_explicit
`atomic.S` is extracted from `gcc` v15.1.0 `libatomic.a`.
And generated by https://github.com/kbkpbot/gen_atomic.git
tcc_set_str() already calls tcc_free() to free the memory of the stringpointer in s->outfile.
With the additional tcc_free(), the memory would be freed twice.
--
Regards ... Detlef
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 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.
cleanup libtcc.c:tcc_set_linker()
cleanup tccelf.c:tcc_load_ldscript()
Also
- tccrun.c, tccelf.c:relocate_syms():
with tcc -run -nostdlib, do resolve but only from explicitly
on the command-line given libraries.
- tccgen.c: optimize UMOD x % c -> x & (c-1) for c = 2^n
- tcc-doc.texi: cleanup
- tcc.h, tccpp.c, libtcc.c: add 'size' arg to pstrncpy()
Also reorder functions in libtcc.c a bit.
9 files changed, 556 insertions(+), 617 deletions(-)
Aka 'intmax_t', as recommended by newer standards.
For example
if (-0x80000000 < 0) is false,
but
#if (-0x80000000 < 0) is true
because in C, 0x80000000 is an unsigned int, Whereas in
a preprocessor expression, it is a signed long long, even
without LL suffix.
Oviously what the patch wants is... on Windows, with
"tcc c:/dir/xyz.dll -run file"... pass the absolute
path of the dll to LoadLibrary() which can make sense
in situations.
Other changes in the patch to other platfurms seem to
have no effect. This reverts 52a9a541b0
except 2 lines in tccpe.c.
Also revert _Float16 patch a06c608625
As long as tcc does not really handle _Float16, we can just define
it in tccdefs.h.
Also move uint128_t to tccdefs.h for same reason.
Update github action (might fix random arm64 crashes)
arm-asm.c: add forward branches & some ops
lib/armeabi.c: faster i/udivmod (asm)
arm-gen.c: use movw/movt to load constants for CPUVER >= 70
configure: use dwarf-4 debug sections on android, detect idiv
lib/Makefile: always add -I$(TOP) for access to config.h
tcdbg.c: add a "code mapping symbol" to help out llvm-objdump
tccelf.c: don't load SHT_ARM_EXIDX, modify ARM.attributes
tccpp.c: accept '@' for arm asm comments
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
TCC treats -nostdlib and -Wl,-nostdlib as equivalent, but on other compilers
which call a discrete linker, -nostdlib behaves as on tcc (not adding
startfiles/libc/endfiles) by modifying the ld command line, but -Wl,-nostdlib
adds -nostdlib to the ld cmdline, which stops the linker searching the default
directories for libraries.
Noticed this when the crt1.o file on an updated riscv had a
text section where the size is not multiple of align.
This file is loaded first and when the c code is then compiled
the code is not aligned any more.
This results in:
alignment of code section not multiple of 4
in riscv64-gen.c
In x86_64-gen.c/i386-gen.c, gfunc_call will generate structure store
for bt == VT_STRUCT. Before generating any code, it is needed fetch
cpu flag.
As #ifdef TCC_TARGET_PE, gfunc_call() forgot to do this.
when there are no other errors then exit tcc with the exit cude
from tcc_run() (messed up in dd2e5f8b06)
Also in tccrun.c, use a more exotic random value to replace zero
with 'exit(0)' in user code (because lonhjmp(jb, c) needs c != 0)
There was a duplicate definition of LDBL_MAX_EXP, which this commit
removes.
There was a missing definition for LDBL_MAX_10_EXP, which this
commit adds.
I've confirmed the value of LDBL_MAX_10_EXP using gcc on an AARM64
Debian system (gcc 8.3.0). I've only indirectly confirmed the value
on RISCV (using "#if ... #error" on godbolt.org). I'm reasonably
sure this update is correct, but someone should confirm it before
merging to "mob".
Commit a522213 ("tccpe.c: never assume static...") removed the global
-I$(TOP) for cleaner lib build, and ensured that it is added for
bcheck.c as it now includes config.h, but forgot that bt-exe.c also
needs config.h, as it includes ../tccrun.c which includes it.
Also, the explicit tccrun.c prerequisite for bt-exe.c is not required,
as all *.o lib files depend on $(TCC), which depends on libtcc, which
depends on tccrun.c .
Also, at win32/built-tcc.bat, while bcheck.c needs -I.. for config.h,
bt-exe.c doesn't, as ../tccrun.c does find it where it expects it.
just clear s1->static_link before loading msvcrt etc.
Also:
- configure: get cc_version/name when making a cross compiler too
- configure: fix android triplets
- Makefile: remove CONFIG_TCC_CROSS, check TCC_TARGET_xxx instead
- libtcc.c: parse some linker option arguments more correctly
- tccelf.c: fix a versym problem with clang on android
- lib/Makefile, build-tcc.bat: bcheck.c now includes config.h
Elsewhere at configure the value of $mingw32 is expected to be
exactly either yes or no (not empty, not caps, etc), and while it
complies internally, it also accepts arbitrary override value.
Clarify acceptable values, and simplify the parsing.
Add very few missing quotes where IFS/globs were applied to arbitrary
user input (commands, arguments, but not assignments or case $var in.
In fn_makelink $dn/$2/$f don't have IFS/globs).
While configure now handles it correctly, there are 2 issues:
- eval opt=\"$opt\" coalesces IFS chars (--prefix="$HOME/x y").
- Even with the eval removed, (gnu) make still fails to find it.
I made few quick experiments with quoting these values in config.mak,
but that had no impact, and make -d was not helpful. Was worth a try.
So no spaces in paths, but at least configure can handle the src path.
$confvars is not supposed to hold the same key more than once, and
spaces in values won't be parsed correctly. Additionally, it's later
iterated using shell IFS-split - which will also apply globs.
We now abort if the value IFS-splits badly (spaces/glob/empty).
We now warn on duplicates, but still accept them like before.
Example duplicate: --enable-static --disable-static
Example spaces: --config-foo="bar baz"
Example glob: --config-foo=" * "
Note that globs currently already expand at eval opt=\"$opt\"
before we get a chance to test it (but we still detect the spaces).
See commit message of 21272067 (boilerplate var=..) about removing it.
These tests are also performed on values which configure itself adds,
but currently there are no issues with those.
Also, default_conf() now uses confvars_has, which fixes the following:
- False-positive if the key is a substring of existing key or value.
- Incorrect test if the value contains '=' or sh pattern chars *?[] .
No-op, because current default_conf calls don't have such issues.
Trivial, but less noisy when reading, and nicer for new code.
The code still adds the value[s] unconditionaly without checking for
duplicates or spaces in values - both are bad, but next commit will.
Add and use "assign_opt" instead of copy-pasting subshell assignment.
Slightly faster, and fixes option values with consecutive spaces,
for instance --libdir='/foo bar' where previously `echo $opt | ...`
coalesced IFS chars because $opt was unquoted. (this is still very
likely to break, but at least now not at the options parsing).
Unrelated note:
The code does eval opt=\"$opt\" for every argument, to "reproduce
autotools behavior" (commit 2e7a1af, 2012-06-12, Thomas Preud'homme).
This is questionable, and not fun (try: --config-x='"; echo "PWNED').
I emailed the author for more info, but didn't get a reply aftre few
days, and without real-world use cases, I think it should be removed.
The vast majority of shells do support "local", but not all, notably
AT&T ksh (default sh in illumos-based distros and Solaris), but also
some other POSIX-compliant shells, so remove "local".
print_str(), print_num() are modified trivially.
default() now uses standard "Assign Default Value" - same semantics,
and works in all shells (and POSIX).
default_conf() is identical to before, but it had and still has few
minor issues, which will be addressed in a future commit.
Shells do support those, and typically simple forms do work, but
these were removed in POSIX 2024 because they are notoriously hard
to parse correctly, and shells don't always agree on the result.
Instead, use standard forms which all shells support identically.
Extreme high level overview of quotes in POSIX shell:
- WORDs without $... or glob don't need quotes (echo, =, no, x86, ...).
- a= b=foo c=$... and case $d in ... all don't need quotes.
- IFS/glob affect command and arguments (not assignments or case..in):
- IFS only splits direct result of $..., quotes will prevent that.
- Glob then splits/matches *?[] and quotes will prevent that.
POSIX "test" (see Application Usage), and shell language (quotes):
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/test.htmlhttps://pubs.opengroup.org/onlinepubs/9799919799/utilities/V3_chap02.html
My own quick guide:
https://gist.github.com/avih/6752ad1e20b334b56fef120cd09c766e
Commit 729918e ("make: make shorter command lines", 2024-11-21) added
"-static" when $cc_name is gcc to statically link with the mingw gcc
runtime, so that tcc.exe won't depend on additional non-system dlls.
However, $cc_name is still the default value at this time - gcc,
so "-static" was unconditional, and it failed if $cc is tcc (msvcrt).
This commit instead checks the already known $cc, and restores the
ability to build tcc using tcc (if "$cc" doesn't contain "gcc").
Put former NATIVE_DEFINES into config.h. Such tcc can be run
and tested directly from source more easily, like for example:
tcc -run tcc.c -B. -run test.c
Also:
- tccelf.c: cleanup
- tccpp.c: avoid stupid clang warning
- configure: reduce -Wno- switches
- tcc.h: inline wait/post_sem()
- tccpe.c: simplify import (assume STT_NOTYPE is function)
This is a very stripped down version[1], with only CommandLineToArgvW
(typically used with GetCommandLineW() - which we already have),
ShellExecute and FindExecutable, which don't require any new structs,
and where used constants already exist at our winuser.h .
Pretty cheap, and hopefully covers some meaningful new use cases[2].
Requires linking with -lshell32 .
[1] original full version:
http://download.savannah.nongnu.org/releases/tinycc/winapi-full-for-0.9.27.zip
[2] Can now build "less" for windows - https://github.com/gwsw/less/ .
Add -luser32 to LIBS at Makefile.wng (mingw makefile), then (gnu make):
make -f Makefile.wng CC=tcc less.exe
The previous code had few issues:
- Didn't quote an empty string.
- Didn't quote if the string contains tabs.
- Didn't take into account existing backslashes at the string.
E.g. previously broken (in POSIX sh, like cygwin or busybox-w32):
- tcc -m 32 test.c -D 'CSTR="foo'$'\t''bar"' (wrongly rejected by tcc).
- tcc -m 32 test.c -D 'CSTR="foo\"bar"' (incorrect CSTR at test.c).
Both issues are fixed with the new code, and presumably any others.
The empty/tabs issues could be fixed within the current code, but the
backslashes issue is not worth shoehorning it, so this is a rewrite.
I happened to bump into thsese, but I didn't try to review the file,
and there may be other places which could be similarly improved.
This is originally my suboptimal code from commit 100f94be
(tiny_libmaker: more robust arguments interpretation), so, a bit late,
but let's improve it anyway.
Before VC2005, the time macros (time, time_t, localtime, etc) were
32 bit on 32 bit platforms, but they became 64 in VC2005.
This works even on XP 32 (_time64 etc do exist in XP32 - and in tcc).
However, tv_sec in struct timeval (which for msvc is in winsock2.h)
remains 32 bit to this day on 32 bit platforms, and dlls which were
not recompiled remain with time 32, possibly at the API boundary.
Due to these, and maybe more, mingw w64 decided to keep the time
macros 32 bit on 32 bit platforms, with __MINGW_USE_VC2005_COMPAT
override (which does nothing in mingw w64 except time -> time64).
It's not perfect, but it allows some existing code to easily switch
to 64 bit time without redefining time etc, e.g. used by libressl:
https://github.com/libressl/portable/blob/master/README.mingw.md
Before, it was impossible to enable the 64 bit time macros in tcc 32.
This commit adds support for __MINGW_USE_VC2005_COMPAT in tcc as well,
which, like in mingw w64, affects only the 32->64 time macros, and is
a cheap way to get 64 bit time in existing code in some 32 bit apps.
The additional #ifndef _USE_32BIT_TIME_T is unrelated to the override,
and avoids a warning (and nothing else) when the code explicitly
defines it - which is allowed in MSVC, and also guarded in mingw w64.
Relevant current quote from the libressl link above:
------- >8 ---------
Why the -D__MINGW_USE_VC2005_COMPAT flag on 32-bit systems?
An ABI change introduced with Microsoft Visual C++ 2005 (also known as
Visual C++ 8.0) switched time_t from 32-bit to 64-bit. It is important
to build LibreSSL with 64-bit time_t whenever possible, because 32-bit
time_t is unable to represent times past 2038 (this is commonly known
as the Y2K38 problem).
If LibreSSL is built with 32-bit time_t, when verifying a certificate
whose expiry date is set past 19 January 2038, it will be unable to
tell if the certificate has expired or not, and thus take the safe
stance and reject it.
In order to avoid this, you need to build LibreSSL (and everything
that links with it) with the -D__MINGW_USE_VC2005_COMPAT flag. This
tells MinGW-w64 to use the new ABI.
64-bit systems always have a 64-bit time_t and are not affected by
this problem.
with -Wl,-oformat=binary, executable code should come first.
(for linux kernel image for example)
Also:
- simplify RELRO sections: create them as readonly, but add
SHF_WRITE flag later when needed (i.e. relocations do exist)
- tcc.h etc: exclude eh_frames on non-elf platforms
- tccelf.c:tcc_load_object_file(): don't load debug sections when
linking without -g (special dwarf case in relocate_section()
wont work when dwlo/hi were not initialized).
- tcc.c: avoid loop if something fails (ret < 0) without message
(while failing without message should not happen either)
- tccelf.c:tcc_load_alacarte: give message
- tccpp.c: treat '# 123xyz' in asm file as comment
- lib/Makefile: cleanup
- libtcc.c: tcc_add_library(): fallback to try filename as is
(also remove tcc_add_library_err())
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.
- 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
This requires adding .eh_frame and .eh_frame_hdr sections.
There are 3 new functions to setup the sections:
tcc_eh_frame_start: create cie in .eh_frame
tcc_debug_frame_end: add fde in .eh_frame for every function
tcc_eh_frame_hdr: create .eh_frame_hdr
The PT_GNU_EH_FRAME header is created.
The dwarf read functions are moved from tccrun.c to tcc.h
The backtrace() function is not supported on all targets.
windows, apple, bsd and arm are disabled.
arm uses its own sections .ARM.extab and .ARM.exidx.
endbr64 has no operand but comes with a ModR/M byte. Handle it in the
same way as *fence instructions.
Co-authored-by: Yao Zi <ziyao@disroot.org>
Signed-off-by: Yao Zi <ziyao@disroot.org>
Signed-off-by: John Nunley <dev@notgull.net>
It has the same effect as call.
Co-authored-by: Yao Zi <ziyao@disroot.org>
Signed-off-by: Yao Zi <ziyao@disroot.org>
Signed-off-by: John Nunley <dev@notgull.net>
We already have sys/unistd.h, but the standard place for it is at
the include root, so make that work too, but keep sys/unistd.h for
backward compatibility.
Since commit 45cff8f0 tcc eventually generates object files
of non-even size.
tccelf.c:
- check ARFMAG for better invalid archive detection
- file_offset needs to be aligned, not the size (just a nitpick)
lib/Makefile:
- remake everything when tcc did change
compiling with tcc and linking with gcc gives error:
tcc -c a.c
gcc a.o
usr/bin/ld: a.o: .symtab local symbol at index 0 (>= sh_info of 0)
/usr/bin/ld: a.o: error adding symbols: bad value
collect2: error: ld returned 1 exit status
Solved by moving call to sort_syms.
Instead of always emitting movabs, emit a regular mov or a xor.
Slims down sequences like:
movabs $0,%rax
mov %rsi,%rax
To:
xor %eax,%eax // also zeroes upper word
mov %rsi,%rax
Future work is to just emit:
xor %esi,%esi
Use `t1` instead of `t0` for the cases when `rr` is not set so `t0` is
used by default and this happens:
lui t0, XXX
add t0, t0, t0
Instead, now we do:
lui t1, XXX
add t0, t0, t1
This commit fixes the case where the register of for the Extended Asm
input or output is known. Before this commit, the following case:
register long __a0 asm ("a0") = one;
asm volatile (
"ecall\n\t"
: "+r" (__a0) // NOTE the +r here
);
Didn't treat `a0` as an input+output register (+ contraint) as the code
skipped the constraint processing when the register was already chosen
(instead of allocated later).
This issue comes from f081acbfba, that was
taken as a reference in every other Extended Assembler implementation.
NOTE: In order to be able to deal with general-purpose vs floating-point
registers, this commit adds a flag in the 6th bit of the register. If
set, it means the register is a floating-point one. This affects all the
assembler.
Before:
ld rd, rs, imm
sd rs1, rs2, imm
Now:
ld rd, imm(rs)
sd rs2, imm(rs1)
NOTES: Just as in GAS:
- In stores the register order is swapped
- imm is optional
- when imm is not included parenthesis can be removed
- tccgen.c: cleanup switch data etc. after errors (*)
- tccpe.c: faster get_dllexports (*)
- tccpe.c: support -Wl,-e[ntry]=... (*)
- libtcc.c: win32: use ANSI functions (GetModuleFileNameA etc.)
- tccrun.c: be nice to tcc-0.9.26 ("struct/enum already defined")
- tccpp.c: be nice to tcc-0.9.27's va_start/end macros
(*) suggested by Robert Schlicht
https://lists.gnu.org/archive/html/tinycc-devel/2024-03/msg00012.html
See test. We need to use 'ind' from later when the address
field of the instruction is put.
Also: fix crash when the substracted symbol is undefined
Also: assume asm-symbols to be lvalues (except func/array)
Apple needs CONFIG_RUNMEM_RO=1
I now only set CONFIG_RUNMEM_RO=0 on _WIN32
Openbsd does not have malloc.h so remove some code
Also fix some warnings when compiling lib with gcc
- LIBTCCAPI int tcc_set_backtrace_func(void *ud, ...)
accept opaque user data pointer,
- tcc -vv -run... : show section info
- use memalign() to allocate runtime memory
- printline_/dwarf : pass output to parent function
- tccpe.c : fix -nostdlib -run
- --config-backtrace=no : make it work again
- 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)
tcc failed to run with bounds checking enabled because the functions
rt_wait_sem, rt_post_sem and _rt_error where defined twice.
This is solved by making them weak in tccrun.c
Also a nested lock was present when setting TCC_BOUNDS_PRINT_CALLS=1
This is solved in lib/bt-exe.c by moving lock/unlock code.
Also added a testcase in tests/Makefile to test tcc with bounds
checking enabled.
- abort with notice when tcc_relocate() is called with the
former two-step method
- support backtrace & bcheck not only with tcc_run() but also
for directly called functions from tcc_get_symbol(); enable
witn 'tcc_set_options("-bt/-b");'
- move struct rt_context and debug sections into compiled code
for TCC_OUTPUT_MEMORY also
- protect access (g_rc) with semaphore
Also:
- add armv7/aarch4/riscv64 github tests (qemu emulated)
- win32/build-tcc.bat: build cross compiler only with -x
- 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
removed second argument for tcc_relocate(s). previous
'TCC_RELOCATE_AUTO' is now default and only behavior.
Rationale:
In the past, the option to compile into memory provided by the
user was introduced because only one TCCState could exist at a time.
This is no longer a limitation. As such it is also possible now to
keep any number of compiled code snippets around together with their
state in order to run them as needed.
- Also
- LIBTCCAPI tcc_get_error_func/opaque() removed
- tccrun/SELINUX: switch rx/rw mappings such that rx comes first
(risc64-link.c:relocate_plt() does not like got < plt)
- tcc_relocate_ex(): free local symbols and obsolete sections
to reduce memory after tcc_relocate()
When using libtcc it's reasonable to be able to use the application's
memory allocator for all allocations, including tcc_new(), and including
#define MEM_DEBUG
Ideally the allocator would be stored in the TCCState, like TCCErrorFunc.
That would imply a new API tcc_new_with_allocator(), but more importantly
would require all uses of tcc_malloc(x) to be changed to s->tcc_malloc(x).
That's a non-starter in my book.
Instead I refactored the memory management code so that all allocations
flow through tcc_realloc(). Which simply calls a function pointer, the
default value of which is the previous tcc_realloc().
It then becomess trivial to install a new allocator with the new function:
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc realloc);
The resulting code adds the trivial cost of an additional function call
per allocation/free. It also doesn't distinguish between malloc failure
and realloc failure, but since both just fprintf then exit() that seems
unimportant to me.
On the plus side the preprocessor magic is much more clear. The diffs
don't hightlight that, but take a look at the result to see if you agree.
All tests passed on my x86 linux box.
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)
In `load` and `store` RISC-V gen used `type_size` to retrieve the size
of the types being moved around, the problem with that function is it
tries to obtain internal information of the type. When using `type_size`
with a `char *` it returns 1, and emits a `lb` instruction when using a
conditional expression like so (but probably also in other cases):
char *a, *b;
b = "hello";
a = x ? b : "" ; // this emits an `lb`
That `lb` clobbers the pointer, only loading the latest byte of it:
// if `b` was, say: 0x1f822e
a = b;
// now `a` is 0x00002e
NOTE: We spotted this when building make-3.82, in `init_switches`
function in the `main.c` file. This error made `make` unable to
run long options like `make --help` (segfault when doing the
`strlen` later)
This happens because a `char *` is internally stored as a `char[1]` or
something similar, it's result is the size of a `char` (1) times the
size of the array `1`. This is not what we want, we are copying the
pointer, not the array itself. Using `type_size` for this is not
appropriate even if it works for some cases.
If the conditional expression is rewritten to imperative style using an
`if` it works properly, so it might be related with the fact the pointer
is `load`ed to a register.
`load` and `store` should only work with integral types, so reading the
size of the array is not useful. This commit creates a simpler version
of this function that only reads the integral type of what's working
with: char * is considered just a pointer. So it makes an `ld` instead,
and the code above works.
add nop
fix asm_emit_i immediate check (negative offsets were missing)
fix check for IM12S
remove non-existent instructions (example: slli64 is just slli with imm=0)
After the change to DT_NEEDED I get warnings for some functions.
The reason is that libc.so on my machine contains:
GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
Before the change to DT_NEEDED we solved the symbols because the
/lib64/libc.so.6 file has as DT_NEEDED set for ld-linux-x86-64.so.2
The above AS_NEEDED section was not followed so symbols in this
file gives a warning.
Currently fixed by including AS_NEEDED files.
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.
Recursive loading of all references can break linking of libraries
(Example: building of netbsd-curses)
Thanks grischka, Michael and Herman for the comments.
--
Regards ... Detlef
macOS builds with --disable-static fail to link if the version number
contains letters because of the -current_version and
-compatibility_version arguments (current version is 0.9.28rc).
This commit adds a new MACOS_DYLIB_VERSION variable to config.mak for
builds that target macOS. It has no impact on other targets.
Enables code such as:
#undef NDEBUG
#include <assert.h>
#include <stdint.h>
static int st_x = 42;
static int st_x_ __attribute((alias("st_x")));
int main(void){ assert((uintptr_t)&st_x == (uintptr_t)&st_x_); }
which would previously fail with no compiler warnings. The limitation of
this is that the alias must be done (or redone) after an actual definition.
An alias done right after a later overridden tentative declaration won't
work (sufficient for my use case).
echo "void bugged() { do {} }" | tcc -run -
now produces the sensible: -:1: error: 'while' expected (got "}")
I believe (but am far from sure) that the additional use of &tokc is ok.
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
On windows, create a .pdb file with option "-g.pdb"
Such executables created by tcc can be debugged with
"ollydbg" or "x64dbg"
This currently relies on the 3rd party tool cv2pdb from
https://github.com/rainers/cv2pdb
which again relies on
mspdbsrv.exe mspdbcore.dll msobj80.dll mspdb80.dll
from a MSVC installation.
cv2pdb.exe + the ms* files may be put in the path or in the
same directory as tcc.exe.
libtcc.c:
- revert "Small patch to allow..." (someone's personal easteregg)
(see da3a763e97)
- check return value from macho_load_tbd/dylib
tcc.c:
- remove help for "not yet implemented" option
tccelf.c:
- check PIE's for "unresolved symbols"
tccgen.c:
- avoid int->double->int cast
(see a46372e910)
- fix constant propagation with pseudo long doubles
(must mask out VT_LONG from type)
- cleanup find_field() (again)
tccpp.c:
- disallow strings and double constants in #if expressions
win32/include/uchar.h:
- change file mode
using (modified) tcc_backtrace() instead.
Also
Also fix the original bug with doubles on x86_64.
(which was not caused by incr_offset() actually).
See 598134fff6
Also cleanup on_exit() stuff
From fef701b57f
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
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
defined tokens for C, M, Ziscr extensions.
separate the base RV32 instructions from the RV64, for potential future
re-use in a RV32-only assembler, from which the RV64-tok can #include
scall, sbreak have been renamed (page 7 of spec),
necessitating some renaming in riscv64-asm.c
riscv-spec-20191213.pdf was used,
in which the "V" extension is not yet ratified.
available under https://riscv.org/technical/specifications/
Tables 16.5–16.7 do not list any "scall"
neither does the privileged spec
3 additional tokens not present in the tables were removed
note that this riscv64-asm.c still contains defects, which will
be addressed in another commit
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)
In order to detect a "same file" faster, this makes one
restriction to the feature: the basenames are required to
match at least (as in "test.h" and "dir/../test.h")
Also remove obsolete 'pp_once' (cached includes do not persist
across compilations anymore anyway)
This rewrites commits
30fd24abd44e363a1728
3 files changed, 38 insertions(+), 74 deletions(-)
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.
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)
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.
avoid memory leaks with lost CStrings on stack after errors.
tccpp.c:
- use/abuse static Cstring tokcstr where possible
tccgen.c:
- use/abuse static Cstring initstr where possible
tcc.h/libtcc.a:
- add 'stk_data' array to track memory pointer on stack
- add macros stk_push/pop() and cstr_new/free_s()
tccasm.c:
- use that
- use char[16] instead of char* for op.constraint
This avoids 'exit(1)' with errors outside of compilation
(nasty in particular with libtcc usage)
As a sideeffect multiple errors can be seen for linker
errors (such as undefined symbols, relocation errors, ...)
tccgen.c:
- allow cross-compiling 0.0L (cross-compile tcc with tcc)
tccelf.c:
- use alignment of TLS section for PT_TLS
tccpp.c:
- support long double constants on systems that do not support
long doubles (i.e. mark them (VT_DOUBLE | VT_LONG))
tccdefs.h:
#define __has_feature() for android
remove _unaligned (why define a msvc extension under !_WIN32)
Value 0 and values >2GB where printed wrong during tests with yarpgen (v1)
Starting the output with a hashtag make it compatible to TAP
--
Regards ... Detlef
These extensions where used by other compiler
to generate different code on old cpu's (arm and x86 before pentium/pentiumpro)
to prevent processor exceptions / very high delays when accessing an unaligned pointer.
--
Regards ... Detlef
if we include standard headers on glibc-based systems then
we can't use '__attribute__' (those are defined away for unknown
compilers) but must use '__attribute' (or #undef that token).
tccgen.c:
- just track local_stack for small scopes (can't declare variables)
- fix a vla problem with nested scopes
- move debug N_L/RBRAC into curly braced block
Also:
- tccpp.c: move 'label_...' functions to tccgen.c
- tccpp.c: let get_tok_str() say "<no name>" for anonymous symbols
- tcctest.c: let __pa_symbol() work for memory > 2GB
- 119_random_stuff.c: revert strtoll test (no reason to test libc)
- tccdefs.h/tcctest.c: enable bit fncs for _WIN32
- Makefile:
- use i686-linux-gnu instead of i386-linux-gnu for cross-i386
- update 'make help'
- revert umplicit 'make all' with 'make install' (but print warning)
instead in vcheck_cmp(), pass the CODE_OFF_BIT to generators
unless other nocode purposes are set.
This reverts commit cad8739594.
Also in 128_run_atexit.c:
avoid line output disorder which may happen on windows when
tcc itself and runned code are using two different printf
implementations and tcc would print the "[Returns 1]" above
any output from the runned test.
The generated code by yarpgen failed. I traced the problem to
expr_landor. The problem was that nocode_wanted was removing
too much code.
See also testcase 33.
the casted type was lost when a delayed bool was finally converted
to a value. See testcase, in the wrong case the '(unsigned int)' cast
was ignored, and hence the division was signed reulting in -1 instead of
the proper 0x7fffffff.
The following code:
typedef struct {
unsigned int a __attribute__((nodebug));
unsigned int b;
unsigned int : 32;
unsigned int c;
} tst;
Supresses a and also suppresses bitfield padding.
So debugger shows only b and c in above example.
the code in expr_cond save nocode_wanted around some parts of
expression evaluation, but at the wrong spots. If the evaluation
of the condition itself (e.g. in the testcase the first whole ternary
expression) resulted in CODE_OFF, then that was saved, and restored
before return, even if in-between codegen would have CODE_ON'ed already.
Thus the whole CODE_OFF state bled out to outside the expression
evaluation and also disabled the whole if-block. Found by yarpgen v1
(seed 64).
we activate code (CODE_ON) only when the target labels are used,
which doesn't happen during nocode_wanted regions. So, we cannot
just switch off code either during nocode_wanted regions, nothing
would switch it on again (except in the happy coincidences when we
outright save/restore nocode_wanted). See the testcase for one
example, reduced from code generated by yarpgen: in
ext = (xxx || 1) // #1
|| ((xxx && 1) || 1) // #2
code is first suppressed in #1 normally, then (before this commit)
was suppressed via CODE_OFF during #2 (via indirect gjmp),
then the suppression from #1 was undone, but nothing undoes the
suppression from #2 anymore as everything therein was generated
while nocode_wanted was active.
So, we would either need to save/restore nocode_wanted around
some more expressions, activate CODE_ON also with unused labels (breaks
some optimizations we want), or deactivate CODE_OFF only when not
already in nocode_wanted state. This does the latter.
Sym.sym_scope and Sym.f (FuncAttr) share space, so blindly setting
one clobbers the other. Right now this only leads to missing errors
on incompatible typedefs (see testcase), which this commit fixes.
But it points to a larger problem:
Generally we can only manipulate Sym.f for anonymous and field symbols,
not for anything that has a top-level name (basically any proper decl),
because the latter use sym_scope. Luckily the functions type always
contains an anonymous symbol (in sym->type.ref), so we can use that.
But some of the functions attributes actually _do_ apply to the decl,
not the type (e.g. always_inline), so we still have a problem possibly,
when we update an pre-existing type that may already be shared with
another decl.
Would need untangling and perhaps using accessor functions that check
that Sym.f and Sym.sym_scope aren't used for the same symbol.
I have a testfile created by YARPGen (seed=9), which displayed
a negative bss size without this patch.
* tcc needs also a bigger VSTACK_SIZE (i used 512)
--
bye bye ... Detlef
I have a testfile created by YARPGen (seed=9), which displayed
a negative bss size without this patch.
* tcc needs also a bigger VSTACK_SIZE (i used 512)
--
bye bye ... Detlef
The last commit was not a problem with macos.
The problem was that dwarf version < 5 uses different indexes for
files and directories.
They start at 1 for dwarf version < 5 and 0 for dwarf version >= 5.
In tcc_load_object_file use unsigned long for size/offset.
This avoids strange sizes of sections in case of overflow.
The sections that are now larger then 4G may not work.
This avoids a hang on macos in realloc.
On macos we cannot use the ar because is does not support elf files
and then does not generate a symbol table.
The solution is to use 'tcc -ar'. The problem now is that some
pacages first built an archive with 'tcc -ar c' and later extracts
the archive with 'tcc -ar x' and built with this a dylib file.
The 'tcc -ar x' failed. So I implemented it. I also added the t
option because it was simple to do,
With these option I can now built several packages without problem.
There are a lot of options we can add so I tried to implement the
minumum.
Add the following options:
dynamiclib same as -shared
flat_namespace default/ignored
two_levelnamespace ignored
undefined default/ignored
install_name name of dynmic lib
compatibility_version version dynamic lib
current_version version version dynamic lib
-Wl options:
all_load same as whole-archive
force_load same as whole-archive with lib
single_module ignored
Export now all global symbols in export trie instead of only text
symbols.
I wrote too much data into dylib file because I did not check
for sk_unknown/sk_discard/sk_uw_info.
Simplified code in tccrun.c
Needed when using ...libtcc1-usegcc=yes in lib/Makefile.
lib/bcheck.c: Add __clang__ for pragma diagnostic
lib/bt-log.c: Add pragma diagnostic as in lib/bcheck.c
lib/builtin.c: Add a lot of alias code to allow building with gcc/clang
lib/stdatomic.c: Same as lib/builtin.c
lib/tcov.c: Avoid clang compiler warning
Update configure and remove dll=no for Darwin.
Also removed dwarf=$dwarf because this is not a config option.
In tccelf.c only add __PAGEZERO if stabs and executable.
In tccrun.c correct rt_printline_dwarf code for dll.
In tests/Makefile disable dlltest with PIC for Darwin because object
format of .o file is still in elf.
In tccmacho.c add dll support and and rpath support.
Corrected trie code. For some reason symbol 'xx' should be after 'xx1'.
Corrected weak symbol support for old macho code.
Used R_JMP_SLOT instead of R_DATA_PTR in check_relocs.
I tested on macos 10, 11, 12 and 13 that old and new macho code work.
I do not know when this new format is introduced but it is now
available on a lot of versions. So make it the default.
Also default to dwarf=4 because stabs and dwarf=5 is not supported.
The test failed because atexit/on_exit code was not correct.
Make it look more like the g_exit_context.
Added a sleep to libtcc_test_mt to allow overlap of threads to
detect this problem.
The last commit only worked on arm64.
The problem was that the new __DWARF segment was empty.
I now remove the __DWARF segment if it is not needed.
This resolves the rebase problem on x86_64.
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.
lldb now works with this push.
In tccmacho.c add S_ATTR_DEBUG to all debug sections.
Add __DWARF section and rearange struct skinfo.
In tccdbg.c The first filename in dwarf_line can not be used.
Also had to fix structure/union/lexical_block/subroutine to
allow empty childs.
dwarfdump --verify complained about this.
The problem is that %n in *printf functions require a format string
that is in a read only section. See man page.
So added __DATA_CONST segment and mapped rodata_section into this segment.
Also added __got to this segment.
Change maxprot of segments to the same values used by clang.
See: https://savannah.nongnu.org/bugs/?58606
and: mpfr-4.1.1/tests/tcmp_ui.c
The code '__builtin_constant_p ((i++, 7))' was not working.
I Fixed it in tccgen.c
I added a testcase in tests/tcctest.c. I also wanted to add a test like
'__builtin_constant_p ((10, 7))' but gcc needs -O1 for that to work.
clang (and now tcc) work as expected.
Fix for external functions as pointers in data section.
See testcase 119 and tccmacho.c in check_relocs.
Make bind/rebase code faster in bind_rebase_import.
- Move reloc check out of loop
- Because relocs are sorted we can do bind/rebase by page.
Change name head into seq in trie code.
Remove unused code in bind_rebase.
I removed the FIXME for generating trie code with working code.
I also fixed a problem where:
cc -g -c a.c; cc -o a a.o
created a bind/rebase error because the second cc did not use -g
and .debug sections where not checked correctly.
I also removed the elfinterp printout in tcc.c when
TCC_TARGET_MACHO is set.
- remove calls to "find_..." for stuff that we know to exist and where.
- rename find_section_create(s1,name,0) -> have_section(s1,name)
Also:
- call update_gnu_hash() from elf_output_file()
gnu_hasn() functions could be moved down into an already existing
!ELF_OBJ_ONLY clause, but in order to avoid too many diff lines
I didn't.
- avoid 'long' (elf_hash). sizeof (long) is host-dependent (4 or 8)
- remove unnecessary checks (for dynsym, versym).
Someone reading "if (dynsym == NULL) ..." must conclude that it
actually can happen under certain circumstances, or otherwise,
might conclude that the person who wrote that felt unsure what's
going on exactly.
arm64-gen.c:
TCC_TARGET_MACHO instead of __APPLE__ (to support cross-compilers
for the apple/M1 target)
Add --config-codesign option to run codesign on apple to sign executables.
See configure and Makefile
In tccmacho.c use codesign option to call codesign application.
Add build_version/source_version
Sort sections in __LINKEDIT the same way as llvm does.
Add simple support for trie code. Need some more attention.
Fix rebase/bind error.
Apple has a new object format that uses chained fixups.
I have implemented this with a configure option '--config-new_macho'
See configure and Makefile
tccmacho.c contains the biggest change.
I split the lazy_bind_rebase structure into lazy_bind and rebase for the
old format.
Under the macro CONFIG_NEW_MACHO there is the new macho format code.
In arm64-gen.c we do not need to push all registers on stack for
variadic functions. variadic parameters are pushed on stack for apple.
There is still one open isue. The export trie is empty.
This only effects dlsym when a local symbol is used.
tested on apple x86_64(10.5) and arm64(12.3).
The __atomic_test_and_set and __atomic_clear code was correct.
They needed locking.
Replaced to code with assembly code.
The changes are in include/stdatomic.h, lib/stdatomic.c, lib/atomic.S
Enabled tests/tests2/124_atomic_counter.c for apple again.
Also moved lib/fetch_and_add.S code to lib/atomic.S.
Removed lib/fetch_and_add.S
Adjusted lib/Makefile
The apple m1 uses position independent executables (pie).
I have implemented this in tccmacho.c
Apple also uses the stack different for var_args.
Also characters are signed instead of unsigned.
This is implemented in arm64-gen.c/tccdefs.h
Add bounds checking lib to lib/Makefile.
Add underscore support in lib/atomic.S and lib/fetch_and_add.S
Disable __clear_cache in lib/lib-arm64.c (Use system version).
I will try to fix this in future push.
Disable test_asm_call in tests/tcctest.c. Clang does not support @plt.
Also disable weak symbols test.
I will try to fix weak support in future push.
Disable tests/tests2/124_atomic_counter.c for 64BITS.
This is a bug in the atomic code and will be fixed in future push.
You have to use --dwarf configure option. stabs only works with -run.
tested on apple x86_64(10.5) and arm64(12.3).
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.
Bad assumption make bad things happen:
long d3;
asm(..."1:\tdec %3\n\t" : ... "=&c" (d3)
Which wants 'dec RDI' but did 'dec EDI' on _WIN64.
Also:
- tcctest.c: enable more asm tests for win64
- configure: show errors if any with 'gcc conftest.c'
- tccgen.c: remove decl0(x, y, z)
- x86_64-link.c:
ignore relocation overflow to undefined (weak) symbols
- 104_inline.test:
test lower 32 bits only
- tccpe.c:
support -Wl,--image-base=... above the 32bit range
The script was expecting gcc-3.2 in a specific directory,
works only, when building tcc in the source directory
and creates >3200 files in /tmp (probably a SSD).
Now gcctestsuite.sh works much better.
* use TESTSUITE_PATH, to tell the script the location, where the actual
gcc.c-torture directory is
* work also, when tcc was build in a separate build directory.
use TCC_SOURCE_PATH, when guessing the tcc source directory does not work
* use RUNTIME_DIR to redirect compiler output
(default: XDG_RUNTIME_DIR, then /tmp)
* skip tests for features not implemented in tcc ( *_builtin_*, _Complex )
--
Regards, Detlef
Almost all systems use .gnu_hash so implement it for tcc.
For most of them it is the default.
tccelf.c:
- Add functions elf_gnu_hash/create_gnu_hash/update_gnu_hash
- Update new_section/sort_sections/fill_dynamic/tcc_output_elf/elf_output_file
Tested with setting .hash section to SHF_PRIVATE in elf_output_file.
This reverts commit 2507c71704.
Why crowd up search-paths for the normal native compiler with
all sort of invalid stuff. Why -UCONFIG_TRIPLET if it isn't
set at all for cross-compilers. Also, the patch still didn't
do anything useful "out of the box".
Instead I'd suggest to do something more simple and more effective.
See Makefile:
- set search paths for cross-compilers to /usr/<triplet> by default
- Install any built "xxx-tcc" and "xxx-libtcc1.a", even if not listed
with PROGS_CROSS/LIBTCC1_CROSS
- Support ELF-<target> = ... to set the elf interpreter
Some common gnu-triplets are supported by default
TRIPLET-i386 ?= i386-linux-gnu
TRIPLET-x86_64 ?= x86_64-linux-gnu
TRIPLET-arm ?= arm-linux-gnueabihf
TRIPLET-arm64 ?= aarch64-linux-gnu
TRIPLET-riscv64 ?= riscv64-linux-gnu
Other triplets can be given explicitly, for example like this:
$ make cross-arm-eabi TRIPLET-arm-eabi=arm-linux-gnueabi
$ sudo make install
(As long as it is in the default install location and was not
moved elsewhere into the library search path manually)
Also:
- libtcc.c:
- error1(): show correct line with "In file included from ..."
- support "tcc -Bxxx -vv"
- tcc_new()/tcc_compile(): Don't create elf sections for tcc -E
- tccdbg.c:
- tcc -E -g : revert 1de025c13a
Let's keep things simple, everybody understands 'do_debug'
and dState is set by tcov too (but no debug sections).
- tccgen.c:
- avoid the extra parameter for gind()
(from c3e3a07ed4)
- vla func params: use skip_or_save_block() and enable
VT_LVAL (see 313855c232)
- cleanup nocode_wanted a bit
- tccelf.c:
- tccelf_end_file(): don't try to translate zero-sym relocs
(seems to happen with asm "jmp 0x1000")
- version_add(): do not make "ld-linux.so" DT_NEEDED
This allow the tcc cross compilers to work as expected,
when tcc was build with '--enable-cross' and a simple config-extra.mak
(see the provided config-extra.mak.example).
Make sure, that cross development packages for libc are installed
Fixes also open bugs in various bug tracker. Example in debian: 940469
tcc: error: library 'c' not found
tcc: error: file 'crtn.o' not found
tcc: error: undefined symbol 'printf'
1) recursive types have no storage anymore, so a
static int (*p)[x];
declaration is just fine
2) since somewhen VT_VLA doesn't imply VT_ARRAY anymore, so we
now need to check VLA in at least one place before checking
test_lvalue.
((2) should probably be cleaned up again so that VLA does again imply
ARRAY)
This fixes the bug that "tcc -gdwarf ..."
still creates the stab debug infos,
when tcc was build without using DWARF debug infos by default
(configure option: --dwarf=x)
--
Regards ... Detlef
- also simplify parse(_line)_comment() and parse_pp_string()
- fixes a continuation problem in strings (see tcctest.c)
- no differences in performance could be observed
161 insertions(+), 246 deletions(-), less 85 lines
- make only one function from previously four pieces
- use parse_pp_string() for the normal cases "..." and <...>
- use the sanity check for computed include as end-condition too.
- use 's1' instead of 'tcc_state' when possible
117 insertions(+), 165 deletions(-), less 48 lines
an expression like 'i*0', even though it's value is constant and
can be evaluated at compile time is not an integer constant expression,
and hence no null pointer constant, and therefore the conditional
operator doesn't select the other type.
if a switch is unreachable then so are the case labels.
Unlike normal labels they can't possibly be reached from not-yet
parsed code, so there's no reason to enable codegen again for those.
see testcase. We have to "empty" the macro-stack string on
end_macro, as it may be 'tokstr_buf' which is going to be used
twice in recursive invocations of macro_subst_tok. The uses aren't
overlapping but the first one needs to be properly finalized.
The no-operand vm* instructions can be interpreted as having a
funny modrm byte, but unlike no-operand OPC_MODRM it's also the
r/m field which selects the insn, not (only) the reg field (aka group),
so we need another insn type.
as this is the first opcode TCC supports that has a 0xf3 prefix
and uses integer registers (not SSE ones) this also needs some shuffling
of the prefix code to not generate invalid instructions (the REX prefix
_must_ come directly before the main opcode (including 0f prefix), and
hence needs to come after the 0xf3 prefix). Also disable some mnemonics
in asmtest.S that new GAS doesn't support anymore. The only difference
to GAS (in asmtest.S) is now the 'lock negl' instruction which TCC
emits as 'lock; negl'. That's fine.
they look similar to labels 'foobar : 32' (when foobar is a typedef),
but cannot be handled as such in parse_btype, the context is important
(labels can only happen when called from within 'block', aka decl0 in
VT_LOCAL context). This got broken back in 2019 (1b57560).
The parameter is stored in tccstate, but nothing more.
Used by multiple software packages.
Current tested example is OpenWatcom-v2
--
bye bye ... Detlef
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
Sort sections in separate function to allow variable
calculatiion of needed program headers. Such execinstr
and relro cah have their own PT_LOAD header.
315 insertions(+), 370 deletions(-)
Allows to create dynamic executables, using the code path
for TCC_OUTPUT_DLL but add an .interp header (plus a FLAGS_1
entry in the dynamic section to make 'readelf' say "PIE")
Introduces TCC_OUTPUT_DYN as alias for TCC_OUTPUT_DLL.
There is no runtime option, only one to configure:
./configure --config-pie
100 insertions(+), 76 deletions(-)
... rather than from tccdir. Also allows to load cross
versions of bcheck.o etc. (if we would build them which
we currently don't).
18 insertions(+), 24 deletions(-)
Instead, return its symbol index from build_got_entries()
Also, copy dynamic symbols later when size of _GLOBAL_OFFSET_TABLE_
was already set and handle -rdynamic there too.
See commit 4c82b00342
5 insertions(+), 5 deletions(-)
seems that symbols under nocode/NODATA should not produce
elf symbols at all, not just elf symbols with no size.
See commit 4c82b00342
5 insertions(+), 5 deletions(-)
libtcc.c:
- integrate find_dllref loop into tcc_add_dllref()
tccelf.c:
- make sure a DT_NEEDED tag is put for versions even
when the dll was not previously loaded.
Related commit 4c82b00342
48 insertions(+), 77 deletions(-)
previous patch seems to work only for bcheck.o and only because
it's loaded after libraries (which is maybe wrong too).
See commit 4c82b00342
section_ptr_add() already clears area to zeros
4 insertions(+), 11 deletions(-)
If the `-btN` was specified, then the __TCC_BACKTRACE_ENABLED__
macro will be defined. This provides a way for user code
to tell if tcc_backtrace is defined or not.
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.
commit ec5d94291 made is to that the nocode_wanted state from
inside a statement expression is retained after it. That is wrong
if the statement expression can't be entered to start with. In the
latter case the state from before the stmt-expr is the one we need.
The main problem is that an application called dlclose and then
had a bound checking problem. The list of dll's in tccrun was
not updated an caused a crash.
Also fixed some minor other things.
tccdbg.c:
- Allow filenames like ../file.c
- Rewrite DWARF_ABBREV_MEMBER_BF/DWARF_ABBREV_MEMBER a bit
tccelf.c:
- Add call to __bt_exit. This solves problem when dlclose is called
tccrun.c:
- Rewrite rt_printline_dwarf a litlle to use opcode_length correctly
- Do not stop at DW_LNE_end_sequence
- Fix DW_LNE_set_address again. Works now in *bsd.
lib/bt-exe.c lib/bt-dll.c:
- Add __bt_exit/__bound_exit_dll
lib/bcheck.c:
- Add __bound_exit_dll
tccgen.c:
- When __FUNCTION__ is used and no code is generated use symbol len = 0.
tccelf.c:
- If library is present in verneed it should be in DT_NEEDED.
- @plt symbols should have size 0
- set _GLOBAL_OFFSET_TABLE_ st_size correct
- Remove version symbol if new value present
reported by elflint:
__FUNCTION__ problem:
section [19] '.symtab': symbol 2134 (L.195) does not fit completely in referenced section [14] '.data.ro'
DT_NEEDED problem:
section [26] '.gnu.version_r': entry 2 references unknown dependency
@plt symbols should have size 0:
section [22] '.symtab': symbol 36557 (r_core_config_init@plt) does not fit completely in referenced section [14] '.plt'
_GLOBAL_OFFSET_TABLE_ size:
section [44] '.symtab': _GLOBAL_OFFSET_TABLE_ symbol size 4 does not match .got section size 736
Remove version symbol:
section [25] '.gnu.version': symbol 86: version index 3 is for requested version
This happened for example with bounds checking symbol malloc
Using the environment CC is a common used feature to
select a compiler to build any software,
so it should be supported when building tcc.
The old way using the parameter --cc still works.
(resend)
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
tccdbg.c
- Fix typo in dwarf_file. This resulted in not finding correct include
files.
tccrun.c:
- Change FILE_TABLE_SIZE to 512. Some files use very large includes.
- When a dll containted more then 1 file the pc was not calculated
correctly.
Some small updates in tccdbg.c found by checking readelf output from
gcc/clang.
- Change encoding type bool type
- Fix enum signed/unsigned
- Do not hash anon symbol
- Use correct filename/line_number for global variables
- Fix compiler warning in tcc_get_dwarf_info
- Use unsigned long long for array indexes
- Display correct first line of function in gdb
Better avoid global variables, at least in new code.
tccdbg.c hopefully should be logically identical to the
former parts in tccgen/elf.c (s1 tccstate added in some
places)
tccelf.c: dwarf linkage seems special per dwarf rather
than special per target.
/* Use "-g" as alias for "-g1". Use "-g0" to disable debug */
So not using -g is now the alias for -g0 ?!?
This reverts commit 8759b2581d.
This reverts commit 3ce7bc6efc.
This reverts commit 5fb582ab7f.
This reverts commit aea68dbb40.
This reverts commit fa9c31c3db.
This reverts commit b3bebdb20a.
This reverts commit ecf8e5a00e.
This reverts commit fe6b5c08dc.
This reverts commit e2e5377e7b.
This reverts commit 1cd7998905.
readelf complained about DW_AT_stmt_list and DW_AT_location.
For dwarf >= 4 we should use DW_FORM_sec_offset instead of DW_FORM_data4
and DW_FORM_exprloc instead of DW_FORM_block1.
This is fixed in tccgen.c
I also updated tccrun.c to use dwarf_read_1 instead of DW_GETC.
This if for clang (pre)release 15.0.0.
tccrun.c:
- update directory/filename read. clang has extra md5 section
- start with filename 0 instead of 1. clang starts at 0
- change dwarf_read_32/dwarf_read_64 into macros
x86_64-link.c:
- Add support for R_X86_64_DTPOFF64/R_X86_64_TPOFF64. Needed by clang
tests/tcctest.c:
- add prototypes for puts/alloca. clang fails with error
- disable other_constraints_test for clang. clang prints 1 instead of 0
tccgen.c:
- add anon support. So tcc_state in tcc works now.
- add function pointer support
- remove DW_FORM_implicit_const from DW_TAG_pointer_type
tccrun.c:
- set initial file name
- correctly use pc in DW_LNE_set_address (see lib/bt-exe.c)
- add DW_LNE_define_file support (even if it is deprecated)
tccelf.c
- do not include debug/test_coverage information for stub functions
lib/bt-exe.c
- use num_callers=-1 to mark dll
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
The code needs to be fixed: use the functions or remove them.
arm-asm.c:
asm_parse_vfp_regvar()
arm64-link:
gotplt_entry_type()
create_plt_entry()
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
Warnings reported in in x86_64-gen.c and arm-gen.c:
warning: ‘align’ may be used uninitialized in this function [-Wmaybe-uninitialized]
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
Target buffer must be larger as the format string + the replacement for %s
to avoid a warning [-Wformat-truncation=]
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
Using the environment CC is a common used feature to
select a compiler to build any software,
so it should be supported when building tcc.
The old way using the parameter --cc still works.
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
Some headers and source code change macros and
implementation, when __OPTIMIZE_SIZE__ is defined.
This does not change our generated code.
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
With this code, we can compile more projects,
who expect gcc or clang as compiler. (-std=gnu11 used in Makefiles)
As a further extension, it would be easy to disable gcc extensions
Signed-off-by: Detlef Riekenberg <wine.dev@web.de>
There is no code generation in post_type for vla arrays. This code
generation has to be delayed until gen_function.
- post_type save code in type info.
- gen_function use this code to generate vla code.
- enable testcode for vla arrays.
Modify function parameter parser such that symbols are
put into token-table temporarily. Benefits are:
- detects redefinitions, as with
int foo(int a, int a);
- detects reserved symbols, as with
int foo(int if);
- can parse expressions like
int main(int argc, char *argv[argc + 1]);
- doesn't fix this one
int main(int argc, char *argv[++argc]);
Also: fix unexpected "function might return no value"
with statement expression
int f() { ({ return 0; }); }
By replacing the `-f 2` field selection with `-f 2-`, we select fields
2 and beyond, so that arguments containing the '=' character are not
truncated.
This option qualifier list format is POSIX standard and tested
to work with the `cut` program from:
* GNU coreutils
* macOS (FreeBSD)
* NetBSD
* toybox
* busybox
* uutils-coreutils
In my case, this is useful because I'm trying to use an installation
prefix which contains an equals sign.
Currently used only with 'tcc_compile_sem' to protect
tcc_compile(), but can be used with other semaphores
Also fix deadlock when tcc_enter_state() is called
recursively for the same state, for example with
tcc_warning() from #pragma comment(option,"...")
Also:
- libtcc.c: error1(): use cstr_[v]printf()
- tcc.h: set TCC_USING_DOUBLE_FOR_LDOUBLE for macho-arm64
(rather than for macho-X86_64)
- tcc.h: define TCC_TARGET_MACHO on __APPLE__ by default
- tcc.h: cleanup TCCState, move DEFASM token stuff to tcctok.h
- tccgen.c: more static
- Makefile/tcc.c: review githash
- tccpe/tcctools: use read() instead of fgets() in pe_load_def()
(all files opened by tcc for reading are now read via 'int fd')
- configure/win32: don't preset CONFIG_TCCDIR (to allow to override it)
- tcc.c -bench: do not include output/run-time
136 insertions(+), 226 deletions(-), less 90 lines (except tests)
only one set_flag() function required
* can now turn off specific errors: -Werror -Wno-error=option
* new interface: tcc_warning_c(warn_option)("format", args...);
* new warning: -Wdiscarded-qualifiers (on by default)
* new variable 'warn_all' for conditional warnings with -Wall
see also the tests
configure:
- re-enable apple M1-arm64
- however, with --cpu=x86_64, set -arch in CFLAGS/LDFLAGS too
(assume rosetta)
Makefile:
- re-enable osx cross-test (Please do not disable tests)
tcc.h
- set TCC_IS_NATIVE for TCC_TARGET_MACHO on __APPLE__
- apply TCC_USING_DOUBLE_FOR_LDOUBLE for x86_64-osx
libtcc.c:
- cleanup tcc_add_file_internal()
- new function char *tcc_load_text(int fd); and use it for tbd files
Supports linking using .tbd definitions found in the default installed
command-line tools SDK or Xcode.app SDK. Only for creating executables
(not yet for `tcc -run`).
Add support for some more options to generate dependency fragments.
-M is likes -MD but doesn't compile anything so the command won't fail
when just supplied a file without all the relevant libs.
-MM and -MMD are like their counterparts but skip system libs.
Note the behavior of -MD has changed to include system libs. Use -MMD
for the old behavior. This matches gcc's corresponding flags
- 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
Some complex types can still be small and simple enough to fit into
register. Other compilers allow some operations on these types, and it
seems to be quite a reasonable choice. From now on, we should be able
to compile the following artificial example:
struct combo {
uint16_t lo;
uint16_t hi;
};
struct combo load(const _Atomic(struct combo) *atom)
{
return atomic_load(atom);
}
void store(_Atomic(struct combo) *atom, struct combo value)
{
atomic_store(atom, value);
}
struct combo xchg(_Atomic(struct combo) *atom, struct combo value)
{
return atomic_exchange(atom, value);
}
bool cmpxchg(_Atomic(struct combo) *atom,
struct combo *cmp, struct combo xchg)
{
return atomic_compare_exchange_strong(atom, cmp, xchg);
}
This might be useful for some corner cases, though it is quite likely
that many programmers will prefer operating on a single 32-bit value
instead of using the structure consisting of 16-bit pair.
Things will work as long as the overall structure size happens to be
the same as for any integer type we support in atomics.
libtcc.c: add -Wwrite-strings to -Wall
tccgen.c: ro float-consts, string-consts, ro arrays if base type is
tccpe.c: merge IAT with rodata
tccrun.c: mprotect rodata accordingly. free section data after copy
x86_64.c: do not use got for static data.
tcc -bench: show data.rw/ro
Probably STB_LOCAL should never get to put_got_entry(), and currently
it doesn't seem to happen (See "Hack Alarm" there)
Other files: use more ro-data in tinycc
when used with string initialization the size of nested struct flex
array member was tested too late for < 0.
GCC accepts but discards such initializers (the flex array member will
become zero sized). TCC supports flex arrays members only in
top-level structs and gives an error in this case.
When defining an array with non-explicit size, one would get
"incompatible types for redefinition of 'array' if the array was already
declared with a different size.
For example:
extern int array[2];
int array[] = {1};
would fail to compile with tcc. Instead the above is now equivalent to:
int array[] = {1, 0};
this change fixes building of invalid types. The inner scope
struct P is return type of the forward decl foobar. The outer scope
foobar() call implicitely declares that function again, with int
return type; overall this leads to access within the sym free list,
effectively building up a type directly referring to itself, leading
to endless recursion later. The testcase is:
void n(void)
{
{
struct P {
int __val;
};
struct P foobar(); // 1
}
foobar(); // 2
}
I've not included it in tests2 for now, because tcc accepts this.
Ideally we would like to reject it (as 'int foobar();' is incompatible
with the earlier decl). clang also accepts it, but only because it's
not handling (1) above as an implicit decl of foobar (it warns, and
with -pedantic also warns about the type incompatiblity). GCC rejects
this.
Implementing that in tcc requires some surgery, as we need to differ
between these cases:
{ struct P foo(int); // 1
foo(); // no implicit decl, call to foo from 1
}
and
{ { struct P foo(int); // 2 }
foo(); // implicit decl, _incompatible_ with 2
}
normally the sym slot is meaningful only with VT_SYM. But we also
use it when mentioning a decl for inline asms with register vars,
conditional on being a VT_LOCAL entry. So when generating VT_LOCAL we
need to reset .sym as it might contain stale entries from the cmp_op
fields.
with fuzzed source code we might run into this with idx out of bounds.
We're going to error out on this later, but let's not access
out-of-bounds elements.
see testcase, reduced example of a situation reported by
Kyryl Melekhin in https://github.com/kyx0r/neatvi/ .
Problem is that setting up the VLA sp-save in a scope that isn't
entered at runtime leaves traces of it in outer scopes that then
try to restore the stack pointer from uninitialized slots.
If spaces are not escaped when generating the make dependencies file,
then if one of the dependencies has a space it would be interpreted as
two separate targets by Make, instead of just one.
Add myself to RELICENSING file
Use locking when writing tcov file
Fixed sometimes last line of function not shown
Merge tcc_tcov_add_file and tcc_add_tcov
Allow absolute file names
Count case labels with no code better
lib/tcov.c:
- can't be cross-compiled (needs stdio.h)
- can be included in libtcc1.a
Reason why bt-xxx.o/bcheck.o are linked separatly is because we
don't want then to linked into exe's and dlls at the same time.
tccgen.c: debug_modes
- don't waste debug function calls during normal execution.
libtcc.c:
- mem_debug: no C99 features in tcc please, for example
({compound expressions}): do not use.
tccgen.c: struct_layout:
- unaligned access is completely ok for most targets.
- Moreover the patch was triggering single byte mode even
for normal aligned access (as with tcc's SymAttr)
static Sym label: don't do this
arm-gen.c:
- use some #ifdefs to explain some code
tccpp.c:
- cleanup UCN chars
libtcc.c:
- replace openbsd library search
configure:
- cleanup strip fallouts
tccgen.c:
- expr_cond(): remove an exotic optimization that eventually
got fixed to do the contrary by a gv(RC_InT)
- pop_local_syms(): remove some args
- init_putv() : use write##le functions to avoid cross-compiler
unaligned access
- __bt_init(): remove unused param 'mode'
libtcc.c:
Fix unaligned load/store from magic3
tccgen.c:
For packed struct allways use single byte code
If field does not start at at align check it
Align stack correctly with vla
I have implemented the -ftest-coverage option. It works a bit different
from the gcc version. It output .tcov text file which looks almost the
same as a gcov file after a executable/so file is run.
Add lib/tcov.c file
Modify Makefiles to compile/install it
Add -ftest-coverage option in tcc.c/tcc.h/tcc-doc.texi
Add code to tccelf.c/tccgen.c/tccpe.c
Add gen_increment_tcov to tcc.h/*gen.c
unrelated changes:
Add sigemptyset in tccrun.c
Fix riscv64-gen.c tok_alloc label size
As the standard requires, take 4 hex digits after the \u opener of a
Universal Character Name, or take 8 hex digits after \U, but reject
smaller counts and don't consume more (https://port70.net/~nsz/c/c11/n1570.html#6.4.3,
https://port70.net/~nsz/c/c99/n1256.html#6.4.3).
The unicode codepoint used to get truncated to 1 byte. Now it gets expanded into UTF-8,
matching gcc & clang behavior on Linux.
TODO: Universal character names should also be supported in identifiers,
as in, e.g., char \u010dau_sv\u011bte[]="čau_světe";
Disable warning softfloat. OpenBSD works fine.
save/restore s0-s15 during memcpy call for structs
update configure script. Works now on raspberry pi/All BSD
Add eabi_mem.. functions in armeabi.c for OpenBSD
Fix fp register in tccrun.c for OpenBSD
Support OpenBSD/FreeBSD/NetBSD on asm.
move PAGESIZE to tcc.h and use _SC_PAGESIZE (netbsd/arm has 8192 pagesize)
arm:
- fix cmp instruction for qemu (raspberry pi works without patch?)
- increase start address/size
- use large plt size
- add return R_ARM_PREL31
- add R_ARM_TARGET1 to prepare_dynamic_rel
- add gcc_s to FreeBSD (unwind code)
- do not use __clear_cache on bsd (sometimes bad system call)
- do stack unwinding on bsd
- test/tcctest.c: use %lld %llu on bsd
The small common parts within elf_output_file() aren't
worth the many #ifdefs. Also, set section sizes and
allocate section names in 2 separate functions.
These gaps are a result of final_sections_reloc. Here some relocs are removed.
The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as
R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this
is illegal.
for floats (currently only). On x86_64 uses built-in fp
constants (in libtcc1.c) to avoid multiple anonymous
instances.
Also: win32/i386: use __alloca for big struct stack store
- use new function int tok_alloc_const(const char*);
- change alloca86.S to preserve EDX
tccelf.c: fix a warning with 'roinf_use'
Using "-0.0 - x" still isn't enough if x is a NaN, so bite the bullet
and implement sign-bit flipping via memory. (It's usually not too bad,
the -0.0-x method also uses memory for the floating point constant).
This way is at least shorter than implementing a new top-level operation
for all backends (a negate) that would be unary.
implement load/store to constant address
use VT_LLONG instead of VT_PTR in register passing
fix bound checking problem with small structs
enable riscv tests in tests/tcctest.c and tests/tests2/119_random_stuff.c
moved target_machine defines to the <target>-gen.c files.
Also:
- c2str.c moved into conftest.c
- tccdefs.h ; defined(__TINYC__) && !defined(_LOCORE) removed
(in tinycc __TINYC__ is always defined and _LO... is never.)
- stddef.h : too many #ifdefs, removed
- tccgen.c:stabs: support win32 long doubles aka doubles.
- win32: math.h/tcc_libm.h: fix pointer mismatch in modfl
- tccpp.c: increment include_stack_ptr after the file was
actually found otherwise it would print
"in file included from <itself>: file not found..."
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
... not just on the BSDs. Sometimes e.g. .note.ABI-tag is allocated
and other sections might contain relocations referring to symbols in
them. TCC doesn't do any special processing to them, like merging
or somesuch, it just pastes them all together in normal link-editing
behaviour.
(Seen on a recent openSUSE with glibc 2.32, when the crt1.o file
contains debug information)
tcc_define_symbol(): now only for -D on command line
include/tccdefs.h: converted to strings and compiled into
the tcc executable. Can be disabled with
./configure --config-predefs=no
In this case include/tccdefs.h is loaded at runtime. This is
default for other build-methods (build-tcc.bat) also (to avoid
some complexity).
Also:
- lib/Makefile: fix typo
- tcc.h : avoid _strto(u)i64 (for TCC on WIN98/2K)
- tccpp.h:cstr_printf() : workaround incompatible vsnprintf's
(generally faster too)
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
Fix all testcases for openbsd except dlltest.
Remember dlopen calls and use them to fix openbsd dlsym problem
Use crtbeginS.o/crtendS.o for DLL for bsd
Do not include -ldl for __NetBSD__
Redirect malloc, realloc, ..., free for bsd
Align stack in tests/asm-c-connect-*.c for x86_64
Remove -B in tests/pp/Makefile (not supported on bsd)
tcc_enter/exit_state() are meant exclusively to protect
the tcc_compile() and its sub-functions in tccpp.c,
tccgen.c, tccasm.c and xxx-gen.c.
Other files that are part of libtcc simply must not use global
variables.
- riscv64/last_hi: move to TCCState
from 72250bece2
- tccrun.c: Using a fixed address would not work anyway
("tcc -run tcc.c -run ..." for example)
from baacb0f52a
- tests/Makefile: support for a platform doesn't make sense if
it doesn't pass our basic tests.
from 591feda103
Also:
- tccgen: cleanup "duplicate member" (only 2 passes,
avoids additional TokenSym field)
from 170be79a42
After this commit we can compile and run code with some limitations.
- The dlsym function is broken so this makes -run and bound checking
not work all the time. Make -k test does work for most code.
- You have to do:
ln -s /usr/lib/libN.so.x.y /usr/lib/libN.so
for all .so files in /usr/lib.
OpenBSD uses opendir/readdir to find the correct so file. This is
not the way other platforms do this.
Also the .a versions do not have all symbols that are present in the .so
files.
tcc.h:
- Use different dynamic loader
elf.h:
- Add SHT_X86_64_UNWIND
tccelf.c:
- Do not use -dl
- Add required NOTE section
- Add extra dynamic tags
- Allow SHT_X86_64_UNWIND/SHT_NOTE in tcc_load_object_file
tccrun.c:
- Uses MAP_FIXED because without the offset between exec and data section
becomes too big for x86_64
lib/bcheck.c:
- Do not use __libc_freeres
tests/tcctest.c:
- aligned_function also disabled for __GNUC__ == 4
Check duplicate struct/union member names
tcc.h: Add cnt field in TokenSym
tccgen.c: New function check_fields to find duplicate member names.
This avoids quadratic behavior and can be used for large structs.
- tccpe.c: commit "tidy support for helper function" created
STT_NOTYPE symbols and hence relied on ad-hoc detection which
didn't work for x86_64 (as reported by Christian Jullien)
- tccgen.c: However to be more safe the helper symbols are
now made STT_FUNC anyway (via new VT_ASM_FUNC).
Also:
- tcc.h: minor reorder
- riscv64-*, arm64-*, tccmacho.c: avoid some gcc format-warnings
(mingw-gcc complains about "%llx" being "unknown conversion",
although it does work since Vista or so)
tcc.h, tccgen.c: Introduce Sym *external_helper_sym(int v);
to create an external reference with no specific type. This
avoids type conflicts if the symbol is used from C too.
the other files: use it.
Tcc considered function ptrs with different return types to be
compatible which disallowed some otherwise valid operations like:
`_Generic(foo, int(*)():0, void(*)(void):1)`
which would fail to compile with a error message of "type match twice"
This changed also required longjump's return type to be void and
munmap's to be int to be compatible with standard headers.
1) Cleanup: moved function implementations from win32/include/math.h to win32/include/tcc/tcc_libm.h
2) Added missing math functions: MUSL: asinh(), acosh(), atanh(), scalbn(). My impl: log1p(), expm1(), ilogb(), scalbln(), nexttoward()
- now only a few are missing: remquo(), remainder(), fma(), nan(), erf(), erfc(), nearbyint().
3) Added/defined all missing *f() and *l() math functions.
4) Added functions have short but accurate/fast implementations.
5) Added <tgmath.h> for all platforms. (not too useful, IMO, but is C99 standard).
The gamma() functions are accurate to 13 digits over the full range. Returns INFINITY / NAN identical to other compiler's math libs.
#include <stdio.h>
#include <math.h>
int main() {
double x;
for (x = -7.0; x <= 520.0; x += 1.0) {
printf("tgamma/lgamma %6.3f: %20.13g %20.13g\n", x/3, tgamma(x/3.0), lgamma(x/3.0));
}
printf("tgamma/lgamma %g: %20.13g %20.13g\n", 0.00000234, tgamma(0.00000234), lgamma(0.00000234));
printf("log2, exp2, cbrt, cbrt: %.15g %.15g %.15g %.15g\n", log2(1024), exp2(10), cbrt(-10), cbrt(10));
}
- tcc.h: msvc doesn't grok __func__ (reverts previous commit)
- tccgen.c: fortify tcc against bogus code:
- n[sizeof({3;})]; // statement expression outside of function
- f(){"123"4}; // tokens with values following each other
(also, add "type defaults to int" warning for variables)
- tccpe.c: removed a check that caused BSS symbols not to be
exported. Whatever that check was meant to prevent.
- win32/build-tcc.bat: cmd.exe sometimes doesn't grok '-' in labels
- Revert "libtcc: no need to undef"
This reverts commit 2b7aa2a1e1.
- Revert "tcc.h libtcc.c: remove unused defines"
This reverts commit 985d963745.
The point of these "unused defines" is to be unused, that is
to remind people not to use malloc but please to "use_tcc_malloc",
instead.
pretty sure that functions with use_* do not exist
and attempts to use the macros will fail to link
I could rename them to be more up to date like tcc_malloc,
but to me overloading the std calls with macros is
probably taking away control from the programmer,
so for the best is to just get rid of them.
Fixes potential writes past the allocated space with mostly
illegal flex array initializers. (60_errors_and_warnings.c
:test_var_array)
In exchange suspicious precautions such as section_reserve
or checks with sec->data_allocated were removed. (There is
an hard check 'init_assert()' for now but it's meant to be
just temporary)
Also, instead of filling holes, always memset(0) structures
& arrays on stack. Sometimes more efficient, sometimes isn't.
At least we can omit putting null initializers.
About array range inititializers: Reparsing tokens has a
small problem with sideeffects, for example
int c = 0, dd[] = { [0 ... 1] = ++c, [2 ... 3] = ++c };
Also, instead of 'squeeze_multi_relocs()', delete pre-existing
relocations in advance. This works even if secondary initializers
don't even have relocations, as with
[0 ... 7] = &stuff,
[4] = NULL
Also, in tcc.h: new macro "tcc_internal_error()"
Always fine to try out things but not everything must be shown
to the public. ;)
Also, AFAIK pointers must compare equal only if derived directly
from each other (for example by cast to void* and back).
This reverts commit 8f9bf3f223.
Arm has a problem with tls after a fork. The pthread_key_create seems to
be forgotten?
Apple has a problem with the exit(0) code in do_fork(). An IO mutex
is still held after a fork().
While MacOS doesn't natively support the alias attribute, let's support
it with TCC anyway. This means we need to make a decision if the
string in the alias attribute is decorated or not due to the implicit
underscore on MacOS. To make life easier we decide that it's the C name,
i.e. without underscore, and so TCC needs to emit alias names with
underscore handling.
Irrespective of that the test case needs to deal with the underscore
itself for __asm__ renaming which is always requiring the assembler name.
The init range with symbols did only init the first value.
The relocation for all other symbols was missing.
Also see testcase.
tccgen.c:
- New function get_init_string
- Use macro processing in decl_designator for each init string
- Use get_init_string in decl_initializer_alloc
tccelf.c:
- Fix insertion sort in squeeze_multi_relocs
tests/tests2/90_struct-init.c:
- Add test case test_init_ranges
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
commit 2a0167a merged alias and asm symbol renaming, but broke
semantics of aliases, see testcase. Basically the difference between
the two is that an asm rename doesn't generate a new symbol, i.e. with
int foo __asm__("bar");
all source reference to 'foo' will be to 'bar', nothing of the name
'foo' will remain in the object file, and for instance reference to
'foo' from other compilation units won't be resolved to this one.
Aliases OTOH create an additional symbol. With:
void target (void) { return; }
void afunc (void) __attribute__((alias("target")));
reference to 'afunc' will remain 'afunc' in the object file. It will
generate two symbols, 'afunc' and 'target' referring to the same entity.
This difference matters if other compilation units make references to
'afunc'.
A side requirement of this is that for alias to work that the target
symbol needs to be defined in the same unit. For TCC we even require a
stricter variant: it must be defined before the alias is created.
Now, with this I merely re-instated the old flow of events before above
commit. It didn't seem useful anymore to place both names in the
asm_label member of attributes, and the asm_label member of Sym now
again only needs the hold the __asm__ rename.
It also follows that tcc_predefs.h can't make use of attribute alias to
e.g. map __builtin_memcpy to __bound_memcpy (simply because the latter
isn't defined in all units), but rather must use __asm__ renaming, which
in turn means that the underscore handling needs to be done by hand.
tccelf.c:
- Check if symbol is in data section and UNDEF. Then generate new
relocation and let dynamic linker solve it.
tests/tests2/42_function_pointer.c:
- Add new test code
The code:
struct bf_SS {unsigned int bit:1,bits31:31; };
void func(void) {
struct bf_SS bf_finit = { .bit = 1 };
}
will not init bits31 to 0.
tccgen.c:
- check_bf: New function to check if bitfield is present in struct/union
- decl_initializer: Call check_bf and set value to 0 is bitfield found
tests/tcctest.c:
- Add struct bitfield test code
from 43ae350390
and a3578379fb
Sorry, but this feature appears to be rather a personal
experiment than generically interesting for other people.
Also those "other people" always have some interest in
TCC staying simple.
One can still avoid the startup code from libtcc1.a simply
by providing __start explicitly.
While at it: Tidy tccpe.c:pe_add_runtime(), somewhat.
lib/va_list.c:
- Handle struct {double, double} correctly
arm64-gen.c:
riscv64-gen.c:
x86_64-gen.c:
- Allow zero sized structs to work with va_arg
tcctest.c:
- Add new va_arg test code
test/bug.c:
- Remove tst2 va_arg test
lib/bt-exe.c:
- call __bound_init before sigset_exception_handler because sigaction
is redirected.
tests/tests2/Makefile:
- run testcase 114 on macos again
Note:
I removed the test that used sin()
function because it makes no sense
to use that there and besides I could
not get the test to work because
sin requires -lm linked but for some reason
make does not compile with -lm and
I get errors like undefined symbol sin.
Coerce function should do the same thing
for the purposes of that test.
reverts commit
310e3b428c
(more info there)
now functions check for
sign bit in float.
now hopefully this patch will
cover entirety of areas it might affect
reproduce bug:
$ ./configure --cc=gcc
$ make
$ make install
(OK)
run a test:
extern int printf(const char *str, ...);
int main()
{
int t2 = (int)(-1.847759065f * 4096);
printf("%d\n", t2);
}
$ tcc test.c
$ ./a.out
$ -7568
(OK)
(self compiled now)
$ ./configure --cc=tcc
$ make
$ make install
(OK)
$ tcc test.c
$ ./a.out
$ 7568
(WRONG!!!)
why:
gcc does not have intristics for
uint to long double conversion
therefore it does cast implicitly, so
the sign bit is preserved, but this does
not happen when __fixunsxfdi is called
because tcc was bootstrapped.
solution:
force cast to int64 and preserve the
sign bit.
side effects:
not found.
The BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF is not working for
signal/sigaction/fork. The reason is that the code stops bound checking
for the whole application. This result in wrong handling of
__bound_local_new/__bound_local_delete and malloc/calloc/realloc/free.
Consider the following code:
void tst(int n) {
int i, arr[n];
for (i = 0; i < n; i++) arr[i] = 0;
}
void *some_thread(void *dummy) {
while (running) { tst(10); tst(20); }
}
void signal_handler(int sig) { ... }
When the signal handler is called the some_thread code can be interrupted when
is just registered the arr[10] data. When the signal handler is leaved the
arr[10] is still registered and did not see the call to deregister arr[10] and
then register arr[20]. The code resumes when tst(20) is running. This results
in a bound checking error when i >= 10.
To solve the above problem I changed the bound checking code to use
tls (thread local storage) for the no_checking variable.
This also makes it now possible to redirect signal/sigaction/fork code
through the bound checking library and disable checking when a signal is
running and to correct the bounds_sem for the fork child process.
The BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF is not needed any more for
signal/sigaction/fork. In fact I could remove them from all my applications.
The use of the tls function code slows down the code by about 10%.
So if the slowdown due to bound checking was 5. It is now 5.5 times slower.
For x86_64/i386 I also allowed to use __thread variable in bcheck.c when
compiled with gcc with:
make x86_64-libtcc1-usegcc=yes
make i386-libtcc1-usegcc=yes
This makes code run faster due to use of gcc and __thread variable.
With the __thread variable there is no 10% slowdown.
For other targets this does not work because stabs is not supported.
Changes:
lib/bcheck.c:
- Add TRY_SEM
- Add HAVE_SIGNAL/HAVE_SIGACTION/HAVE_FORK/HAVE_TLS_FUNC/HAVE_TLS_VAR
- HAVE_SIGNAL: redirect signal() call if set.
- HAVE_SIGACTION: redirect sigaction() call if set.
- HAVE_FORK: redirect fork() call if set.
- HAVE_TLS_FUNC: If target has tls function calls.
- HAVE_TLS_VAR: If target has __thread tls support.
- Replace all no_checking refecrences to NO_CHECKING_SET/NO_CHECKING_GET macros
tcc-doc.texi:
- Remove examples for signal/sigaction/fork code.
- Add some explanation for signal/sigaction/fork code.
- Add documentaion for __bounds_checking().
tccelf.c:
- Add support for SHF_TLS
tests/tests2/114_bound_signal.c:
- Remove BOUNDS_CHECKING_ON/BOUNDS_CHECKING_OFF
- Add code to trigger failure when tls is not working.
x86_64-link.c:
- Add support for R_X86_64_TLSGD/R_X86_64_TLSLD/R_X86_64_DTPOFF32/R_X86_64_TPOFF32
i386-link.c:
- Add support for R_386_TLS_GD/R_386_TLS_LDM/R_386_TLS_LDO_32/R_386_TLS_LE
This allows for example this scenario:
- A dll to be linked with is specified in file.c, where file.c
and the dll exist in the same directory:
#pragma comment(lib, "txml")
#pragma comment(option, "-L{f}")
- tcc is called to run file.c from other, varying directories:
$ tcc -run some/dir/file.c <args...>
Note that tcc replaces {f} by the currently compiled file's
directory ('some/dir' in this example).
Also:
- tccgen.c: fix last commit for gen_cast.
Please respect some conventions:
- tests2 filenames don't end with '..._test'
- tests2 tests are meant to produce some output
- the output should be somehow informative, not just
"error" or "dummy". Because other people would want to
know where it fails if it does.
- tests2 tests should work with both GCC and TCC, except
if there are specifc reasons (like testing tcc-only
feature such as bounds checking)
- tests2 tests should never crash or abort. Because that
would cause gui dialogs to pop up on windows, and because
other people would not know where it fails if it does.
- tests2 tests should be somehow specific, in general.
(rather than just collections of random stuff)
- in general, do not use 'long' if you mean 'larger than int'
Because it isn't on many platforms.
- use four (4) spaces for block indention. Do not insert
tab characters in files if possible.
Also:
- tccgen.c:gen_cast() simplify last fix.
Providing both run-time and compile-time control for bounds
checking as an user interface appears unnecessary and confusing.
Also:
- replace 'bound_...' by 'bounds_...' for consistency
- tcc-doc: put related info into one place and cleanup
The __bounds_checking(x) function is still missing explanation.
(I.e. what happens if the accumulated value drops below zero.)
The switch/case operation was entirely performed on int64_t, resulting
in a warning and bad code to be emitted on 64 bit machines when used on
an unsigned long with a case range whose signed representation starts
positive and ends negative like in the example below:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int nbdg(unsigned long n)
{
switch (n) {
case 1UL ... 9UL: return 1;
case 10UL ... 99UL: return 2;
case 100UL ... 999UL: return 3;
case 1000UL ... 9999UL: return 4;
case 10000UL ... 99999UL: return 5;
case 100000UL ... 999999UL: return 6;
case 1000000UL ... 9999999UL: return 7;
case 10000000UL ... 99999999UL: return 8;
case 100000000UL ... 999999999UL: return 9;
case 1000000000UL ... 9999999999UL: return 10;
case 10000000000UL ... 99999999999UL: return 11;
case 100000000000UL ... 999999999999UL: return 12;
case 1000000000000UL ... 9999999999999UL: return 13;
case 10000000000000UL ... 99999999999999UL: return 14;
case 100000000000000UL ... 999999999999999UL: return 15;
case 1000000000000000UL ... 9999999999999999UL: return 16;
case 10000000000000000UL ... 99999999999999999UL: return 17;
case 100000000000000000UL ... 999999999999999999UL: return 18;
case 1000000000000000000UL ... 9999999999999999999UL: return 19; // this one
case 10000000000000000000UL ... ULONG_MAX: return 20;
}
return 0;
}
int main(int argc, char **argv)
{
unsigned long v = strtoul(argc > 1 ? argv[1] : "1111", NULL, 0);
printf("%lu : %d\n", v, nbdg(v));
return 0;
}
$ tcc dg.c
dg.c:26: warning: empty case range
$ x="";for i in 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0; do x=$x$i; ./a.out $x;done
1 : 1
12 : 2
123 : 3
1234 : 4
12345 : 5
123456 : 6
1234567 : 7
12345678 : 8
123456789 : 9
1234567890 : 10
12345678901 : 11
123456789012 : 12
1234567890123 : 13
12345678901234 : 14
123456789012345 : 15
1234567890123456 : 16
12345678901234567 : 17
123456789012345678 : 18
1234567890123456789 : 0
12345678901234567890 : 20
What this patch does is to use a separate set of signed and unsigned
case_cmp functions depending on whether the expression is signed or
unsigned, and also does this to decide when to emit the warning.
The bad code on output was caused by the removal of the unsigned bit
resulting from the signed sort, which causes only signed comparisons
to be emitted in the asm code. As such some sets could not match.
Note that there is no way to rely on the values only to sort properly
nor to emit the warning because we're effectively dealing with 65-bit
arithmetic here and any two values will have a different behavior
depending on the signed or unsigned expectation.
For unsigned expressions now the warning only happens when bounds are
switched, For signed expressions (e.g. if the input is signed long
above), the warning remains and the abnormal output as well. In both
cases this remains consistent with what gcc produces.
tcctok.h:
- Add CONFIG_TCC_BCHECK arround TOK_NO_BOUND_CHECK1/TOK_NO_BOUND_CHECK2
tccgen.c:
- Add CONFIG_TCC_BCHECK arround TOK_NO_BOUND_CHECK1/TOK_NO_BOUND_CHECK2
- Undo alias definition in tccpp.c when function bound checking if off
tests/tests2/114_bound_signal.c:
- Test alias undo
- fix sleep problem
Most support was already present.
arm-link.c:
- set RELOCATE_DLLPLT to 1
- create_plt_entry:
- remove DLLs unimplemented!
- leave code gen to relocate_plt. only set got_offset
- relocate_plt:
- create code for got entry
- relocate:
- Add TCC_OUTPUT_DLL for R_ARM_ABS32
tccelf.c:
- prepare_dynamic_rel:
- Add R_ARM_ABS32
- alloc_sec_names:
- Always add SHT_ARM_ATTRIBUTES section
- New function create_arm_attribute_section
- elf_output_file:
- call create_arm_attribute_section
The load/store code is optimized to make better use of the offsets
present in the load/store instructions.
Also use GOT reloc's instead of ABS64 relocs.
arm64-gen.c/arm64_check_offset:
- New function to split offset used by load/store and by arm64_sym.
arm64-gen.c/arm64_sym:
- Use GOT reloc's instead of ABS64 relocs.
arm64-gen.c/load arm64-gen.c/store:
- Use new arm64_check_offset function.
arm64-gen.c/gen_bounds_prolog arm64-gen.c/gen_bounds_epilog:
- Use GOT reloc's instaed of ABS64 relocs.
old qemu (before april 2020) have a bug in the layout of
struct ucontext, so we get invalid values under qemu-userspace emulation
when inspecting the signal context. Try to recognize this and
graciously error out instead of segfaulting in the backtracer routines.
found in mpfr. Expressions like "(longlong)i <= MAX_ULONGLONG" are
always true (not yet short-circuited in tcc), but still need to be
handled correctly in the backends.
The orignal code does:
push eax/edx/size
call alloca
pop eax/edx/size
The pop does not work because the stack pointer has changed.
To make this also work with bound checking the code is now
using the stack probing from alloca.
i386-gen.c:
- Fix large stack size alloca code.
The returned value of alloca was not used corectly.
libtcc.c:
- Use __SIZE_TYPE__ for __builtin_offsetof
tccpp.c:
- Fix __MAYBE_REDIR and abort builtins.
tests/tests2/Makefile
- Run 117_gcc_test also with bound checking enabled
This found the above problems.
those aren't preprocessed, but our use of a fake file in
preprocess_start requires inline stack processing (which isn't done
without preprocessing). Just don't try to setup anything requiring
preprocessing at all in this case.
for benchmarking the preprocessor, without having to use the PP_BENCH
macro. No output will be produced for '-E -bench', so it's the raw
tokenization/preprocess speed.
tccgen.c:
- cleanup __builtin_... stuff
- merge __attribute((alias("sym"))) with __asm__("sym")
Now one cannot have both, however for alias underscores are
added if enabled. For __asm__ they aren't.
tccpp.c:
- extend tcc_predefs accordingly. Was generated with
'cd tests/misc && tcc -run c2str.c tcc_predef.h tcc_predefs'
xxx-gen.c:
- move bcheck setjmp test to tccgen.c:gbound_args()
i386-gen.c:
- create win32 compatible stack space for big structures
tcctest.c:
- some cleanup + nicer output
tested on win32/64 to pass the tests when enabled
- libtcc.c :
let tcc define __leading_underscore if enabled
tcc_add_symbol() : add _ automatically
- tccelf.c : remove tcc_get_symbol_err(), find_c_sym()
currently symbol length is limited to 256 in several
places, so we can use a fixed local buffer for now as well.
- win32/lib/crtinit.c : new file for init/fini
- lib/*.S, tests7* : use __leading_underscore
- bt-log.c: this file wont work relibaly if compiled with gcc
- configure/Makefile : cleanup, really use CC_NAME
- tccasm.c : remove C99 construct that MSVC doesn't compile
- arm-gen.c, x86_64-gen.c, riscv64-gen.c, tccmacho.c : ditto
- arm64-gen.c: commit 383acf8eff wrote:
"Instead of a cast, it would be better to pass the exact type."
It is true that there are better solutions but it is not
passing the exact type (I think).
- tcctest.c: revert "fix cast test for clang" 03646ad46f
this obviously wants to test non-portable conversions
- 114_bound_signal.test: clock_nanosleep is too new for older
linuxes, just use sleep() instead
Thus it can parse command-line -Dsym=value directly, for the
convenience of libtcc users or tcc itself
Also used in libtcc_test_mt.c to avoid strdup().
tccelf.c/tccpp.c/tccrun.c
Change: "..."+int into &"..."[int] to avoid clang warning.
tests/tcctest.c:
- Change __APPLE__ into __clang__
- Add undefined_function for clang
- disable most asm code for clang
- Fix res6/res8 for __builtin_constant_p
This uses a glibc feature present since constructor/destructor support was added.
Modify tccrun.c to call constructor with argc, argcv, envp.
In lib/bcheck.c use these values to register them in the splay tree.
Remove HAS_ENVIRON is lib/bcheck.c as it is not needed any more.
Modify win32/lib/crt1.c/win32/lib/dllcrt1.c/win32/lib/wincrt1.c to also
call constructor with argc, argcv, envp.
While implementing I saw that tccrun did nog call main with envp. Fixed it.
Also fix fetch_and_add_arm.S to make it work on armv6 (raspberry pi default).
some linux programs (kernel) really want to have 'extern inline'
functions be visible from other units, i.e. not be static, but also
mark them as always_inline. That's -fgnu89-inline semantics, so it's
fine, but we don't (yet) implement this, so we can't make them static
just so. But we do need this hack on MacOS due to some uses in
system headers (see commit f18f8651).
So, for now conditionalize the hack on Mach-O.
via some heavy-handed hackery in the ASM symbol handling in case
C symbols get a leading underscore (but ASM symbols do not).
But this is now like clang and GCC on Darwin work: asm symbols are
undecorated, C symbols get a _ prepended, so to connect both some
trickery is involved for the ASM symbols that don't have a _ prepended.
They must be included in the C symbol table (because that's what we use
to lookup also ASM labels), but they also must not disturb the normal
C symbol (which don't have the _ prepended), so they need some mangling.
A bit unsatisfying, but well. So, add asm-c-connect-test to the working
ones for Darwin as well.
all except the below work now on MacOS, also as executable test,
not just with -run:
* dlltest - we don't support dylib generation (yet)
* memtest - tccmacho.c contains some leaks
* asm-c-connect-test - some confusion with underscores still
we need to disable or adjust some tests where clang behaves
slightly different from GCC:
* slight difference in __FILE__ behaviour
* difference (to less useful vs GCC) in computed #include
* difference in __builtin_constant_p
* attribute(weak, alias) isn't supported by clang on MacOS (though
it could be, as Mach-O has the capabilities for this)
* the built-in assembler of clang is mediocre
this was all checked with
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
* instead of /usr/include use the current SDK path as system
include directory (/usr/include is empty with current tools)
(this also removes the need to add these paths in individual
Makefiles)
* define _DARWIN_C_SOURCE in tcc.h to get the full set of decls
from system headers (e.g. vsnprintf), similar to _GNU_SOURCE
(and don't define _ANSI_SOURCE in the main Makefile anymore)
* tests/tests2/Makefile: remove the -w flag, it's added when necessary
in the rules generating the .expect files
this is needed for multi-file testcases using stdio.h, as
the __sputc function is implemented as a extern inline
function (with gnu_inline attribute, but we don't support that for now).
Without this change that leads to multiply defined symbols when using
multiple units including stdio.h.
It also has an always_inline attribute, which we can use to guide our
behaviour, as in ISO-C an always_inline can't be defined with ISO
'extern inline' semantics. This is the minimal change and not a full
implementation of GNU inline semantics, which would require thorough
testcases.
If __clang__ would be defined the header would make use of C99 semantics,
which would work for us. It would also do that if _GNUC_ wouldn't be
defined. But we can't do the latter (as the whole MacOSX SDK refuses
to be compiled with anything not defining that). I haven't tested
defining __clang__, but suspect that's going to be problematic.
* alloca needs to be _alloca
* int64_t and uint64_t are also defined in <sys/_types/_int64_t.h>
but as long long, not as long, so adjust out <stddef.h> to agree
on Darwin
* define __APPLE_CC__ so that <TargetConditionals.h> correctly defines
various macros like TARGET_OS_MAC and TARGET_CPU_X86_64
* non-process-shared POSIX semaphores aren't supported on
Darwin, we use the dispatch framework
* dlsym segfaults with RTLD_NEXT from JIT code, so we must not
even try this for -run. So we need to know in __bound_init
if called from -run code, or from normal code, which means passing
this down also from __bt_init and hence from the stub added in
tcc_add_btstub
* Darwin uses different structures for <ctype.h> facilities, this
merely adds a warning about this
* __libc_freeres doesn't exist
* for non -run modus the context (.prog_base member) is constructed
incorrectly (uses symbol zero for trying to get at the load bias,
which doesn't really work that way), on Mach-O this errors out
(and could also error out on ELF). For now deactivate this, which
makes backtraces not be symbolic on MacOS for not -run.
uncovered by the backtrace/boundcheck tests:
* handle STT_SECTION symbols
* call tcc_add_runtime (to get the bcheck.o/bt-exe.o files added)
* add .stab strtab into segments (we should probably add all stab
syms to the output LC_SYMTAB eventually, but right now TCC uses
32 bit stabs, while mach-o uses 32/64bit stabs
* <malloc.h> isn't as portable as <stdlib.h>
* skip 113_btdll.c on Darwin
* replace [...]\+ with [...]\{1,\} in the sed regex (basic REs
have no + even some sed(1) accept it as \+, but bounds _are_ part
of POSIX BREs)
for handling leading underscores when looking up symbols.
Necessary on MacOS, as there C symbols have a '_' prepended.
get_sym_addr (replacing get_elf_sym_addr) gets an argument to
specify if bare/raw/ELF symbols should be looked up or if decorated
C symbols should be looked up. That reflects into tcc_get_symbol.
tcc_add_symbol is _not_ yet changed, but probably should be.
all C/C++/ObjC symbols in symbols tables have a leading underscore
in Mach-O. Within TCC there's some confusion with tcc_add_symbol
(not adding it) and tcc_get_elf_symbol (not expecting it), and
resolve_syms (using dlsym, which doesn't expect it) and -run support.
But this sort of works.
these are resolved non-lazy for now. We only need to generate
the jump stub (using the GOT slot that will be initialized due
to the non-lazy pointer marking, like with data symbols). On
x86-64 we don't even need special marking of these stubs (with
S_SYMBOL_STUBS and associated additional indirect symbol entries),
as that's only used on i386 (where the stubs are self-modifying).
So, this now works:
extern int _printf(const char*, ...);
int _start(void)
{
_printf("hello\n");
return 0;
}
at least data symbols coming from dylibs can be used now, as in the
below. Note in the example that optind is defined in libc (really in
libsystem_c.dylib, reexported from libSystem.B.dylib):
static int loc;
extern int _optind;
int _start(void)
{
_optind = 0;
loc = 42 + _optind;
return loc - 42;
}
if a GOT slot is required (due to codegen, indicated by
presence of some relocation types), then it needs to contain
the address of the wanted symbol, also when it's local and defined,
i.e. not overridable. For simplicity we use a GOT slot for that as
well (other storage would require rewriting relocs and symbols,
as resolving of GOT relocs is hardwired to be based on s1->got).
But that means we need to fill in its indirect symbol mapping slot as
well, for which Mach-O provides a mean to say "not symbol based,
resolved locally". So this fixes this testcase:
static int loc;
int _start(void)
{
loc = 42;
return loc - 42;
}
(where our codegen currently uses a GOT-based access for the write
by accident)
this now sorts the symbols properly (local, global defined, undefined;
the latter two by name), marks the three ranges within LC_DYSYMTAB,
generates a __got section (non-lazy pointers) and slots for
relocations which need them, and the indirect symbol mapping for
them.
This doesn't yet deal with undefined symbols. But it means compared to
last example now this also works, i.e. read access to _global_ data:
% cat simple3.c
int loc = 42;
int _start(void)
{
return loc - 42;
}
this creates a proper LC_SYMTAB, with reasonable entries. It's
not sorted, so not usable for LC_DYSYMTAB. But 'nm -x -no-sort'
allows to see us some useful info.
This also relocates sections and symbols, so now this example
works as well (i.e. read access to static local data):
% cat simple2.c
static int loc = 42;
int main(void)
{
return loc - 42;
}
this does generate a working executable for a very simple
example input, e.g. this:
% cat simple.c
int main(void)
{
return 0;
}
% ./tcc -B. -c simple.c
% ./tcc -nostdlib -B. simple.o -lc
% ./a.out && echo okay
okay
(the -lc is actually not necessary right now, see below). This
has many limitations:
* no symbol table, hence no calls to external functions from
e.g. libc, aka libSystemB
* no proper entry point (should be main, but is hardcoded to first
real .text address)
* libSystemB is hardcoded, no other libs are supported (but again
no external calls anyway)
* generated Mach-O executable is in old format: neither LC_DYLD_INFO
no export tries for symbols are created (no symbol table at all!)
* the __LINKEDIT segment is faked and empty, as dyld doesn't like
it empty even if no symbols point into it
* same with __DATA, dyld wants a non-empty writable segment which
we enforce with useless data
* no relocations, hence no function call stubs (lazy or not) are
generated
* hardcodes some other constants as well
we ignore dylibs for now (can't inspect them yet for meta-info).
Also don't try to load GNU linker scripts, it's simply an unknown file
type (e.g. when mentioning Mach-O object files).
cctools for MacOS 10.14 (at least) unconditionally uses the
__has_include preprocessor directive (i.e. without checking
if defined __has_include
as normally suggested for portable code). So we need to handle
it a little bit. For now we simply say "nope" aka evaluate to 0.
- call TOK_GET() as a function only for tokens with values
- get rid of 'next_nomacro_spc()'
- be sligtly more efficient in next()
This made about 4-5%+ speed in my tests.
Also: tcc.h: reorder tokens
It might have advantages in cases if tcc/libtcc does not
depend on extern files.
Also:
- apply "stray \\ ..." check to macros only. For files it
was already checked. Add positive test.
from e640ed1aeb
Also:
- cleanup -std, -O, -pthread
- tcc.h:win32: use win32-type include paths even for cross
compilers (needed for loading tcc_predefs.h in cases)
- Makefile: simplify OSX .dylib clause
Add code for VT_FUNC.
Use octal number for unsigned int/unsigned long for 32 bits targets.
Add VT_BYTE | VT_UNSIGNED for targets with default unsigned signed char.
Remove extra ',' in default_debug struct.
Checked on:
- i386/x86_64 (linux/windows)
- arm/arm64 (rapberry pi)
- riscv64 (simulator)
Not tested for arm softfloat because raspberry pi does not support it.
Modifications:
Makefile:
add arm-asm.c to arm64_FILES
add riscv64-asm.c (new file) to riscv64_FILES
lib/Makefile:
add fetch_and_add_arm.o(new file) to ARM_O
add fetch_and_add_arm64.o(new file) to ARM64_O
add fetch_and_add_riscv64.o(new file) to RISCV64_O
add $(BCHECK_O) to OBJ-arm/OBJ-arm64/OBJ-riscv64
tcc.h:
Enable CONFIG_TCC_BCHECK for arm32/arm64/riscv64
Add arm-asm.c, riscv64-asm.c
tcctok.h:
for arm use memmove4 instead of memcpy4
for arm use memmove8 instead of memcpy8
tccgen.c:
put_extern_sym2: for arm check memcpy/memmove/memset/memmove4/memmove8
only use alloca for i386/x86_64
for arm use memmove4 instead of memcpy4
for arm use memmove8 instead of memcpy8
fix builtin_frame_address/builtin_return_address for arm/riscv64
tccrun.c:
Add riscv64 support
fix rt_getcontext/rt_get_caller_pc for arm
tccelf.c:
tcc_load_dll: Print filename for bad architecture
libtcc.c:
add arm-asm.c/riscv64-asm.c
tcc-doc.texi:
Add arm, arm64, riscv64 support for bound checking
lib/bcheck.c:
add __bound___aeabi_memcpy/__bound___aeabi_memmove
__bound___aeabi_memmove4/__bound___aeabi_memmove8
__bound___aeabi_memset for arm
call fetch_and_add_arm/fetch_and_add_arm64/fetch_and_add_riscv64
__bound_init: Fix type for start/end/ad
__bound_malloc/__bound_memalign/__bound_realloc/__bound_calloc: Use size + 1
arm-gen.c:
add bound checking code like i386/x86_64
assign_regs: only malloc if nb_args != 0
gen_opi/gen_opf: Fix reload problems
arm-link.c:
relocate_plt: Fix address calculating
arm64-gen.c:
add bound checking code like i386/x86_64
load/store: remove VT_BOUNDED from sv->r
arm64_hfa_aux/arm64_hfa_aux: Fix array code
gfunc_prolog: only malloc if n != 0
arm64-link.c:
code_reloc/gotplt_entry_type/relocate: add R_AARCH64_LDST64_ABS_LO12_NC
relocate: Use addXXle instead of writeXXle
riscv64-gen.c:
add bound checking code like i386/x86_64
add NB_ASM_REGS/CONFIG_TCC_ASM
riscv64-link.c:
relocate: Use addXXle instead of writeXXle
i386-gen.c/x86_64-gen.c
gen_bounds_epilog: Fix code (unrelated)
tests/Makefile:
add $(BTESTS) for arm/arm64/riscv64
tests/tests2/Makefile:
Use 85 only on i386/x86_64 because of asm code
Use 113 only on i386/x86_64 because of DLL code
Add 112/114/115/116 for arm/arm64/riscv64
Fix FILTER (failed on riscv64)
tests/boundtest.c:
Only use alloca for i386/x86_64
an enum must be compatible with one or more integer type,
so adjust the test accordingly. That means the following
redeclarations should work:
enum e6 { E1 = -1, E0 };
void f3(enum e6);
void f3(int); // should work as int and e6 are compatible
while the following should not:
void f4(enum e6 e);
void f4(unsigned e); // should error as unsigned and e6 are incompatible
they were emitted too early, in particular also in macro
substitution which might turn out to not be stray in case it's
further stringified. Check in next() instead. Add two testcases
that an error is still emitted for obvious top-level baskslashes,
and that stringifying such a thing works.
i386-gen.c:
- load/gen_opf: set v1.sym to NULL
lib/Makefile:
- Add -gstabs -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
lib/bt-log.c:
- tcc_backtrace: Prevent __builtin_frame_address warning
tccgen.c:
- struct_layout: Set t.t to VT_BYTE
- default_debug: Use octal instead of -1 to make size_t work
tccpp.c:
- tal_realloc_impl: Only memcpy when p set
x86_64-gen.c:
- gen_bounds_epilog: Do not save/restore rcx (not caller/callee saved)
This also made stack not aligned to 16 bytes.
tcctok.h:
- Add __bound_setjmp/setjmp/_setjmp/longjmp
tccgen.c:
- redirect setjmp/longjmp to bcheck.c code
i386-gen.c/x86_64-gen.c
- Change func_bound_alloca_used into func_bound_add_epilog
- Set func_bound_add_epilog also when setjmp is called
bcheck.c:
- Add __bound_setjmp/__bound_longjmp
- __bound_local_delete: remove setjmp if used in function
- __bound_exit: clear setjmp list and print statistic
- make malloc_redir more readable (unrelated)
New testcases:
- 115_bound_setjmp
- 116_bound_setjmp2
Merge function attributes with those given given for the
prototype, also handle post-decl appearance such as
void func() __attribute__((noreturn))
{
}
Also, some test fixes (unrelated).
from 3e731e3a78
tccgen.c:
- make 'struct default_debug' const
- pass TCCState* as parameter to tcc_debug_xxx functions
- always check tcc_state->do_debug before calling functions
- factor out tcc_debug_extern_sym()
- remove formats "%lld"/"%llu" (not reliable on windows)
xxx-gen files:
- set func_vt/var from caller
for simplicity handles like -v (verbose), but enables the usual idiom
of configure scripts to use '$CC --version' to find out the compiler
variant and version.
This allows debugging with variables/structs/unions/enums/bitfields.
Add new functions:
- tcc_debug_stabs: store stabs debug info
- tcc_debug_stabn: store stabn debug info
- tcc_get_debug_info: generate stabs debug info
- tcc_debug_finish: store debug info in debug section
- tcc_add_debug_info: Add function debug info
Update functions:
- tcc_debug_end: free debug hash
- tcc_debug_funcstart: Generate correct function debug info
- tcc_debug_funcend: Finish debug info
- put_extern_sym2: Generate debug info for symbols
- pop_local_syms: Add debug info
- prev_scope: Add local symbols
it doesn't round so the RM field can be zero. According to some
sourcs it should be set to zero by software in these cases, and
the binutils disassembler doesn't like us setting it to 7.
This shouldn't matter in practice, but who knows.
This makes available the __builtin_va_list type and __builtin variants
of va_start, va_arg, va_copy and va_end. We do this via a header file
that's prepended to all compilations always (except if merely
preprocessing): tcc_predefs.h. That header could also be used
for predefining other builtins in the future.
We don't need the define hacks for musl anymore with this.
Also fix x86_64 gfunc_prologue to reserve enoug space for the
full va_list structure, not just 16 bytes.
this partly reverts 1803762e3 to fix stdarg on x86-64 again. I've tried
to retain the apple specific changes from that commit.
Also include stdarg.h first in tcc.h, maybe that helps as well.
When compiling on macOS (at least in version 10.12) the TCC compiler failed
to compile libtcc1.a. Three problems were solved:
- The predefined macro "__APPLE__" is now available, as it is tested in the
libc darwin header files
- the libtcc1 Makefile defined _ANSI_SOURCE, although it used signals
- stdargs.h defined va_list differently from the darwin libc.
If the darwin standard library was included BEFORE stdargs this caused
problems.
- the darwin libc generated a warning if GCC < 4 was used
- additional defines are predefined now to make darwin libc headers compile.
as there's overlap between handling types for binary and ternay
operations. Factor this into a single routine (combine_types).
This uses the structure that gen_op was following, and expr_cond
was using as well in the past, which I find easier to reconvene
with the standard language. But it reuses the new functions for
diagnostics to improve (a little) on what GCC or clang produce :)
the support for the macro GCC_MAJOR is gone since 2017, and it's
fairly doubtful that anyone serious is using gcc 2.95.
Also adds a test for the ternary ops typing rules: 'x?bool:bool' has
to promote to int.
as per testcase. We must not reset token.sym_label twice with
kept symbols. This is no problem for non-label symbols because those
aren't generated on demand when mentioning them.
On windows. there is no long double really IOW it is the
same as double. However setting the VT_LONG flag in
combination with VT_DOUBLE allows to keep track of the
original type for the purpose of '_Generic() or more
accurate type warnings.
... in order to avoid fp stack overflow (see test below).
#include <math.h>
#include <stdio.h>
int main()
{
printf("%f %f %f %f\n", trunc(1.2), rint(1.2), trunc(1.2), rint(1.2));
printf("%f %f %f %f\n", trunc(1.2), rint(1.2), trunc(1.2), rint(1.2));
printf("%f %f %f %f\n", trunc(1.2), rint(1.2), trunc(1.2), rintl(1.2));
}
Also in rintl:
- 'long double' is not a ten-byte float on windows.
- Updated msvcrt.def with symbols from 64bit version of dll - it contains the float math functions missing in the 32bit dll.
- Made sure this patch only apply to to WIN32 and WIN64. For WIN32 float functions calls the double variants, on 64bit they are called natively.
by calling the double functions and removing unsupported __asm implementations using "=t".
This patch also enables the double version of logb(double).
Note: None of the 'long double' variants works though - could easily be fixed
by aliasing the double equvalents for completeness/compability.
Fix static assert to support literal string instead of just printing
the sring of the current token as it use to be
so we can now use _Static_assert(0, "0" "1") which will print
__FILE__ __LINE__ error: 01
commit ef42295fe8 intrduced 4 .o files to
win32/lib. But they (bcheck.o, bt-dll.o, bt-exe.o and bt-log.o) are not
removed by "win32/build-tcc.bat -clean". This commit should fix it.
- revert const-folding in gvtst() and put it back into
expr_landor(). Although it did make sense, one reason
not to do it is __builtin_constant_p() which may return
true when it shouldn't because of nocode_wanted, see test.
- tccgen_init() can do init_prec(), also for tcc -E.
- for nostalgic reasons, keep the original expression parser
functions in the source.
- Makefile: remove stale stuff
so that it also is called from the precedence parser. This
is complicated by the fact that something needs to be done before
the second operand is parsed in a single pass compiler, so it
doesn't quite fit into expr_infix itself. It turns out the smallest
code changes result when expr_landor remains separate. But it can
be tidied a bit.
This is smaller and uses less stack depth per expression (eight function
calls from expr_or to get down to a unary). It's a tiny bit faster
depending on how good the branch predictor is, on my machine a wash.
ELF files that refer to shared libs containing sym-versions, but
don't refer to any dynamic symbols with symbol versions (should happen
only with very simple shared libs) would generate an empty .gnu.version_r
section. Some dynamic linker contain bugs in that they don't check
the section size or DT_VERNEEDNUM (which are both zero for such files
we generate) before accessing the first entry, and then bail out with
a message like
./a.exe: error while loading shared libraries: ./a1.so: unsupported
version 25960 of Verneed record
(where the "version number" actually comes from neighboring bytes
from different sections).
So, there's not much choice, we simply must not generate such section.
- tests2/113_btdll.c: test handling multiple stabs infos
Also:
- libtcc.c: remove _ISOC99_SOURCE pre-defines. It is causing
strange warnings such as 'strdup not declared'
- i386/x86_64-gen.c cleanup bounds_pro/epilog. This discards
the extra code for main's argv. If needed, __argv might be
processed instead.
- tccgen.c:block(): reduce stackspace usage. For example with
code like "if (..) ... else if (..) ... else if (..)... "
considerable numbers of nested block() calls may occur.
Before that most stack space used when compiling itself was
for libtcc.c:tcc_set_linker().
Now it's rather this construct at tccpp.c:2765: in next_nomacro1():
if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
|| c == '.'
|| ((c == '+' || c == '-')
...
the strcat checker first checks dest for overlap, then src.
If the padding byte between b[] and the pad[] arrays happens to be zero
the dest check would have succeeded and the src test failed. If that
padding byte would be zero the dest check would trigger first.
As we can't influence the padding byte (only the b[] and pad[] arrays)
it was random if the dest or src checks triggered.
This makes it reliably trigger the dest check first.
This makes it possible to get backtraces with executables
(including DLLs/SOs) like we had it already with -g -run.
Option -b includes -bt, and -bt includes -g.
- new file lib/bt-exe.c: used to link rt_printline and the
exception handler from tccrun.c into executables/DLLs.
- new file lib/bt-log.c: provides a function that may be
called from user code to print out a backtrace with a
message (currently for i386/x86_64 only):
int (*tcc_backtrace)(const char *fmt, ...);
As an extra hack, if 'fmt' is prefixed like "^file.c^..."
then the backtrace will skip calls from within 'file.c'.
- new file lib/bt-dll.c: used on win32 to link the backtrace
and bcheck functions with the main module at runtime
- bcheck.c: now uses the tcc_backtrace function from above
- tccgen.c: minor cleanups
- tccelf.c: stab sections get SHF_ALLOC for easy access.
Also in relocate_section(): 64bit relocations for stabs
in DLLs cannot work. To find DLL addresses, the DLL base
is added manually in tccrun.c via rc.prog_base instead.
- tccpe.c: there are some changes to allow merging sections,
used to merge .finit_array into .data in the first place.
- tccpp.c: tcc -run now #defines __TCC_RUN__
also: refactor a line in tal_realloc that was incompatible
with bcheck
- tcctest.c: fixed a problem with r12 which tcc cannot preserve
as well as gcc does.
- tests2/112_backtrace.c: test the feature and the bcheck test18
that previously was in boundtest.c
remove quadratic loops by not using side tables; address-taken
can simply be a flag per local sym, and the lbounds section can
be filled after symbols go out of scope at which point we know
if the address was taken, so that there's no need to compress it
again after the funcion is done.
we were emitting error messages for something like
'static int i = 2 || 1/0', even though the exception would be in
the unevaluated part. This doesn't destroy const-ness, so we must
accept it. This requires splitting the nocode_wanted values a bit more,
so that nocode_wanted due to const_wanted can be differentiated from
nocode_wanted due to non-evaluation.
Add __attribute__((constructor)) to __bounds_init.
- remove tcc_add_bcheck from i386-link.c and x86_64-link.c
- add simplified tcc_add_bcheck to tccelf.c
- Update tccrun.c to call constructor/destructor.
Set dynsym sh_info to number of local symbols in tccelf.c
Reduce stack size when bounds checking is enabled.
Added variable TCC_LIBBCHECK for windows support.
Add signal stack to detect stack overflow.
Add all & parameters in lbound_section and remove them if not used.
Close fd in tcc_relocate in tccrun.c
Fix section type constructor/destructor in tccelf.c
Add check code in tests/boundtest.c for mem/str functions.
Remove -ba from documentation.
Add bounds check signal info in documentation.
bcheck.c:
- Fix initial_pool alignment.
. Fix printf statements.
. Add prototypes for all external interface functions.
- Add TCC_BOUNDS_WARN_POINTER_ADD environment variable.
. Add ctype and errno data.
- Fix alloca when multithreading is used.
- Add lock for __bound_checking and __bound_never_fatal.
- Catch pthread_create and use locks when called.
- Detect in loaded in shared lib and use locks when found
- Use spin locks instead of semaphore locks.
- Make spin locked code as small as possible.
- Fix mem/str functions checking.
- Fix overlap checking mem/str functions.
this is a bit complicated: for i386 and x86-64 we really need to
extend return values ourself, as the common code now does. For arm64
this at least preserves old behaviour. For riscv64 we don't have to
extend ourself but can expect things to be extended up to int (this
matters for var-args tests, when the sign-extension to int64 needs to
happen explicitely). As the extensions are useless, don't do them.
And for arm32 we actually can't express GCC behaviour: the callee side
expects the return value to be correctly extended to int32, but
remembers the original type. In case the ultimate target type for the
call result is only int, no further extension is done. But in case
the target type is e.g. int64 an extension happens, but not from int32
but from the original type. We don't know the ultimate target type,
so we have to choose a type to put into vtop:
* original type (plus VT_MUSTCAST) - this looses when the ultimate
target is int (GCC: no cast, TCC: a cast)
* int (without MUSTCAST) - this looses when the ultimate target is
int64 (GCC: cast from original type, TCC: cast from int)
This difference can only be seen with undefined sources, like the
testcases, so it doesn't seem worthwhile to try an make it work, just
disable the test on arm and choose the second variant as that generates
less code.
This allows adding files or libraries from
#pragma comment(option, ...)
Also, {f}/file.c will be expanded with the directory of
the current source, that is the file that has the #pragma
Put total_lines etc. into TCCState. Also, initialize
the predefined compiler types for the preprocessor too.
tccpe.c: fix BaseOfCode if .init section present (with tcc -b)
protect some more accesses to global data with the semaphore.
(And for the testcase: don't just write into global data, use local
copies; it's not important for speed here).
* a major revision of the rt_printline() feature in
tccrun.c to report file:linenumber more correctly.
* minor changes to the stab info produced by the
compiler in tccgen.c
However stab addresses are limited to 32 bits. I added
a work around:
if (sizeof pc == 8)
pc |= wanted_pc & 0xffffffff00000000ULL;
However GDB has problems with that too.
- revert Makefiles to state before last bcheck additions
Instead, just load bcheck.o explicitly if that is
what is wanted.
- move tcc_add_bcheck() to the <target>-link.c files and
remove revently added arguments. This function is to
support tccelf.c with linking, not for tccgen.c to
support compilation.
- remove -ba option: It said:
"-ba Enable better address checking with bounds checker"
Okay, if it is better then to have it is not an option.
- remove va_copy. It is C99 and we try to stay C89 in tinycc
when possible. For example, MS compilers do not have va_copy.
- win64: revert any 'fixes' to alloca
It was correct as it was before, except for bound_checking
where it was not implemented. This should now work too.
- remove parasitic filename:linenum features
Such feature is already present with rt_printline in
tccrun.c. If it doesn't work it can be fixed.
- revert changes to gen_bounded_ptr_add()
gen_bounded_ptr_add() was working as it should before
(mostly). For the sake of simplicity I switched it to
CDECL. Anyway, FASTCALL means SLOWCALL with tinycc.
In exchange you get one addition which is required for
bounds_cnecking function arguments. The important thing
is to check them *BEFORE* they are loaded into registers.
New function gbound_args() does that.
In any case, code instrumentation with the bounds-check
functions as such now seems to work flawlessly again,
which means when they are inserted as NOPs, any code that
tcc can compile, seems to behave just the same as without
them.
What these functions then do when fully enabled, is a
differnt story. I did not touch this.
There was a problem with strncpy and strncmp.
Made bound_ptr_add and bound_ptr_indir a little bit faster.
Fix statistic counter types. Change long into long long.
The following functions are now also bounds checked:
memcmp, strncpy, strcmp, strncmp, strcat, strchr, strdup.
Add statistics code for bounds checking functions.
The statistics can be printed by settings environment variable
"TCC_BOUNDS_PRINT_STATISTIC".
Enabled more tests in test/Makefile.
The bounds checking code has now enabled gen_bounded_ptr_add tests.
This makes the code slower but finds more errors.
I had to correct some things in tcc to make it work.
- Fixed off by one in lib/bcheck.c
- Corrected tccelf.c sym_versions.
- Disabled USE_TAL when using bounds checking.
- Fixed cstr_printf va_start.
- Fixed tests/tests2/46_grep.c off by one error.
- Updated gen_bounded_ptr_add in x86_64-gen.c
- Fixed x86_64-link.c pointer diff.
For gen_vla_alloc now always use alloca call when bounds checking.
Added line/filename in %rax before bound calls to find location of error.
my last patch here fixed a missing dependency, but in the wrong
way. It would build some object files twice, which could race.
The lib/all target already builds both libtcc{,b}1.a libs, so
a simple dependency is enough.
This allows creation of TCCStates and operation with API
calls independently from each other, even from threads.
Frontend (option parsing/libtcc.c) and backend (linker/tccelf.c)
now depend only on the TCCState (s1) argument.
Compilation per se (tccpp.c, tccgen.c) is still using
globals for convenience. There is only one entry point
to this section which is tcc_compile() which is protected
by a semaphore.
There are some hacks involved to avoid too many changes,
as well as some changes in order to avoid too many hacks ;)
The test libtcc_test_mt.c shows the feature. Except this
new file the patch adds 87 lines overall.
on i386 111_conversion.c breaks when save_reg_upstack isn't careful
about r2 and type mismatches. The bcheck patches fixed this by
enlarging the stack slot beyond the natural type, this variant simply
avoids saving the second register is the type indicates that it isn't
needed.
Adds also a comment how this should ideally work, namely that type
and r/r2 entries in the vstack are consistent. In the 111_conversion
testcase it's specifically gen_cast via gen_cvt_ftoi that breaks
this, but there more general code broken as well, so that would deserve
a careful fixup based on some additional asserts.
so it isn't quadratic in number of symbols. It's still quadratic
in number of lib/version combinations (at library load time the
sym versions are internalized), but that's much less a problem as
in practice only glibc uses sym versioning.
This fixes the issue
int main() { extern char *x; }
void main1() { extern char *x; }
t2.c:5: error: incompatible types for redefinition of 'x'
(reported by Giovanni Mascellani 2019/07/16)
Fedora, RHEL and Centos have a default page size of 64K for arm64, so
bump up the page size so that ELF sections of the generated inary are
correctly aligned for 64K pages too.
this fixes the ret_mixed_test of abitest.c, now everything of the
testsuite works.
The generic code for returns is good enough for our use, except in
the specific case of a mixed int/float structures returned in registers,
so instead of duplicating the whole generic gfunc_return function, add
another modus for gfunc_sret: returning -1 makes the actual register
transfer by a new backend function.
relocs against defined symbols are replaced by relative
relocs, when a GOT slot is created. But code relocs (usually
calls via PLT) use the plt_offset member of attr, not the got_offset
member, so the "huh" warning was triggered in the case of calls to
static functions (the code still worked).
So, for now just use the AUTO_GOT_PLT mechanism. We could also
emit a non-PLT reloc in the backend for calls to VT_STATIC functions
(like the x86-64 backend does) and do the same as for x86-64 in
build_got_entries (which transforms PLT32 into PC32 relocs, riscv
would transform CALL_PLT into CALL relocs). Maybe later.
this fixes ret_2float_test, ret_2double_test and
ret_8plus2double_test of abitest.c. The common gfunc_return
actually works for these cases, so let's use that for now.
The ret_mixed_test (as well as mixed2 and mixed3) are left
broken, and tccgen.c:gfunc_return can't be used for that as is,
so I'll leave the gfunc_return implementation in riscv64-gen.c for
now, I'll have to think about this some more.
this is it! With this tcctest.c works, as well as compiling
TCC with itself. abitest.c doesn't yet work due to known
problems, all the rest does. There are still warnings during
linking.
float to int must be truncations, not normal rounding.
And ftof was typoed to select the wrong conversion function.
This fixes tcctest.c completely. (make -C tests test1)
loads and stores to global symbols need to go via the
GOT (at least for weaks), otherwise -run doesn't work.
Ideally we'd generate GOT relocs (and loads) always and replace
them with PCREL relocs and adds during linking.
the invariant for the risc-v codegen is, that 64bit regs
generally contain the sign-extension of a 32bit value.
This wasn't heeded by loads of 32bit values from memory, which
used lwu and ultimately caused a miscompilation in string_test
of tcctest.c.
Now most of tcctest.c works (not with -run, but with linking
a real executable), except some ftoi/ftof conversions.
for the implementation of operations we can reuse the ones
from lib/lib-arm64.c, risc-v long double is also float128.
Also implement ggoto, and PDIV, and use t0 in load/store as
temporary register if necessary, not one given by get_reg
(the latter can destroy assignments of long double parameters
in function calls that are already set up).
This let's us compile tcc.c and tcctest.c, though both
don't yet work.
some constants were loaded wrong (e.g. 0xffffabcdU), and
risc-v needs to do explicit zero-extensions for widening from
32bit (not sign-extensions like the other 64bit targets).
This makes the whole tests2.all testsuite work.
Parameter passing is still not psABI-compliant, but internally
consistent. (e.g. structs of two floats/doubles are passed
in integer registers, but should sit in float regs).
this also fixes passing of params > 16 bytes. In riscv
they aren't passed by value on stack, but via reference (and
because callees are allowed to modify by-ref params the caller must
allocate an own copy per call).
This fixes the stdarg parts of 73_arm.c.
like long double (16 bytes) and structs. Not completely
correct, but 73_arm64 somewhat works now (when the stdarg part
is disabled), though with some errors. What's definitely incorrect
is arguments of a mixed int/float struct. I'm using VT_LDOUBLE
(which conveniently has to be placed in a int-reg-pair) to load/store
structure arguments of size > 8 and <= 16, and that can lead to
overreads.
for 101_cleanup we need 256kb stack (with the associated problem
of needing a larger prologue/epilogue) as well as jumps out of
range for the 21bit offsets (exactly for second part of the prologue).
* support loading sym addresses from GOT: important for weak syms,
fixes 104_inline. This is still incomplete, it only works
for taking the sym address, not for directly loading/storing into
such symbols (i.e. not for VT_LVAL)
* another op: '%'
* ELF flags: add EF_RISCV_FLOAT_ABI_DOUBLE, which is our ABI.
fixes 95_bitfields. loading 64bit constants is suboptimal
right now. int32_t shifts really need to use the W form,
otherwise 'x << 24 >> 24' doesn't extract the low 8 bits.
long double on risc-v is 128bit, but there are no registers
for that type (without the Q ISA extension). They are passed
like two 64bit integers values (with an exception for varargs,
where it's an aligned register pair). This all requires some
hacks in generic code as otherwise RC_FLOAT regs are tried for
holding values of long double type, but we need a RC_INT register
pair. This really could all use some cleanup for all archs.
This doesn't implement any conversions of operations for long
double, but it's enough to get 70_floating_point_literals working.
* more ops: umod and udiv
* large immediates: suboptimal code, e.g. when loading
0xffffffffU (which is what a cast from long to int does).
tests2 work up to 67_macro_concat.
* load/store of FP ops
* load/store from symbols, VT_LLOCAL, some with large addend
* load of VT_JMP result
* calls with many args (stack slots)
* calls with FP args
* more operations: and/or/xor/div
* register indirect loads and stores
* load of local addresses
* indirect calls (uses ra as temporary reg if necessary)
* operations *, -, <<
* gen_cvt_sxtw: is not needed in most cases, let's see
tests2 runs until (incl) 09_do_while.
* implement compares, gtst and gsym/gjmp and add
* implement stores (simple cases)
* fix arg passing with more than one register arg, fix
loads to not always use 8byte loads
* add some predefined macros: __riscv, __riscv_xlen,
__SIZEOF_POINTER__ (needed by glibc header)
The first 5 tests of tests2 run now.
this is enough to let me link a tcctest.c compiled by GCC
using some current debian sid riscv64 system. It needs
linking against libgcc.a for various floating point TFmode
routines. The result runs.
the uninitialized cumofs was leading to random sizes for
the memset when initializing local structures, potentially
leading to segfaults from it. Only a problem with GNU
designated initializers, which we didn't test very well.
See testcase.
- libtcc.c/tccpp.c: fix -U option for multiple input files
- libtcc: remove decl of tcc_add_crt() for PE
- tcc.h: define __i386__ and __x86_64__ for msvc
- tcc.h: undef __attribute__ for __TINYC__ on gnu/linux platforms
- tccelf.c: disable prepare_dynamic_rel unless x86/x64
- tccpe.c: construct rather than predefine PE section flags
- tccpp.c: (alt.) fix access of dead stack variable after error/longjmp
- x86_64-gen.c: fix func_alloca chain for nocode_wanted
- tccpp.c/tccgen.c: improve file:line info for inline functions
- winapi/winnt.h: correct position for DECLSPEC_ALIGN attribute
- win32/lib/crt: simplify top exception handler (needed for signal)
- arm64-gen.c: remove dprintf left from VT_CMP commit
- tccgen.c: limit binary scan with gcase to > 8 (= smaller code)
- tccgen.c: call save_regs(4) in gen_opl for cmp-ops (see test in tcctest.c)
This removes a spurious \r at $gcc_{major,minor} in configure on cygwin.
Details:
The EOL output of conftest.exe for windows was \r\n . Now it's only \n .
The output of conftest is used with sh command substitutions which trim
trailing newlines, but not all windows shells consider \r\n as newline.
E.g. msys2 and busybox (for windows) were designed for tight integration
with windows apps and their shells do trim \r\n, but cygwin sh is closer
to POSIX and trims only \n - leaving \r at the string.
Adds a tool `ppif` at configure which can test preprocessor conditions
even when $cc is a cross compiler to any foreign platform.
Currently used only to identify i386 or x86_64 (including when cross
compiling) as a mini-demonstration.
Hopefully will be used in the future to test more compiler features
and/or replace uname-related tests with more accurate results.
A more automatic approach to code suppression (aka. nocode_wanted)
The simple rules are:
- Clear 'nocode_wanted' at (im/explicit) label IF it was used
- Set 'nocode_wanted' after unconditional jumps
Also in order to test this then I did add the "function might
return no value" warning, and then to make that work again I
did add the __attribute__((noreturn)).
Also moved the look ahead label check into the type parser
to gain a little speed.
Example:
int a = 1;
void f(void)
{
int a = 2;
{
extern int a; // = 1 !!
....
To get this (more) correctly there is a new function to copy
syms between local to global stacks.
Also, this patch changes the meaning of VT_EXTERN back
to the simpler and IMO more useful notion of
DECLARED but not (yet) DEFINED.
and that for both variables and functions. That is, VT_EXTERN
in tcc doesn't have to do with the keyword 'extern' necessarily.
Also this patch does allow
int x[];
as alias for
extern int x[];
(as do gcc and msvc)
new glibc really can't avoid it anymore, so let's provide it.
I've tried doing it only on systems that possibly are glibc
based. (For others it would be harmless as it simply wouldn't
be picked up from libtcc1.a)
... which IMO are:
1) files don't need a _test suffix because all files in
the directory are tests ;)
2) we test the BEHAVIOR of the program, rather than its
binary bit contents.
Ok, but nobody said a test can't use two files ;)
(where the 104+_ construct is meant to prevent the file
from being picked up by the makefile as a test on its own).
Previously test 104 used a combination of *nix tools and system() calls
to emulate a `sh` script, which required split code paths for windows
due to different shell and different absolute path representation.
Also, it used a hardcoded tcc binary path, didn't set locale for sort.
Now the tools are used from a `sh` script which the program generates
and invokes, tmp files are at CWD and no conversion is required, tcc
path is taken from Makefile (exported), and `sort` uses LC_ALL=C.
my last inline changes caused parameter names to be overwritten
always (as VT_EXTERN now doesn't mark the current def anymore),
leading to a compile error when including windows.h. Rework this.
Also silence a warning that currently happens for mingw, which is
written with gnu-inline behaviour in mind. Our work-arounds
of using "static inline" actually create invalid C (which we warn
about). Until we implement this properly, just silence the warning.
there's no need for two new flags in type.t . We just can't use
VT_EXTERN as marker if functions are defined or not (like we can
for objects), and then can simply implement the rules of C99/C11
by not overwriting VT_STATIC/VT_EXTERN at all but rather only
look at them. A function already on the inline list can be
forced by removing the VT_INLINE flag, and then linkage
follows from some combination of VT_STATIC, VT_EXTERN and VT_INLINE.
build_got might realloc the symbol table (for the _GLOBAL_OFFSET_TABLE_
symbol), so we can't reuse sym (a pointer into it) after build_got.
Using it isn't necessary, as we pass the sym_index to put_got_entry,
and that recomputes sym.
By always instantiating extern inlines, the patch has discovered
2 assembly errors, which were fixed in the original mingw64 in 2009.
This fixes those errors.
Additionally it changes __CRT_INLINE in win32/include/_mingw.h
from `extern __inline__` to `static __inline__`.
__CRT_INLINE is used exclusively in header files and as such
it should not create externally visible instantiations like a `extern
inline` would (as per the C standard).
- add tests for standard conformant inline functions
- implement it
The old tinycc failed to provide a conforming implementation
of non-static inlines. It would expose external symbols where it
shouldn't and hide them where it should expose them.
This commit provides a hopefully comprehensive test suite
for how things should be done. The .expect file can be obtained
by compiling the example c file (embedded in the test)
with a conforming compiler such as gcc, clang or icc and then
printing the exported symbols (e.g., with nm+awk+sort).
(The implementation currently reserves two new VT_ flags.
If anyone can provide an implementation without reserving
two extra flags, please replace mine.)
The macro conflicts (=> redef warnings in a simple hello world)
with a definition introduced by glibc headers and
it's probably not "necessary" anyway since clang doesn't use it.
GCC wouldn't be able to implement this either (due to the separate
phases of compilation and assembly). We could allow it but it
makes not much sense and actively can confuse broken code into
segfaulting TCC. At least we can warn.
Warning exposes a problem in tcctest, and fixing that gives us
an opportunity to also test .pushsection/.popsection and .previous
directive support.
the real difference is in decl0 where we can use external_sym
just fine also for function definitions, we don't have to use
external_global_sym. Setting VT_EXTERN in external_sym isn't
necessary either (the type will have it set if necessary).
The rest is tidying: removing unused arguments and moving
some code around.
we can register a top-level exception filter which does
nothing else than call into _XcptFilter (provided by
the default C runtime environment) and signal handlers
for the few POSIX signals that Windows can handle start
working (that includes e.g. SEGV).
anonymous struct members were somewhat broken as the testcase
demonstrates. The reason is the jumping through hoops to fiddle
with the offsets I once introduced to avoid having to track
a cumulative offset. That's now not necessary anymore and actively
harmful, doing the obvious thing is now better.
see testcase, when the inner array dimension of multi-dimensional
VLAs isn't given TCC was generating invalid vstack accesses.
Those are actually invalid, so just diagnose them.
this test is run only on i386 so its failing went unnoticed for
a while, since 1fd3709379. IS_ASM_SYMs should not be tested
for conflicting types, the C typing overrides.
_Noreturn, just like __attribute__((noreturn)), is ignored.
I also added stdnoreturn.h, in all its glorious uselessness.
_Alignas only works for integer expressions right now. In order
to comply, we need:
- _Alignas(type) -> _Alignas(_Alignof(type)).
- stdalign.h as soon as it is done.
Note: DR 444 is supported; it works on struct members.
Signed-off-by: Devin Hussey <husseydevin@gmail.com>
see testcases. A local 'extern int i' declaration needs to
refer to the global declaration, not to a local one it might
be shadowing. Doesn't seem to happen in the wild very often as
this was broken forever.
in presence of invalid source code we can't rely on the
next token to determine if we have or haven't already parsed
an initializer element, we really have to track it in some separate
state; it's a flag, so merge it with the other two we have (size_only
and first). Also add some syntax checks for situations which
formerly lead to vstack leaks, see the added testcases.
Also added a test yielding a failure with the previous definition,
i.e. when using: (va_end(ap));
The test also checks potentially incorrect va_start() definition.
sometimes abstract decls in parameter lists left the returned name
uninitialized potentially leading to segfaults, like in
int f(int ()) {
return 0;
}
Deal with this.
like on 'enum myenum { L = -1 } L;'. It's a bit tedious as
there are two paths (for global vs local symbols), and because
the scope and enum_val share same storage.
the ABIs (and other compilers) extend sub-int return values in the
caller. TCC extends them in the callee. For compatibility with
those other compilers we have extend them in the caller as well.
That introduces a useless double extension in pure TCC-compiled code,
but fixing that generally requires that the code generator of TCC would
understand sub-int types. For the time being bite the bullet.
encode most things in Syms, do only as much work as necessary
(e.g. pending cleanups), don't track scopes in a large
structure (instead encode the scopes with cleanups directly
in the cleanups tree). Removes ca. 120 lines of code.
old implementation use only a global static array for storing
ScopeTracker which have the advantage to be fast, but you can't
use cleanup in a function that have move than SCOPE_TCK_STORE_SIZE
scopes.
I don't want to use only dynarray_* as it would slow down tcc for
every functions, so I keep both stores.
The major difficulty was to handle cleanup when a goto happen
to do so, I've had a "ScopeTracker" struct.
I can't use local_scope because that would not work with code like below
as local_scope would be at the same level:
{
char * __attribute__ ((cleanup(clean_function))) str = "hej";
goto next;
}
{
next:
}
read() is allowed to short-read, and return less bytes then requested.
The caller must restart read() when this happens (and they want more
bytes).
This patch is still buggy, because errors are not always checked.
Still, less buggy than before.
symbols are local when defined and referred to from the executable.
Also, we need to relocate the .got section when this is a static link
(our static linking effectively generates code as if this were a dynamic
link with PLT and GOT, and then emulates the runtime loader).
Support multiple __label__ declarations at the beginning of a block
as long as they're contiguous.
gcc and clang accept:
{ __label__ a,b; __label__ c; /*...*/ }
.
Tcc would fail it. This patch makes it accept it.
The patch:
- if (tok == TOK_LABEL) {
+ while (tok == TOK_LABEL) {
In gfunc_call, regisger will be saved before gcall_or_jmp. The register
stored the function will be saved too, though in some generator the SValue
of this function will be immediately poped after gcall_or_jmp, and no need to be saved. So I modify some generator to avoid save redundant SValue before gcall_or_jmp.
Before this patch, save_reg can't reuse the temporary local variable
created before to save register. It may consume a lot of stack memory. this patch make save_reg reuse the temporary local variable.
when parsing the type in this cast:
(int (__attribute__(X) *)(int))foo
we ignored the attribute, which matters if it's e.g. a 'stdcall'
attribute on the function pointer. Only this particular placement
was misparsed. Putting the attribute after the '*' or outside the inner
parens worked. This idiom seems to be used on SQLite, perhaps this
fixes a compilation problem on win32 with that.
like qualifier merging the array sizes are merged as well
for the operands of ?:, and they must not statically influence
the types of decls.
Also fix some style problems, spaces aren't stinky :)
char **argv;
_Generic(argv, char**: (void)0);
_Generic(0?(char const*)0:argv[0], char const*: (void)0);
_Generic(argv, char**: (void)0);
would fail because the type of argv would get modified by the
ternary. Now allocate a separate type on the value stack to
prevent this error.
tcc would reject e.g.,
void f(){ struct {_Bool x:_Generic(({0;}),default:1);} my_x; }
with `expected constant`. This patch makes it accept it.
(The patch also makes tcc's _Generic a little more "generic" than that
of gcc and clang in that that tcc now also accepts
`struct {_Bool x:_Generic(({0;}),default:1);} my_x;` in file scope
while gcc and clang don't, but I think there's no harm in that
and gcc and clang might as well accept it in filescope too, given
that they have no problem with
e.g., `/*filescope:*/int x=1, y=2, z=_Generic(x+y, int:3);`)
The type within the cast (int (__attribute__((foo)) *)(void))
was misparsed because of the presence of the attribute (parse_btype
prematurely concluded that (__attribute__() *) is a type.
Also see testcase. This construct is used in sqlite it seems.
Prevent any decoration that would otherwise affect an exported
PE function. For example, given the following:
__declspec(dllexport) __stdcall
int decorated(int arg) {
return 0;
}
__declspec(dllexport) __stdcall __attribute__((nodecorate))
int undecorated(int arg) {
return 0;
}
The following exported functions can now be seen in the DLL:
_decorated@4
undecorated
The attribute is recognised for all targets but only
affects PE codegen. I'm not sure whether this would be
useful for other targets; its intended use was to allow
the creation of a DLL matching an existing set of signatures.
linkers don't treat relocations using symindex 0 (undefined)
very well, it can't be misused as indicator for an absolute number.
Just don't bother with special casing this, rather emit an indirect
call/jump right away. ARM64 needs the same (and didn't handle
calls via constant absolute func pointers before).
The testcase as is doesn't fail without the patch, it actually
needs separate compilation (to -fPIC .o file, then to shared lib)
to fail.
the lvalue Syms for arguments didn't correctly reflect
their own types in all cases (a side-effect of the type being
stored in type->t and the ->r members (as VT_LVAL_xxx), so the below
used an int load (not a byte load) in the conditional.
extern void bar (void);
void foo (signed char c)
{
signed char x = c;
if (c)
bar();
}
misc fixes including:
- tcc.c: fix "tcc -vv" for libtcc1.a on win32/PE
- tccelf.c: fix a crash when GOT has no relocs (witn -nostdlib)
- tccelf.c: fix stab linkage for zero n_strx
- tccgen.c: fix stdcall decoration for array parameters
int __stdcall func(char buf[10]) is _func@4 (was _func@12)
- tccgen.c: fix static variables with nocode/nodata_wanted
see tests2/96_nodata_wanted.c
- tccrun.c: align sections using sh_addralign (for reliable function_alignment)
- tests2/Makefile sort 100 after 99
- win32/include/sys/stat.h fix _stat and _wstat
- x86_64-gen.c: win64/gfunc_call: fix a bug with xmmN register args
previously overwrote valid other xmmN registers eventually
This is supposed to fix a bug where libtcc eventually was trying to
compile libtcc1.a as C source code.
Anyway, there is now only two functions that refer to s->filetype,
tcc_add_file() and tcc_add_library().
which requires being able to emit an arbitrary number of NOP
instructions, which is also implemented here. For x86 we
could emit other sequences but these are the easiest.
This patch makes tcc ignore them.
Normally (as per the C standard), They should
be only applicable inside parameter arrays
and affect (const/restrict) the pointer the
array gets converted to.
[matz: fix formatting, add volatile handling, add testcase,
add comment about above deficiency]
Code like:
#include <signal.h>
int main() { _Generic(signal, int: 0); }
should fail with
error: type 'extern void (*(int, void (*)(int)))(int)' does not match any association
not
error: type 'extern void *(int)(int, void *(int))' does not match any association
[matz: fix formatting, fix function-to-pointer decay for operands of
_Generic, add testcase for this]
A target triplet of arm-linux-gnueabihf indicates that the compiler
should use the VFP variant of the calling convention which as its name
implies requires VFP. This commit enables VFP when triplet is
arm-linux-gnueabihf.
In prepare_dynamic_rel() on non x86 targets the count++ statements
appear before any case label and are therefore dead code. This triggers
build failure when building with -Werror. This patch adds an extra guard
around all the x86 case labels and their associated action, leaving just
the default case label for non x86 targets which builds fine.
Origin: vendor
Forwarded: no
Last-Updated: 2018-02-24
for a final link we shouldn't emit relocation sections that are applied
already. For now we need to emit ALLOCed .rel sections as they contain
dynamic relocs, they should be put into their own (new) section instead.
the rules for constant expressions in static initializers are more
relaxed than for integer constant expressions. We need to accept
0.0/0.0 in static initializers (in non-static initializers the potential
exceptions need to be raised though, so no translation-time calculation
then).
This reverts commit 3f8225509b.
It fixes the linking case but introduces an ugly error with -c
about adding a library. To fix both uses the old code structure is
better.
adding -pthread confused option parsing as the number of file counting
came out wrong. Simplify and fit it, can be handled purely within
option parsing, no need for a state flag.
2017-12-23 14:14:57 +01:00
294 changed files with 57157 additions and 12801 deletions
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.