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).
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 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
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)
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)
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)
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.
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.
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.
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)
(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
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)
- 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
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.
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).
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
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(-)
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)
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.
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
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.
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
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>
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; }); }
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
- 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.