Fix va_arg bug, Fix type conversion bug, an increase of loc_stack () function is used to manage loc
This commit is contained in:
parent
9ff288648b
commit
5af0ea7fb8
5 changed files with 236 additions and 154 deletions
110
lib/libtcc1.c
110
lib/libtcc1.c
|
@ -530,74 +530,77 @@ long double __floatundixf(unsigned long long a)
|
||||||
|
|
||||||
unsigned long long __fixunssfdi (float a1)
|
unsigned long long __fixunssfdi (float a1)
|
||||||
{
|
{
|
||||||
register union float_long fl1;
|
register union float_long fl1;
|
||||||
register int exp;
|
register int exp;
|
||||||
register unsigned long l;
|
register unsigned long l;
|
||||||
|
int s;
|
||||||
|
fl1.f = a1;
|
||||||
|
|
||||||
fl1.f = a1;
|
if (fl1.l == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (fl1.l == 0)
|
exp = EXP (fl1.l) - EXCESS - 24;
|
||||||
return (0);
|
|
||||||
|
|
||||||
exp = EXP (fl1.l) - EXCESS - 24;
|
l = MANT(fl1.l);
|
||||||
|
s = SIGN(fl1.l)? -1: 1;
|
||||||
l = MANT(fl1.l);
|
if (exp >= 64)
|
||||||
if (exp >= 41)
|
return (unsigned long long)-1;
|
||||||
return (unsigned long long)-1;
|
else if (exp >= 0)
|
||||||
else if (exp >= 0)
|
return ((unsigned long long)l << exp)*s;
|
||||||
return (unsigned long long)l << exp;
|
else if (exp >= -23)
|
||||||
else if (exp >= -23)
|
return (l >> -exp)*s;
|
||||||
return l >> -exp;
|
else
|
||||||
else
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long __fixunsdfdi (double a1)
|
unsigned long long __fixunsdfdi (double a1)
|
||||||
{
|
{
|
||||||
register union double_long dl1;
|
register union double_long dl1;
|
||||||
register int exp;
|
register int exp;
|
||||||
register unsigned long long l;
|
register unsigned long long l;
|
||||||
|
int s;
|
||||||
|
dl1.d = a1;
|
||||||
|
|
||||||
dl1.d = a1;
|
if (dl1.ll == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
if (dl1.ll == 0)
|
exp = EXPD (dl1) - EXCESSD - 53;
|
||||||
return (0);
|
|
||||||
|
|
||||||
exp = EXPD (dl1) - EXCESSD - 53;
|
l = MANTD_LL(dl1);
|
||||||
|
s = SIGND(dl1)? -1: 1;
|
||||||
l = MANTD_LL(dl1);
|
if (exp >= 64)
|
||||||
|
return (unsigned long long)-1;
|
||||||
if (exp >= 12)
|
else if (exp >= 0)
|
||||||
return (unsigned long long)-1;
|
return (l << exp)*s;
|
||||||
else if (exp >= 0)
|
else if (exp >= -52)
|
||||||
return l << exp;
|
return (l >> -exp)*s;
|
||||||
else if (exp >= -52)
|
else
|
||||||
return l >> -exp;
|
return 0;
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long __fixunsxfdi (long double a1)
|
unsigned long long __fixunsxfdi (long double a1)
|
||||||
{
|
{
|
||||||
register union ldouble_long dl1;
|
register union ldouble_long dl1;
|
||||||
register int exp;
|
register int exp;
|
||||||
register unsigned long long l;
|
register unsigned long long l;
|
||||||
|
int s;
|
||||||
|
dl1.ld = a1;
|
||||||
|
|
||||||
dl1.ld = a1;
|
if (dl1.l.lower == 0 && dl1.l.upper == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
if (dl1.l.lower == 0 && dl1.l.upper == 0)
|
exp = EXPLD (dl1) - EXCESSLD - 64;
|
||||||
return (0);
|
s = SIGNLD(dl1)? -1: 1;
|
||||||
|
l = dl1.l.lower;
|
||||||
|
|
||||||
exp = EXPLD (dl1) - EXCESSLD - 64;
|
if (exp >= 64)
|
||||||
|
return (unsigned long long)-1;
|
||||||
l = dl1.l.lower;
|
else if (exp >= 0)
|
||||||
|
return ((unsigned long long)l << exp)*s;
|
||||||
if (exp > 0)
|
else if (exp >= -64)
|
||||||
return (unsigned long long)-1;
|
return (l >> -exp)*s;
|
||||||
else if (exp >= -63)
|
else
|
||||||
return l >> -exp;
|
return 0;
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long long __fixsfdi (float a1)
|
long long __fixsfdi (float a1)
|
||||||
|
@ -637,7 +640,7 @@ extern void abort(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum __va_arg_type {
|
enum __va_arg_type {
|
||||||
__va_gen_reg, __va_float_reg, __va_stack
|
__va_gen_reg, __va_float_reg, __va_ld_reg, __va_stack
|
||||||
};
|
};
|
||||||
|
|
||||||
//This should be in sync with the declaration on our include/stdarg.h
|
//This should be in sync with the declaration on our include/stdarg.h
|
||||||
|
@ -688,10 +691,11 @@ void *__va_arg(__va_list_struct *ap,
|
||||||
size = 8;
|
size = 8;
|
||||||
goto use_overflow_area;
|
goto use_overflow_area;
|
||||||
|
|
||||||
|
case __va_ld_reg:
|
||||||
|
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
|
||||||
case __va_stack:
|
case __va_stack:
|
||||||
use_overflow_area:
|
use_overflow_area:
|
||||||
ap->overflow_arg_area += size;
|
ap->overflow_arg_area += size;
|
||||||
ap->overflow_arg_area = (char*)((intptr_t)(ap->overflow_arg_area + align - 1) & -(intptr_t)align);
|
|
||||||
return ap->overflow_arg_area - size;
|
return ap->overflow_arg_area - size;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
1
tcc.h
1
tcc.h
|
@ -1194,6 +1194,7 @@ ST_DATA int func_var; /* true if current function is variadic */
|
||||||
ST_DATA int func_vc;
|
ST_DATA int func_vc;
|
||||||
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
||||||
ST_DATA char *funcname;
|
ST_DATA char *funcname;
|
||||||
|
ST_DATA int pop_stack;
|
||||||
|
|
||||||
ST_INLN int is_float(int t);
|
ST_INLN int is_float(int t);
|
||||||
ST_FUNC int ieee_finite(double d);
|
ST_FUNC int ieee_finite(double d);
|
||||||
|
|
199
tccgen.c
199
tccgen.c
|
@ -70,6 +70,7 @@ ST_DATA int func_var; /* true if current function is variadic (used by return in
|
||||||
ST_DATA int func_vc;
|
ST_DATA int func_vc;
|
||||||
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */
|
||||||
ST_DATA char *funcname;
|
ST_DATA char *funcname;
|
||||||
|
ST_DATA int pop_stack;
|
||||||
|
|
||||||
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
|
ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
|
||||||
|
|
||||||
|
@ -524,6 +525,41 @@ static void vdup(void)
|
||||||
vpushv(vtop);
|
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 */
|
/* save r to the memory stack, and mark it as being free */
|
||||||
ST_FUNC void save_reg(int r)
|
ST_FUNC void save_reg(int r)
|
||||||
{
|
{
|
||||||
|
@ -924,13 +960,10 @@ ST_FUNC int gv(int rc)
|
||||||
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
|
/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
|
||||||
ST_FUNC void gv2(int rc1, int rc2)
|
ST_FUNC void gv2(int rc1, int rc2)
|
||||||
{
|
{
|
||||||
int v;
|
|
||||||
|
|
||||||
/* generate more generic register first. But VT_JMP or VT_CMP
|
/* generate more generic register first. But VT_JMP or VT_CMP
|
||||||
values must be generated first in all cases to avoid possible
|
values must be generated first in all cases to avoid possible
|
||||||
reload errors */
|
reload errors */
|
||||||
v = vtop[0].r & VT_VALMASK;
|
if (rc1 <= rc2) {
|
||||||
if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
|
|
||||||
vswap();
|
vswap();
|
||||||
gv(rc1);
|
gv(rc1);
|
||||||
vswap();
|
vswap();
|
||||||
|
@ -1018,6 +1051,7 @@ ST_FUNC void lexpand_nr(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TCC_TARGET_X86_64
|
||||||
/* build a long long from two ints */
|
/* build a long long from two ints */
|
||||||
static void lbuild(int t)
|
static void lbuild(int t)
|
||||||
{
|
{
|
||||||
|
@ -1026,6 +1060,7 @@ static void lbuild(int t)
|
||||||
vtop[-1].type.t = t;
|
vtop[-1].type.t = t;
|
||||||
vpop();
|
vpop();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* rotate n first stack elements to the bottom
|
/* rotate n first stack elements to the bottom
|
||||||
I1 ... In -> I2 ... In I1 [top is right]
|
I1 ... In -> I2 ... In I1 [top is right]
|
||||||
|
@ -1087,8 +1122,8 @@ static void gv_dup(void)
|
||||||
{
|
{
|
||||||
int rc, t, r, r1;
|
int rc, t, r, r1;
|
||||||
SValue sv;
|
SValue sv;
|
||||||
|
|
||||||
t = vtop->type.t;
|
t = vtop->type.t;
|
||||||
|
#ifndef TCC_TARGET_X86_64
|
||||||
if ((t & VT_BTYPE) == VT_LLONG) {
|
if ((t & VT_BTYPE) == VT_LLONG) {
|
||||||
lexpand();
|
lexpand();
|
||||||
gv_dup();
|
gv_dup();
|
||||||
|
@ -1098,15 +1133,14 @@ static void gv_dup(void)
|
||||||
vrotb(4);
|
vrotb(4);
|
||||||
/* stack: H L L1 H1 */
|
/* stack: H L L1 H1 */
|
||||||
lbuild(t);
|
lbuild(t);
|
||||||
vrotb(3);
|
vrott(3);
|
||||||
vrotb(3);
|
|
||||||
vswap();
|
vswap();
|
||||||
lbuild(t);
|
lbuild(t);
|
||||||
vswap();
|
vswap();
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
/* duplicate value */
|
/* duplicate value */
|
||||||
rc = RC_INT;
|
|
||||||
sv.type.t = VT_INT;
|
|
||||||
if (is_float(t)) {
|
if (is_float(t)) {
|
||||||
rc = RC_FLOAT;
|
rc = RC_FLOAT;
|
||||||
#ifdef TCC_TARGET_X86_64
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
@ -1114,8 +1148,9 @@ static void gv_dup(void)
|
||||||
rc = RC_ST0;
|
rc = RC_ST0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sv.type.t = t;
|
}else
|
||||||
}
|
rc = RC_INT;
|
||||||
|
sv.type.t = t;
|
||||||
r = gv(rc);
|
r = gv(rc);
|
||||||
r1 = get_reg(rc);
|
r1 = get_reg(rc);
|
||||||
sv.r = r;
|
sv.r = r;
|
||||||
|
@ -1127,7 +1162,6 @@ static void gv_dup(void)
|
||||||
vtop->r = r1;
|
vtop->r = r1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TCC_TARGET_X86_64
|
#ifndef TCC_TARGET_X86_64
|
||||||
/* generate CPU independent (unsigned) long long operations */
|
/* generate CPU independent (unsigned) long long operations */
|
||||||
static void gen_opl(int op)
|
static void gen_opl(int op)
|
||||||
|
@ -2441,17 +2475,78 @@ static void gen_assign_cast(CType *dt)
|
||||||
gen_cast(dt);
|
gen_cast(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vstore_im(){
|
||||||
|
int rc, ft, sbt, dbt, t, r;
|
||||||
|
ft = vtop[-1].type.t;
|
||||||
|
sbt = vtop->type.t & VT_BTYPE;
|
||||||
|
dbt = ft & VT_BTYPE;
|
||||||
|
if (is_float(ft)) {
|
||||||
|
rc = RC_FLOAT;
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
if (dbt == VT_LDOUBLE) {
|
||||||
|
rc = RC_ST0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}else
|
||||||
|
rc = RC_INT;
|
||||||
|
r = gv(rc); /* generate value */
|
||||||
|
/* if lvalue was saved on stack, must read it */
|
||||||
|
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
|
||||||
|
SValue sv;
|
||||||
|
t = get_reg(RC_INT);
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
sv.type.t = VT_PTR;
|
||||||
|
#else
|
||||||
|
sv.type.t = VT_INT;
|
||||||
|
#endif
|
||||||
|
sv.r = VT_LOCAL | VT_LVAL;
|
||||||
|
sv.c.ul = vtop[-1].c.ul;
|
||||||
|
load(t, &sv);
|
||||||
|
vtop[-1].r = t | VT_LVAL;
|
||||||
|
vtop[-1].c.ul = 0;
|
||||||
|
}
|
||||||
|
/* two word case handling : store second register at word + 4 */
|
||||||
|
#ifdef TCC_TARGET_X86_64
|
||||||
|
if ((dbt == VT_QLONG) || (dbt == VT_QFLOAT))
|
||||||
|
#else
|
||||||
|
if (dbt == 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;
|
||||||
|
#endif
|
||||||
|
vtop[-1].type.t = load_type;
|
||||||
|
store(r, vtop - 1);
|
||||||
|
vswap();
|
||||||
|
/* convert to int to increment easily */
|
||||||
|
vtop->type = char_pointer_type;
|
||||||
|
gaddrof();
|
||||||
|
vpushi(load_size);
|
||||||
|
gen_op('+');
|
||||||
|
vtop->r |= VT_LVAL;
|
||||||
|
vswap();
|
||||||
|
vtop[-1].type.t = load_type;
|
||||||
|
/* XXX: it works because r2 is spilled last ! */
|
||||||
|
store(vtop->r2, vtop - 1);
|
||||||
|
vtop->type.t = ft;
|
||||||
|
vtop[-1].type.t = ft;
|
||||||
|
} else {
|
||||||
|
store(r, vtop - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* store vtop in lvalue pushed on stack */
|
/* store vtop in lvalue pushed on stack */
|
||||||
ST_FUNC void vstore(void)
|
ST_FUNC void vstore(void)
|
||||||
{
|
{
|
||||||
int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
|
int sbt, dbt, ft, size, align, bit_size, bit_pos, delayed_cast;
|
||||||
|
|
||||||
ft = vtop[-1].type.t;
|
ft = vtop[-1].type.t;
|
||||||
sbt = vtop->type.t & VT_BTYPE;
|
sbt = vtop->type.t & VT_BTYPE;
|
||||||
dbt = ft & VT_BTYPE;
|
dbt = ft & VT_BTYPE;
|
||||||
if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
|
if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
|
||||||
(sbt == VT_INT && dbt == VT_SHORT))
|
(sbt == VT_INT && dbt == VT_SHORT)) && !(vtop->type.t & VT_BITFIELD)) {
|
||||||
&& !(vtop->type.t & VT_BITFIELD)) {
|
|
||||||
/* optimize char/short casts */
|
/* optimize char/short casts */
|
||||||
delayed_cast = VT_MUSTCAST;
|
delayed_cast = VT_MUSTCAST;
|
||||||
vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
|
vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
|
||||||
|
@ -2507,15 +2602,15 @@ ST_FUNC void vstore(void)
|
||||||
vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
|
vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
|
||||||
|
|
||||||
/* duplicate source into other register */
|
/* duplicate source into other register */
|
||||||
gv_dup();
|
|
||||||
vswap();
|
|
||||||
vrott(3);
|
|
||||||
|
|
||||||
if((ft & VT_BTYPE) == VT_BOOL) {
|
if((ft & VT_BTYPE) == VT_BOOL) {
|
||||||
gen_cast(&vtop[-1].type);
|
gen_cast(&vtop[-1].type);
|
||||||
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
|
vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* duplicate destination */
|
||||||
|
vdup();
|
||||||
|
vtop[-1] = vtop[-2];
|
||||||
|
|
||||||
/* duplicate destination */
|
/* duplicate destination */
|
||||||
vdup();
|
vdup();
|
||||||
vtop[-1] = vtop[-2];
|
vtop[-1] = vtop[-2];
|
||||||
|
@ -2556,56 +2651,7 @@ ST_FUNC void vstore(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!nocode_wanted) {
|
if (!nocode_wanted) {
|
||||||
rc = RC_INT;
|
vstore_im();
|
||||||
if (is_float(ft)) {
|
|
||||||
rc = RC_FLOAT;
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
if ((ft & VT_BTYPE) == VT_LDOUBLE) {
|
|
||||||
rc = RC_ST0;
|
|
||||||
} else if ((ft & VT_BTYPE) == VT_QFLOAT) {
|
|
||||||
rc = RC_FRET;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
r = gv(rc); /* generate value */
|
|
||||||
/* if lvalue was saved on stack, must read it */
|
|
||||||
if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
|
|
||||||
SValue sv;
|
|
||||||
t = get_reg(RC_INT);
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
sv.type.t = VT_PTR;
|
|
||||||
#else
|
|
||||||
sv.type.t = VT_INT;
|
|
||||||
#endif
|
|
||||||
sv.r = VT_LOCAL | VT_LVAL;
|
|
||||||
sv.c.ul = vtop[-1].c.ul;
|
|
||||||
load(t, &sv);
|
|
||||||
vtop[-1].r = t | VT_LVAL;
|
|
||||||
}
|
|
||||||
/* two word case handling : store second register at word + 4 (or +8 for x86-64) */
|
|
||||||
#ifdef TCC_TARGET_X86_64
|
|
||||||
if (((ft & VT_BTYPE) == VT_QLONG) || ((ft & 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;
|
|
||||||
#else
|
|
||||||
if ((ft & VT_BTYPE) == VT_LLONG) {
|
|
||||||
int addr_type = VT_INT, load_size = 4, load_type = VT_INT;
|
|
||||||
#endif
|
|
||||||
vtop[-1].type.t = load_type;
|
|
||||||
store(r, vtop - 1);
|
|
||||||
vswap();
|
|
||||||
/* convert to int to increment easily */
|
|
||||||
vtop->type.t = addr_type;
|
|
||||||
gaddrof();
|
|
||||||
vpushi(load_size);
|
|
||||||
gen_op('+');
|
|
||||||
vtop->r |= VT_LVAL;
|
|
||||||
vswap();
|
|
||||||
vtop[-1].type.t = load_type;
|
|
||||||
/* XXX: it works because r2 is spilled last ! */
|
|
||||||
store(vtop->r2, vtop - 1);
|
|
||||||
} else {
|
|
||||||
store(r, vtop - 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
vswap();
|
vswap();
|
||||||
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
|
||||||
|
@ -4623,6 +4669,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
gsym_addr(b, d);
|
gsym_addr(b, d);
|
||||||
} else if (tok == '{') {
|
} else if (tok == '{') {
|
||||||
Sym *llabel;
|
Sym *llabel;
|
||||||
|
int saved_loc, saved_pop_stack, size;
|
||||||
int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
|
int block_vla_sp_loc, *saved_vla_sp_loc, saved_vla_flags;
|
||||||
|
|
||||||
next();
|
next();
|
||||||
|
@ -4632,7 +4679,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
frame_bottom->next = scope_stack_bottom;
|
frame_bottom->next = scope_stack_bottom;
|
||||||
scope_stack_bottom = frame_bottom;
|
scope_stack_bottom = frame_bottom;
|
||||||
llabel = local_label_stack;
|
llabel = local_label_stack;
|
||||||
|
|
||||||
|
saved_loc = loc;
|
||||||
|
saved_pop_stack = pop_stack;
|
||||||
|
|
||||||
/* save VLA state */
|
/* save VLA state */
|
||||||
block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
|
block_vla_sp_loc = *(saved_vla_sp_loc = vla_sp_loc);
|
||||||
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
||||||
|
@ -4684,7 +4734,12 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
|
||||||
/* pop locally defined symbols */
|
/* pop locally defined symbols */
|
||||||
scope_stack_bottom = scope_stack_bottom->next;
|
scope_stack_bottom = scope_stack_bottom->next;
|
||||||
sym_pop(&local_stack, s);
|
sym_pop(&local_stack, s);
|
||||||
|
|
||||||
|
size = -(loc - saved_loc);
|
||||||
|
pop_stack = saved_pop_stack;
|
||||||
|
if(size)
|
||||||
|
pop_stack += size;
|
||||||
|
|
||||||
/* Pop VLA frames and restore stack pointer if required */
|
/* Pop VLA frames and restore stack pointer if required */
|
||||||
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
if (saved_vla_sp_loc != &vla_sp_root_loc)
|
||||||
*saved_vla_sp_loc = block_vla_sp_loc;
|
*saved_vla_sp_loc = block_vla_sp_loc;
|
||||||
|
|
|
@ -1680,7 +1680,6 @@ void prefix ## fcast(type a)\
|
||||||
printf("ftof: %f %f %Lf\n", fa, da, la);\
|
printf("ftof: %f %f %Lf\n", fa, da, la);\
|
||||||
ia = (int)a;\
|
ia = (int)a;\
|
||||||
llia = (long long)a;\
|
llia = (long long)a;\
|
||||||
a = (a >= 0) ? a : -a;\
|
|
||||||
ua = (unsigned int)a;\
|
ua = (unsigned int)a;\
|
||||||
llua = (unsigned long long)a;\
|
llua = (unsigned long long)a;\
|
||||||
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
|
printf("ftoi: %d %u %lld %llu\n", ia, ua, llia, llua);\
|
||||||
|
@ -1710,6 +1709,18 @@ void prefix ## call(void)\
|
||||||
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
|
printf("strto%s: %f\n", #prefix, (double)strto ## prefix("1.2", NULL));\
|
||||||
}\
|
}\
|
||||||
\
|
\
|
||||||
|
void prefix ## calc(type x, type y)\
|
||||||
|
{\
|
||||||
|
x=x*x;y=y*y;\
|
||||||
|
printf("%d, %d\n", (int)x, (int)y);\
|
||||||
|
x=x-y;y=y-x;\
|
||||||
|
printf("%d, %d\n", (int)x, (int)y);\
|
||||||
|
x=x/y;y=y/x;\
|
||||||
|
printf("%d, %d\n", (int)x, (int)y);\
|
||||||
|
x=x+x;y=y+y;\
|
||||||
|
printf("%d, %d\n", (int)x, (int)y);\
|
||||||
|
}\
|
||||||
|
\
|
||||||
void prefix ## signed_zeros(void) \
|
void prefix ## signed_zeros(void) \
|
||||||
{\
|
{\
|
||||||
type x = 0.0, y = -0.0, n, p;\
|
type x = 0.0, y = -0.0, n, p;\
|
||||||
|
@ -1732,7 +1743,7 @@ void prefix ## signed_zeros(void) \
|
||||||
1.0 / x != 1.0 / p);\
|
1.0 / x != 1.0 / p);\
|
||||||
else\
|
else\
|
||||||
printf ("x != +y; this is wrong!\n");\
|
printf ("x != +y; this is wrong!\n");\
|
||||||
p = -y;\
|
p = -y;\
|
||||||
if (x == p)\
|
if (x == p)\
|
||||||
printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\
|
printf ("Test 1.0 / x != 1.0 / -y returns %d (should be 0).\n",\
|
||||||
1.0 / x != 1.0 / p);\
|
1.0 / x != 1.0 / p);\
|
||||||
|
@ -1748,7 +1759,8 @@ void prefix ## test(void)\
|
||||||
prefix ## fcast(234.6);\
|
prefix ## fcast(234.6);\
|
||||||
prefix ## fcast(-2334.6);\
|
prefix ## fcast(-2334.6);\
|
||||||
prefix ## call();\
|
prefix ## call();\
|
||||||
prefix ## signed_zeros();\
|
prefix ## calc(1, 1.0000000000000001);\
|
||||||
|
prefix ## signed_zeros();\
|
||||||
}
|
}
|
||||||
|
|
||||||
FTEST(f, float, float, "%f")
|
FTEST(f, float, float, "%f")
|
||||||
|
@ -2572,7 +2584,6 @@ int constant_p_var;
|
||||||
|
|
||||||
void builtin_test(void)
|
void builtin_test(void)
|
||||||
{
|
{
|
||||||
#if GCC_MAJOR >= 3
|
|
||||||
COMPAT_TYPE(int, int);
|
COMPAT_TYPE(int, int);
|
||||||
COMPAT_TYPE(int, unsigned int);
|
COMPAT_TYPE(int, unsigned int);
|
||||||
COMPAT_TYPE(int, char);
|
COMPAT_TYPE(int, char);
|
||||||
|
@ -2582,9 +2593,9 @@ void builtin_test(void)
|
||||||
COMPAT_TYPE(int *, void *);
|
COMPAT_TYPE(int *, void *);
|
||||||
COMPAT_TYPE(int *, const int *);
|
COMPAT_TYPE(int *, const int *);
|
||||||
COMPAT_TYPE(char *, unsigned char *);
|
COMPAT_TYPE(char *, unsigned char *);
|
||||||
|
COMPAT_TYPE(char, unsigned char);
|
||||||
/* space is needed because tcc preprocessor introduces a space between each token */
|
/* space is needed because tcc preprocessor introduces a space between each token */
|
||||||
COMPAT_TYPE(char * *, void *);
|
COMPAT_TYPE(char **, void *);
|
||||||
#endif
|
|
||||||
printf("res = %d\n", __builtin_constant_p(1));
|
printf("res = %d\n", __builtin_constant_p(1));
|
||||||
printf("res = %d\n", __builtin_constant_p(1 + 2));
|
printf("res = %d\n", __builtin_constant_p(1 + 2));
|
||||||
printf("res = %d\n", __builtin_constant_p(&constant_p_var));
|
printf("res = %d\n", __builtin_constant_p(&constant_p_var));
|
||||||
|
|
57
x86_64-gen.c
57
x86_64-gen.c
|
@ -826,7 +826,7 @@ void gfunc_prolog(CType *func_type)
|
||||||
|
|
||||||
func_ret_sub = 0;
|
func_ret_sub = 0;
|
||||||
func_scratch = 0;
|
func_scratch = 0;
|
||||||
loc = 0;
|
pop_stack = loc = 0;
|
||||||
|
|
||||||
addr = PTR_SIZE * 2;
|
addr = PTR_SIZE * 2;
|
||||||
ind += FUNC_PROLOG_SIZE;
|
ind += FUNC_PROLOG_SIZE;
|
||||||
|
@ -968,12 +968,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty)
|
||||||
case VT_BYTE:
|
case VT_BYTE:
|
||||||
case VT_SHORT:
|
case VT_SHORT:
|
||||||
case VT_LLONG:
|
case VT_LLONG:
|
||||||
|
case VT_QLONG:
|
||||||
case VT_BOOL:
|
case VT_BOOL:
|
||||||
case VT_PTR:
|
case VT_PTR:
|
||||||
case VT_FUNC:
|
case VT_FUNC:
|
||||||
case VT_ENUM: return x86_64_mode_integer;
|
case VT_ENUM: return x86_64_mode_integer;
|
||||||
|
|
||||||
case VT_FLOAT:
|
case VT_FLOAT:
|
||||||
|
case VT_QFLOAT:
|
||||||
case VT_DOUBLE: return x86_64_mode_sse;
|
case VT_DOUBLE: return x86_64_mode_sse;
|
||||||
|
|
||||||
case VT_LDOUBLE: return x86_64_mode_x87;
|
case VT_LDOUBLE: return x86_64_mode_x87;
|
||||||
|
@ -984,7 +986,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty)
|
||||||
// Detect union
|
// Detect union
|
||||||
if (f->next && (f->c == f->next->c))
|
if (f->next && (f->c == f->next->c))
|
||||||
return x86_64_mode_memory;
|
return x86_64_mode_memory;
|
||||||
|
|
||||||
mode = x86_64_mode_none;
|
mode = x86_64_mode_none;
|
||||||
for (f = f->next; f; f = f->next)
|
for (f = f->next; f; f = f->next)
|
||||||
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
|
mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
|
||||||
|
@ -995,14 +997,14 @@ static X86_64_Mode classify_x86_64_inner(CType *ty)
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
|
static int classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
|
||||||
{
|
{
|
||||||
X86_64_Mode mode;
|
X86_64_Mode mode;
|
||||||
int size, align, ret_t = 0;
|
int size, align, ret_t = 0;
|
||||||
|
|
||||||
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
|
if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
|
||||||
*psize = 8;
|
*psize = 8;
|
||||||
*palign = 8;
|
*palign = 8;
|
||||||
*reg_count = 1;
|
*reg_count = 1;
|
||||||
ret_t = ty->t;
|
ret_t = ty->t;
|
||||||
mode = x86_64_mode_integer;
|
mode = x86_64_mode_integer;
|
||||||
|
@ -1013,6 +1015,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
|
||||||
|
|
||||||
if (size > 16) {
|
if (size > 16) {
|
||||||
mode = x86_64_mode_memory;
|
mode = x86_64_mode_memory;
|
||||||
|
ret_t = ty->t;
|
||||||
} else {
|
} else {
|
||||||
mode = classify_x86_64_inner(ty);
|
mode = classify_x86_64_inner(ty);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -1021,16 +1024,22 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
|
||||||
*reg_count = 2;
|
*reg_count = 2;
|
||||||
ret_t = VT_QLONG;
|
ret_t = VT_QLONG;
|
||||||
} else {
|
} else {
|
||||||
*reg_count = 1;
|
*reg_count = 1;
|
||||||
ret_t = (size > 4) ? VT_LLONG : VT_INT;
|
if(size > 4)
|
||||||
}
|
ret_t = VT_LLONG;
|
||||||
|
else if(size > 2){
|
||||||
|
ret_t = VT_INT;
|
||||||
|
}else if(size > 1)
|
||||||
|
ret_t = VT_SHORT;
|
||||||
|
else
|
||||||
|
ret_t = VT_BYTE;
|
||||||
|
}
|
||||||
|
ret_t |= (ty->t & VT_UNSIGNED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case x86_64_mode_x87:
|
case x86_64_mode_x87:
|
||||||
*reg_count = 1;
|
*reg_count = 1;
|
||||||
ret_t = VT_LDOUBLE;
|
ret_t = VT_LDOUBLE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case x86_64_mode_sse:
|
case x86_64_mode_sse:
|
||||||
if (size > 8) {
|
if (size > 8) {
|
||||||
*reg_count = 2;
|
*reg_count = 2;
|
||||||
|
@ -1040,13 +1049,15 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p
|
||||||
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
|
ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
|
default:
|
||||||
|
ret_t = ty->t;
|
||||||
|
break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret->ref = NULL;
|
ret->ref = ty->ref;
|
||||||
ret->t = ret_t;
|
ret->t = ret_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,12 +1068,13 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty)
|
||||||
{
|
{
|
||||||
/* This definition must be synced with stdarg.h */
|
/* This definition must be synced with stdarg.h */
|
||||||
enum __va_arg_type {
|
enum __va_arg_type {
|
||||||
__va_gen_reg, __va_float_reg, __va_stack
|
__va_gen_reg, __va_float_reg, __va_ld_reg, __va_stack
|
||||||
};
|
};
|
||||||
int size, align, reg_count;
|
int size, align, reg_count;
|
||||||
X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count);
|
X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, ®_count);
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
default: return __va_stack;
|
default: return __va_stack;
|
||||||
|
case x86_64_mode_x87: return __va_ld_reg;
|
||||||
case x86_64_mode_integer: return __va_gen_reg;
|
case x86_64_mode_integer: return __va_gen_reg;
|
||||||
case x86_64_mode_sse: return __va_float_reg;
|
case x86_64_mode_sse: return __va_float_reg;
|
||||||
}
|
}
|
||||||
|
@ -1387,7 +1399,7 @@ void gfunc_prolog(CType *func_type)
|
||||||
|
|
||||||
sym = func_type->ref;
|
sym = func_type->ref;
|
||||||
addr = PTR_SIZE * 2;
|
addr = PTR_SIZE * 2;
|
||||||
loc = 0;
|
pop_stack = loc = 0;
|
||||||
ind += FUNC_PROLOG_SIZE;
|
ind += FUNC_PROLOG_SIZE;
|
||||||
func_sub_sp_offset = ind;
|
func_sub_sp_offset = ind;
|
||||||
func_ret_sub = 0;
|
func_ret_sub = 0;
|
||||||
|
@ -1398,7 +1410,6 @@ void gfunc_prolog(CType *func_type)
|
||||||
/* frame pointer and return address */
|
/* frame pointer and return address */
|
||||||
seen_stack_size = PTR_SIZE * 2;
|
seen_stack_size = PTR_SIZE * 2;
|
||||||
/* count the number of seen parameters */
|
/* count the number of seen parameters */
|
||||||
sym = func_type->ref;
|
|
||||||
while ((sym = sym->next) != NULL) {
|
while ((sym = sym->next) != NULL) {
|
||||||
type = &sym->type;
|
type = &sym->type;
|
||||||
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
mode = classify_x86_64_arg(type, NULL, &size, &align, ®_count);
|
||||||
|
@ -1439,19 +1450,19 @@ void gfunc_prolog(CType *func_type)
|
||||||
o(0xf845c7);
|
o(0xf845c7);
|
||||||
gen_le32(seen_stack_size);
|
gen_le32(seen_stack_size);
|
||||||
|
|
||||||
|
o(0xc084);/* test %al,%al */
|
||||||
|
o(0x74);/* je */
|
||||||
|
g(4*(8 - seen_sse_num) + 3);
|
||||||
|
|
||||||
/* save all register passing arguments */
|
/* save all register passing arguments */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
loc -= 16;
|
loc -= 16;
|
||||||
o(0xd60f66); /* movq */
|
o(0x290f);/* movaps %xmm1-7,-XXX(%rbp) */
|
||||||
gen_modrm(7 - i, VT_LOCAL, NULL, loc);
|
gen_modrm(7 - i, VT_LOCAL, NULL, loc);
|
||||||
/* movq $0, loc+8(%rbp) */
|
|
||||||
o(0x85c748);
|
|
||||||
gen_le32(loc + 8);
|
|
||||||
gen_le32(0);
|
|
||||||
}
|
|
||||||
for (i = 0; i < REGN; i++) {
|
|
||||||
push_arg_reg(REGN-1-i);
|
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < (REGN - seen_reg_num); i++) {
|
||||||
|
push_arg_reg(REGN-1 - i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sym = func_type->ref;
|
sym = func_type->ref;
|
||||||
|
|
Loading…
Reference in a new issue