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.
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.
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)
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.
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.
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.
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.
* 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.
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)
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)
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.
- 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 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.
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.