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.