aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorjiang <30155751@qq.com>2014-05-01 01:48:50 +0800
committerjiang <30155751@qq.com>2014-05-01 01:48:50 +0800
commit9e3713facd9d857201326ac2038ab6a8fb64a5fc (patch)
treed5b8198ca19372f827b3ca54b19a5ae3b6df3bcc /tccgen.c
parent2b2e7f85d7119677f0ffdd4c1bde5d3095dead4e (diff)
downloadtinycc-9e3713facd9d857201326ac2038ab6a8fb64a5fc.tar.gz
tinycc-9e3713facd9d857201326ac2038ab6a8fb64a5fc.tar.bz2
Expansion code again for x86_64-gen
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c186
1 files changed, 73 insertions, 113 deletions
diff --git a/tccgen.c b/tccgen.c
index 33240cf..daf5f48 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -28,7 +28,7 @@
rsym: return symbol
anon_sym: anonymous symbol index
*/
-ST_DATA int rsym, anon_sym, ind, loc;
+ST_DATA int rsym, anon_sym, ind, loc, ex_rc;
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
ST_DATA Section *cur_text_section; /* current section where function code is generated */
@@ -525,41 +525,6 @@ static void vdup(void)
vpushv(vtop);
}
-static int align_size(int size)
-{
-#ifdef TCC_TARGET_X86_64
- if(size > 4)
- return 8;
- else
-#endif
- if(size > 2)
- return 4;
- else if(size > 1)
- return 2;
- else
- return 1;
-}
-
-int loc_stack(int size, int is_sub){
- int l, align;
- align = align_size(size);
- size = (size + align - 1) & - align;
- if(is_sub){
- pop_stack -= size;
- if(pop_stack >= 0)
- l = loc + pop_stack;
- else{
- loc += pop_stack;
- l = loc &= -align;
- pop_stack = 0;
- }
- }else{
- pop_stack += size;
- l = loc + pop_stack;
- }
- return l;
-}
-
/* save r to the memory stack, and mark it as being free */
ST_FUNC void save_reg(int r)
{
@@ -762,25 +727,28 @@ static void gbound(void)
register value (such as structures). */
ST_FUNC int gv(int rc)
{
- int r, bit_pos, bit_size, size, align, i;
+ int r, bit_pos, bit_size, size, align, i, ft, sbt;
int rc2;
+ ft = vtop->type.t;
+ sbt = ft & VT_BTYPE;
/* NOTE: get_reg can modify vstack[] */
- if (vtop->type.t & VT_BITFIELD) {
+ if (ft & VT_BITFIELD) {
CType type;
- int bits = 32;
- bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
- bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+ int bits;
+ bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
+ bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
/* remove bit field info to avoid loops */
- vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
+ ft = vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
/* cast to int to propagate signedness in following ops */
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
+ if (sbt == VT_LLONG) {
type.t = VT_LLONG;
bits = 64;
- } else
+ } else{
type.t = VT_INT;
- if((vtop->type.t & VT_UNSIGNED) ||
- (vtop->type.t & VT_BTYPE) == VT_BOOL)
+ bits = 32;
+ }
+ if((ft & VT_UNSIGNED) || sbt == VT_BOOL)
type.t |= VT_UNSIGNED;
gen_cast(&type);
/* generate shifts */
@@ -837,41 +805,39 @@ ST_FUNC int gv(int rc)
gbound();
#endif
- r = vtop->r & VT_VALMASK;
- rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
- if (rc == RC_IRET)
- rc2 = RC_LRET;
-#ifdef TCC_TARGET_X86_64
- else if (rc == RC_FRET)
- rc2 = RC_QRET;
-#endif
+ r = vtop->r & VT_VALMASK;
+ if((rc & ~RC_MASK) && (rc != RC_ST0))
+ rc2 = ex_rc;
+ else
+ rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
/* need to reload if:
- constant
- lvalue (need to dereference pointer)
- already a register, but not in the right class */
- if (r >= VT_CONST
- || (vtop->r & VT_LVAL)
- || !(reg_classes[r] & rc)
+ if (r >= VT_CONST || (vtop->r & VT_LVAL) || !(reg_classes[r] & rc)
#ifdef TCC_TARGET_X86_64
- || ((vtop->type.t & VT_BTYPE) == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
- || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
+ || (sbt == VT_QLONG && !(reg_classes[vtop->r2] & rc2))
+ || (sbt == VT_QFLOAT && !(reg_classes[vtop->r2] & rc2))
#else
- || ((vtop->type.t & VT_BTYPE) == VT_LLONG && !(reg_classes[vtop->r2] & rc2))
+ || (sbt == VT_LLONG && !(reg_classes[vtop->r2] & rc2))
#endif
- )
+ || vtop->c.i)
{
r = get_reg(rc);
#ifdef TCC_TARGET_X86_64
- if (((vtop->type.t & VT_BTYPE) == VT_QLONG) || ((vtop->type.t & VT_BTYPE) == VT_QFLOAT)) {
- int addr_type = VT_LLONG, load_size = 8, load_type = ((vtop->type.t & VT_BTYPE) == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
+ if ((sbt == VT_QLONG) || (sbt == VT_QFLOAT))
#else
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
- int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
+ if (sbt == VT_LLONG)
+#endif
+ {
+#ifdef TCC_TARGET_X86_64
+ int load_size = 8, load_type = (sbt == VT_QLONG) ? VT_LLONG : VT_DOUBLE;
+#else
+ int load_size = 4, load_type = VT_INT;
unsigned long long ll;
#endif
- int r2, original_type;
- original_type = vtop->type.t;
+ int r2;
/* two register type load : expand to two words
temporarily */
#ifndef TCC_TARGET_X86_64
@@ -884,20 +850,19 @@ 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)) {
+ /* XXX: test to VT_CONST incorrect ? */
+ if (r >= VT_CONST || (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. */
- save_regs(1);
+ in the regs. use VT_TMP XXX: totally inefficient. */
/* load from memory */
vtop->type.t = load_type;
load(r, vtop);
vdup();
- vtop[-1].r = r; /* save register value */
+ vtop[-1].r = r | VT_TMP; /* lock register value */
/* increment pointer to get second word */
- vtop->type.t = addr_type;
+ vtop->type = char_pointer_type;
gaddrof();
vpushi(load_size);
gen_op('+');
@@ -907,23 +872,23 @@ ST_FUNC int gv(int rc)
/* move registers */
load(r, vtop);
vdup();
- vtop[-1].r = r; /* save register value */
+ vtop[-1].r = r | VT_TMP; /* lock register value */
vtop->r = vtop[-1].r2;
}
/* Allocate second register. Here we rely on the fact that
get_reg() tries first to free r2 of an SValue. */
r2 = get_reg(rc2);
load(r2, vtop);
- vpop();
+ vtop--;
/* write second register */
vtop->r2 = r2;
- vtop->type.t = original_type;
- } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
- int t1, t;
+ vtop->r &= ~VT_TMP;
+ vtop->type.t = ft;
+ } else if ((vtop->r & VT_LVAL) && !is_float(ft)) {
+ int t;
/* lvalue of scalar type : need to use lvalue type
because of possible cast */
- t = vtop->type.t;
- t1 = t;
+ t = ft;
/* compute memory access type */
if (vtop->r & VT_REF)
#ifdef TCC_TARGET_X86_64
@@ -940,7 +905,7 @@ ST_FUNC int gv(int rc)
vtop->type.t = t;
load(r, vtop);
/* restore wanted type */
- vtop->type.t = t1;
+ vtop->type.t = ft;
} else {
/* one register type load */
load(r, vtop);
@@ -994,6 +959,7 @@ static int rc_fret(int t)
return RC_ST0;
}
#endif
+ ex_rc = RC_QRET;
return RC_FRET;
}
@@ -2116,31 +2082,30 @@ ST_FUNC int type_size(CType *type, int *a)
{
Sym *s;
int bt;
+ size_t size;
bt = type->t & VT_BTYPE;
if (bt == VT_STRUCT) {
+ assert(!(type->t & VT_VLS));
/* struct/union */
s = type->ref;
*a = s->r;
- return s->c;
+ size = s->c;
} else if (bt == VT_PTR) {
if (type->t & VT_ARRAY) {
int ts;
-
s = type->ref;
ts = type_size(&s->type, a);
-
if (ts < 0 && s->c < 0)
ts = -ts;
-
- return ts * s->c;
+ size = (size_t)ts * s->c;
} else {
*a = PTR_SIZE;
- return PTR_SIZE;
+ size = PTR_SIZE;
}
} else if (bt == VT_LDOUBLE) {
*a = LDOUBLE_ALIGN;
- return LDOUBLE_SIZE;
+ size = LDOUBLE_SIZE;
} else if (bt == VT_DOUBLE || bt == VT_LLONG) {
#ifdef TCC_TARGET_I386
#ifdef TCC_TARGET_PE
@@ -2157,21 +2122,23 @@ ST_FUNC int type_size(CType *type, int *a)
#else
*a = 8;
#endif
- return 8;
+ size = 8;
} else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
*a = 4;
- return 4;
+ size = 4;
} else if (bt == VT_SHORT) {
*a = 2;
- return 2;
- } else if (bt == VT_QLONG || bt == VT_QFLOAT) {
+ size = 2;
+ } else if (bt == VT_QLONG || bt == VT_QFLOAT) {
*a = 8;
- return 16;
+ size = 16;
} else {
/* char, void, function, _Bool */
*a = 1;
- return 1;
+ size = 1;
}
+ assert(size == (int)size);
+ return (int)size;
}
/* push type size as known at runtime time on top of value stack. Put
@@ -2600,24 +2567,19 @@ ST_FUNC void vstore(void)
bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
/* remove bit field info to avoid loops */
vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
-
/* duplicate source into other register */
- if((ft & VT_BTYPE) == VT_BOOL) {
+ if(dbt == VT_BOOL) {
gen_cast(&vtop[-1].type);
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
}
- /* duplicate destination */
- vdup();
- vtop[-1] = vtop[-2];
-
/* duplicate destination */
vdup();
vtop[-1] = vtop[-2];
/* mask and shift source */
- if((ft & VT_BTYPE) != VT_BOOL) {
- if((ft & VT_BTYPE) == VT_LLONG) {
+ if(dbt != VT_BOOL) {
+ if(dbt == VT_LLONG) {
vpushll((1ULL << bit_size) - 1ULL);
} else {
vpushi((1 << bit_size) - 1);
@@ -2628,7 +2590,7 @@ ST_FUNC void vstore(void)
gen_op(TOK_SHL);
/* load destination, mask and or with source */
vswap();
- if((ft & VT_BTYPE) == VT_LLONG) {
+ if(dbt == VT_LLONG) {
vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
} else {
vpushi(~(((1 << bit_size) - 1) << bit_pos));
@@ -2637,10 +2599,6 @@ ST_FUNC void vstore(void)
gen_op('|');
/* store result */
vstore();
-
- /* pop off shifted source from "duplicate source..." above */
- vpop();
-
} else {
#ifdef CONFIG_TCC_BCHECK
/* bound check case */
@@ -4772,7 +4730,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
vstore();
} else {
/* returning structure packed into registers */
- int r, size, addr, align;
+ int rc, size, addr, align;
size = type_size(&func_vt,&align);
if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1)))
&& (align & (ret_align-1))) {
@@ -4786,18 +4744,20 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
}
vtop->type = ret_type;
if (is_float(ret_type.t))
- r = rc_fret(ret_type.t);
- else
- r = RC_IRET;
+ rc = rc_fret(ret_type.t);
+ else{
+ rc = RC_IRET;
+ ex_rc = RC_LRET;
+ }
for (;;) {
- gv(r);
+ gv(rc);
if (--ret_nregs == 0)
break;
/* We assume that when a structure is returned in multiple
registers, their classes are consecutive values of the
suite s(n) = 2^n */
- r <<= 1;
+ rc <<= 1;
/* XXX: compatible with arm only: ret_align == register_size */
vtop->c.i += ret_align;
vtop->r = VT_LOCAL | VT_LVAL;