mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-28 04:00:06 +08:00
tccgen: arm/i386: save_reg_upstack
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)
This commit is contained in:
parent
1c4cf18556
commit
b691585785
@ -1177,7 +1177,8 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
/* second pass to restore registers that were saved on stack by accident */
|
||||
/* second pass to restore registers that were saved on stack by accident.
|
||||
Maybe redundant after the "lvalue_save" patch in tccgen.c:gv() */
|
||||
if (++pass < 2)
|
||||
goto again;
|
||||
|
||||
|
@ -848,6 +848,8 @@ ST_FUNC void gen_opi(int op)
|
||||
fr = vtop[0].r;
|
||||
vtop--;
|
||||
save_reg(TREG_EDX);
|
||||
/* save EAX too if used otherwise */
|
||||
save_reg_upstack(TREG_EAX, 1);
|
||||
if (op == TOK_UMULL) {
|
||||
o(0xf7); /* mul fr */
|
||||
o(0xe0 + fr);
|
||||
|
1
tcc.h
1
tcc.h
@ -1295,6 +1295,7 @@ ST_FUNC void lexpand_nr(void);
|
||||
#endif
|
||||
ST_FUNC void vpushv(SValue *v);
|
||||
ST_FUNC void save_reg(int r);
|
||||
ST_FUNC void save_reg_upstack(int r, int n);
|
||||
ST_FUNC int get_reg(int rc);
|
||||
ST_FUNC void save_regs(int n);
|
||||
ST_FUNC void gaddrof(void);
|
||||
|
44
tccgen.c
44
tccgen.c
@ -533,17 +533,35 @@ static void vdup(void)
|
||||
vpushv(vtop);
|
||||
}
|
||||
|
||||
/* save registers up to (vtop - n) stack entry */
|
||||
ST_FUNC void save_regs(int n)
|
||||
{
|
||||
SValue *p, *p1;
|
||||
for(p = vstack, p1 = vtop - n; p <= p1; p++)
|
||||
save_reg(p->r);
|
||||
}
|
||||
|
||||
/* save r to the memory stack, and mark it as being free */
|
||||
ST_FUNC void save_reg(int r)
|
||||
{
|
||||
save_reg_upstack(r, 0);
|
||||
}
|
||||
|
||||
/* save r to the memory stack, and mark it as being free,
|
||||
if seen up to (vtop - n) stack entry */
|
||||
ST_FUNC void save_reg_upstack(int r, int n)
|
||||
{
|
||||
int l, saved, size, align;
|
||||
SValue *p, sv;
|
||||
SValue *p, *p1, sv;
|
||||
CType *type;
|
||||
|
||||
if ((r &= VT_VALMASK) >= VT_CONST)
|
||||
return;
|
||||
|
||||
/* modify all stack values */
|
||||
saved = 0;
|
||||
l = 0;
|
||||
for(p=vstack;p<=vtop;p++) {
|
||||
for(p = vstack, p1 = vtop - n; p <= p1; p++) {
|
||||
if ((p->r & VT_VALMASK) == r ||
|
||||
((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
|
||||
/* must save value on stack if not already done */
|
||||
@ -659,20 +677,6 @@ ST_FUNC int get_reg(int rc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* save registers up to (vtop - n) stack entry */
|
||||
ST_FUNC void save_regs(int n)
|
||||
{
|
||||
int r;
|
||||
SValue *p, *p1;
|
||||
p1 = vtop - n;
|
||||
for(p = vstack;p <= p1; p++) {
|
||||
r = p->r & VT_VALMASK;
|
||||
if (r < VT_CONST) {
|
||||
save_reg(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* move register 's' (of type 't') to 'r', and flush previous value of r to memory
|
||||
if needed */
|
||||
static void move_reg(int r, int s, int t)
|
||||
@ -859,13 +863,17 @@ ST_FUNC int gv(int rc)
|
||||
vpushi(ll >> 32); /* second word */
|
||||
} else
|
||||
#endif
|
||||
if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
|
||||
(vtop->r & VT_LVAL)) {
|
||||
if (vtop->r & VT_LVAL) {
|
||||
/* We do not want to modifier the long long
|
||||
pointer here, so the safest (and less
|
||||
efficient) is to save all the other registers
|
||||
in the stack. XXX: totally inefficient. */
|
||||
#if 0
|
||||
save_regs(1);
|
||||
#else
|
||||
/* lvalue_save: save only if used further down the stack */
|
||||
save_reg_upstack(vtop->r, 1);
|
||||
#endif
|
||||
/* load from memory */
|
||||
vtop->type.t = load_type;
|
||||
load(r, vtop);
|
||||
|
@ -1953,6 +1953,11 @@ long long int value(struct S *v)
|
||||
return ((long long int)v->item);
|
||||
}
|
||||
|
||||
long long llfunc2(long long x, long long y, int z)
|
||||
{
|
||||
return x * y * z;
|
||||
}
|
||||
|
||||
void longlong_test(void)
|
||||
{
|
||||
long long a, b, c;
|
||||
@ -1999,15 +2004,17 @@ void longlong_test(void)
|
||||
}
|
||||
lloptest(0x80000000, 0);
|
||||
|
||||
/* another long long spill test */
|
||||
{
|
||||
long long *p, v;
|
||||
long long *p, v, **pp;
|
||||
v = 1;
|
||||
p = &v;
|
||||
p[0]++;
|
||||
printf("%lld\n", *p);
|
||||
}
|
||||
printf("another long long spill test : %lld\n", *p);
|
||||
pp = &p;
|
||||
|
||||
v = llfunc2(**pp, **pp, ia);
|
||||
printf("a long long function (arm-)reg-args test : %lld\n", v);
|
||||
}
|
||||
a = 68719476720LL;
|
||||
b = 4294967295LL;
|
||||
printf("%d %d %d %d\n", a > b, a < b, a >= b, a <= b);
|
||||
|
Loading…
Reference in New Issue
Block a user