tccgen.c:gv() when loading long long from lvalue, before
was saving all registers which caused problems in the arm
function call register parameter preparation, as with
void foo(long long y, int x);
int main(void)
{
unsigned int *xx[1], x;
unsigned long long *yy[1], y;
foo(**yy, **xx);
return 0;
}
Now only the modified register is saved if necessary,
as in this case where it is used to store the result
of the post-inc:
long long *p, v, **pp;
v = 1;
p = &v;
p[0]++;
printf("another long long spill test : %lld\n", *p);
i386-gen.c :
- found a similar problem with TOK_UMULL caused by the
vstack juggle in tccgen:gen_opl()
(bug seen only when using EBX as 4th register)
"make test" crashes without that "save_regs()".
This partially reverts
commit 49d3118621.
Found another solution: In a 2nd pass Just look if
any of the argument registers has been saved again,
and restore if so.
* Documentation is now in "docs".
* Source code is now in "src".
* Misc. fixes here and there so that everything still works.
I think I got everything in this commit, but I only tested this
on Linux (Make) and Windows (CMake), so I might've messed
something up on other platforms...
Jsut for testing. It works for me (don't break anything)
Small fixes for x86_64-gen.c in "tccpp: fix issues, add tests"
are dropped in flavor of this patch.
Pip Cet:
Okay, here's a first patch that fixes the problem (but I've found
another bug, yet unfixed, in the process), though it's not
particularly pretty code (I tried hard to keep the changes to the
minimum necessary). If we decide to actually get rid of VT_QLONG and
VT_QFLOAT (please, can we?), there are some further simplifications in
tccgen.c that might offset some of the cost of this patch.
The idea is that an integer is no longer enough to describe how an
argument is stored in registers. There are a number of possibilities
(none, integer register, two integer registers, float register, two
float registers, integer register plus float register, float register
plus integer register), and instead of enumerating them I've
introduced a RegArgs type that stores the offsets for each of our
registers (for the other architectures, it's simply an int specifying
the number of registers). If someone strongly prefers an enum, we
could do that instead, but I believe this is a place where keeping
things general is worth it, because this way it should be doable to
add SSE or AVX support.
There is one line in the patch that looks suspicious:
} else {
addr = (addr + align - 1) & -align;
param_addr = addr;
addr += size;
- sse_param_index += reg_count;
}
break;
However, this actually fixes one half of a bug we have when calling a
function with eight double arguments "interrupted" by a two-double
structure after the seventh double argument:
f(double,double,double,double,double,double,double,struct { double
x,y; },double);
In this case, the last argument should be passed in %xmm7. This patch
fixes the problem in gfunc_prolog, but not the corresponding problem
in gfunc_call, which I'll try tackling next.
The common code to move a returned structure packed into
registers into memory on the caller side didn't take the
register size into account when allocating local storage,
so sometimes that lead to stack overwrites (e.g. in 73_arm64.c),
on x86_64. This fixes it by generally making gfunc_sret also return
the register size.
arm-gen.c: In function `gfunc_call':
arm-gen.c:1202: warning: unused variable `variadic'
arm-gen.c: In function `gfunc_prolog':
arm-gen.c:1258: warning: unused variable `avregs'
arm-gen.c:1340: warning: label `from_stack' defined but not used
arm-gen.c:222: warning: 'default_elfinterp' defined but not used
Author: Thomas Preud'homme <robotux@celest.fr>
Date: Tue Dec 31 23:51:20 2013 +0800
Move logic for if (int value) to tccgen.c
Move the logic to do a test of an integer value (ex if (0)) out of
arch-specific code to tccgen.c to avoid code duplication. This also
fixes test of long long value which was only testing the bottom half of
such values on 32 bits architectures.
I don't understand why if () in gtst(i) was removed.
This patch allows to compile a linux kernel v.2.4.26
W/o this patch a tcc simply crashes.
TinyCC miscompiled
void g(int,...);
void f(void)
{
char b[4000];
g(1, 2, 3, 4, b);
}
in two ways:
1. It didn't align the stack to 8 bytes before the call
2. It added sizeof(b) to the stack pointer after the call
For ARM target, tcc uses the soft float ABI when not asked to use hard
float ABI. This means machine without a VFP co-processor generate code
that they cannot run. This commit add a warning for such cases.
This improves commit 5cbe03b9c4 by
avoiding a double transfer when the default float ABI is already softfp.
It's also more clean by expliciting that the ABI is simply changed for
runtime ABI functions.
EABI functions to convert an int to a double register take the integer
value in core registers and also give the result in core registers.
It is thus necessary to move the result back to VFP register after the
function call. This only affected integer to double conversion because
integer to float conversion used a VFP instruction to do the conversion
and this obviously left the result in VFP register. Note that the
behavior is left untouched for !EABI as the correct behavior in this
case is unknown to the author of this patch.
The procedure calling standard for ARM architecture mandate the use of
the base standard for variadic function. Therefore, hgen float aggregate
must be returned via stack when greater than 4 bytes and via core
registers else in case of variadic function.
This patch improve gfunc_sret() to take into account whether the
function is variadic or not and make use of gfunc_sret() return value to
determine whether to pass a structure via stack in gfunc_prolog(). It
also take advantage of knowing if a function is variadic or not move
float result value from VFP register to core register in gfunc_epilog().
Move the logic to do a test of an integer value (ex if (0)) out of
arch-specific code to tccgen.c to avoid code duplication. This also
fixes test of long long value which was only testing the bottom half of
such values on 32 bits architectures.
Add infrastructure to support special calling convention for runtime ABI
function no matter what is the current calling convention. This involve
2 changes:
- behave as per base standard in gfunc_call
- move result back in VFP register in gen_cvt_itof1
Fix the address on stack where a structure is copied when it is a
parameter of a function call. This address must be computed from the
stack pointer and a possible padding offset.
On ARM with hardfloat calling convention, structure containing 4 fields
or less of the same float type are returned via float registers. This
means that a structure can be returned in up to 4 double registers in a
structure is composed of 4 doubles. This commit adds support for return
of structures in several registers.
Fix in gfunc_prolog for ARM the counting of the highest numbered VFP
float register used for parameter passing, rounded to 2. It can be
computed from the range of VFP float register with the highest range
start and adding the number of VFP float register occupied. This ensure
that parameter of type struct that spans over more than 2 float
registers are correctly taken into account.
Prior to this commit, params could use some registers that do not appear
in the value stack. Therefore when generating function call, one of such
register could be reused, leading to wrong parameter content. This
happens when a structure is passed via core register, as only the first
register would appear in the value stack.
* Correctly align stack in case of structure split between core
registers and stack
* Correctly reclaim stack space after function call in the case where
the stack needed padding to be aligned at function call.
Wrap runtime_main as per its declaration in tcc.h.
Fix preprocessor check for TCC_ARM_EABI macro definition.
Signed-off-by: Joseph Poirier <jdpoirier@gmail.com>
Allocation of struct in core and/or VFP registers on ARM is made by
manipulating the value stack to create 3 distinct zones: parameters
allocated on stack, parameters of type struct allocated in core
registers and parameters of type struct allocated in VFP registers.
Parameters of primitive type can be in any zone. This commit change the
order of the zones from stack, VFP, core to stack, core, VFP (from
highest addresses to lowest ones) in order to correctly deal the
situation when structures are allocated both in core and VFP registers.
VLA storage is now freed when it goes out of scope. This makes it
possible to use a VLA inside a loop without consuming an unlimited
amount of memory.
Combining VLAs with alloca() should work as in GCC - when a VLA is
freed, memory allocated by alloca() after the VLA was created is also
freed. There are some exceptions to this rule when using goto: if a VLA
is in scope at the goto, jumping to a label will reset the stack pointer
to where it was immediately after the last VLA was created prior to the
label, or to what it was before the first VLA was created if the label
is outside the scope of any VLA. This means that in some cases combining
alloca() and VLAs will free alloca() memory where GCC would not.
abitest now passes; however test1-3 fail in init_test. All other tests
pass. I need to re-test Win32 and Linux-x86.
I've added a dummy implementation of gfunc_sret to c67-gen.c so it
should now compile, and I think it should behave as before I created
gfunc_sret.
I expect that Linux-x86 is probably fine. All other architectures
except ARM are definitely broken since I haven't yet implemented
gfunc_sret for these, although replicating the current behaviour
should be straightforward.
Should fix some warnings wrt. access out of array bounds.
tccelf.c: fix "static function unused" warning
x86_64-gen.c: fix "ctype.ref uninitialzed" warning and cleanup
tcc-win32.txt: remove obsolete limitation notes.
Fix initialization of args_size before doing register allocation.
When adding hardfloat calling convention the initialization stopped
being performed when !defined (TCC_ARM_EABI).