diff options
| author | grischka <grischka> | 2016-10-04 17:36:51 +0200 |
|---|---|---|
| committer | grischka <grischka> | 2016-10-04 17:36:51 +0200 |
| commit | b691585785086024549cfb9ac65f3397263965aa (patch) | |
| tree | e7b13cf60f7c967c7230b4175d2e81eed950d7ac /tccgen.c | |
| parent | 1c4cf1855632d712a67f3cc28e43469f8b5f936a (diff) | |
| download | tinycc-b691585785086024549cfb9ac65f3397263965aa.tar.gz tinycc-b691585785086024549cfb9ac65f3397263965aa.tar.bz2 | |
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)
Diffstat (limited to 'tccgen.c')
| -rw-r--r-- | tccgen.c | 44 |
1 files changed, 26 insertions, 18 deletions
@@ -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); |
