From f6b50558fc46aeb8e981355009871b30e61de841 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Fri, 14 Jun 2013 16:18:16 +0200 Subject: Add support for load/store of _Bool value Add support for loading _Bool value in i386, x86_64 and arm as well as support for storing _Bool value on arm. --- x86_64-gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 2788677..d1bf75c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -414,7 +414,7 @@ void load(int r, SValue *sv) r = REG_VALUE(r); } else if ((ft & VT_BTYPE) == VT_LDOUBLE) { b = 0xdb, r = 5; /* fldt */ - } else if ((ft & VT_TYPE) == VT_BYTE) { + } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) { b = 0xbe0f; /* movsbl */ } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) { b = 0xb60f; /* movzbl */ -- cgit v1.3.1 From 0f5942c6b382105075dabb6f975a313efc63a5f9 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 24 Sep 2013 15:36:04 +0200 Subject: Avoid warnings with gcc 4.8 + default CFLAGS --- tccgen.c | 3 +-- x86_64-gen.c | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'x86_64-gen.c') diff --git a/tccgen.c b/tccgen.c index 0f0aac5..d5b915b 100644 --- a/tccgen.c +++ b/tccgen.c @@ -800,9 +800,9 @@ ST_FUNC int gv(int rc) #else if ((vtop->type.t & VT_BTYPE) == VT_LLONG) { int addr_type = VT_INT, load_size = 4, load_type = VT_INT; + unsigned long long ll; #endif int r2, original_type; - unsigned long long ll; original_type = vtop->type.t; /* two register type load : expand to two words temporarily */ @@ -3765,7 +3765,6 @@ ST_FUNC void unary(void) case TOK_builtin_va_arg_types: { CType type; - int bt; next(); skip('('); parse_type(&type); diff --git a/x86_64-gen.c b/x86_64-gen.c index d1bf75c..3cb211a 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -239,13 +239,6 @@ static int is64_type(int t) (t & VT_BTYPE) == VT_LLONG); } -static int is_sse_float(int t) { - int bt; - bt = t & VT_BTYPE; - return bt == VT_DOUBLE || bt == VT_FLOAT; -} - - /* instruction + 4 bytes data. Return the address of the data */ ST_FUNC int oad(int c, int s) { @@ -687,6 +680,12 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) } } +static int is_sse_float(int t) { + int bt; + bt = t & VT_BTYPE; + return bt == VT_DOUBLE || bt == VT_FLOAT; +} + int gfunc_arg_size(CType *type) { int align; if (type->t & (VT_ARRAY|VT_BITFIELD)) @@ -989,7 +988,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) { X86_64_Mode mode; - int size, align, ret_t; + int size, align, ret_t = 0; if (ty->t & (VT_BITFIELD|VT_ARRAY)) { *psize = 8; @@ -1030,6 +1029,9 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT; } break; + case x86_64_mode_memory: /* avoid warning */ + case x86_64_mode_none: + tcc_error("argument type not handled in classify_x86_64_arg\n"); } } } @@ -1083,7 +1085,7 @@ void gfunc_call(int nb_args) { X86_64_Mode mode; CType type; - int size, align, r, args_size, stack_adjust, run_start, run_end, i, j, reg_count; + int size, align, r, args_size, stack_adjust, run_start, run_end, i, reg_count; int nb_reg_args = 0; int nb_sse_args = 0; int sse_reg, gen_reg; @@ -1133,6 +1135,8 @@ void gfunc_call(int nb_args) gen_reg -= reg_count; if (gen_reg + reg_count > REGN) goto stack_arg; break; + case x86_64_mode_none: /* avoid warning */ + tcc_error("argument type not handled in gfunc_call"); } } @@ -1366,7 +1370,7 @@ void gfunc_prolog(CType *func_type) { X86_64_Mode mode; int i, addr, align, size, reg_count; - int param_addr, reg_param_index, sse_param_index; + int param_addr = 0, reg_param_index, sse_param_index; Sym *sym; CType *type; @@ -1499,6 +1503,8 @@ void gfunc_prolog(CType *func_type) } break; } + case x86_64_mode_none: + tcc_error("argument type not handled in gfunc_prolog\n"); } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, param_addr); -- cgit v1.3.1 From 385a86b000ca8c363959a1ae7b6a5518446ce497 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 1 Oct 2013 17:10:18 +0200 Subject: Fix commit 0f5942c6b382105075dabb6f975a313efc63a5f9 --- x86_64-gen.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 3cb211a..690236e 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1029,9 +1029,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT; } break; - case x86_64_mode_memory: /* avoid warning */ - case x86_64_mode_none: - tcc_error("argument type not handled in classify_x86_64_arg\n"); + default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/ } } } @@ -1135,8 +1133,7 @@ void gfunc_call(int nb_args) gen_reg -= reg_count; if (gen_reg + reg_count > REGN) goto stack_arg; break; - case x86_64_mode_none: /* avoid warning */ - tcc_error("argument type not handled in gfunc_call"); + default: break; /* nothing to be done for x86_64_mode_none */ } } @@ -1503,8 +1500,7 @@ void gfunc_prolog(CType *func_type) } break; } - case x86_64_mode_none: - tcc_error("argument type not handled in gfunc_prolog\n"); + default: break; /* nothing to be done for x86_64_mode_none */ } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, param_addr); -- cgit v1.3.1 From dcec8673f21da86ae3dcf1ca3e9498127715b795 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Fri, 22 Nov 2013 09:27:15 +0800 Subject: Add support for struct > 4B returned via registers 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. --- arm-gen.c | 48 ++++++++++++++++++++++++++++++------------------ c67-gen.c | 5 +++-- i386-gen.c | 9 +++++---- tccgen.c | 46 +++++++++++++++++++++++++++++----------------- x86_64-gen.c | 18 ++++++++++-------- 5 files changed, 77 insertions(+), 49 deletions(-) (limited to 'x86_64-gen.c') diff --git a/arm-gen.c b/arm-gen.c index 92b080d..6d0acd8 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -746,24 +746,6 @@ static void gcall_or_jmp(int is_jmp) } } -/* Return 1 if this function returns via an sret pointer, 0 otherwise */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { -#ifdef TCC_ARM_EABI - int size, align; - size = type_size(vt, &align); - if (size > 4) { - return 1; - } else { - *ret_align = 4; - ret->ref = NULL; - ret->t = VT_INT; - return 0; - } -#else - return 1; -#endif -} - #ifdef TCC_ARM_HARDFLOAT /* Return whether a structure is an homogeneous float aggregate or not. The answer is true if all the elements of the structure are of the same @@ -831,6 +813,33 @@ int assign_vfpreg(struct avail_regs *avregs, int align, int size) } #endif +/* Return the number of registers needed to return the struct, or 0 if + returning via struct pointer. */ +ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +#ifdef TCC_ARM_EABI + int size, align; + size = type_size(vt, &align); +#ifdef TCC_ARM_HARDFLOAT + if (is_float(vt->t) || is_hgen_float_aggr(vt)) { + *ret_align = 8; + ret->ref = NULL; + ret->t = VT_DOUBLE; + return (size + 7) >> 3; + } else +#endif + if (size > 4) { + return 0; + } else { + *ret_align = 4; + ret->ref = NULL; + ret->t = VT_INT; + return 1; + } +#else + return 0; +#endif +} + /* Parameters are classified according to how they are copied to their final destination for the function call. Because the copying is performed class after class according to the order in the union below, it is important that @@ -1198,6 +1207,9 @@ void gfunc_prolog(CType *func_type) n = nf = 0; variadic = (func_type->ref->c == FUNC_ELLIPSIS); if((func_vt.t & VT_BTYPE) == VT_STRUCT +#ifdef TCC_ARM_HARDFLOAT + && (variadic || !is_hgen_float_aggr(&func_vt)) +#endif && type_size(&func_vt,&align) > 4) { n++; diff --git a/c67-gen.c b/c67-gen.c index 0d5e33f..1189dbb 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1879,10 +1879,11 @@ static void gcall_or_jmp(int is_jmp) } } -/* Return 1 if this function returns via an sret pointer, 0 otherwise */ +/* Return the number of registers needed to return the struct, or 0 if + returning via struct pointer. */ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { *ret_align = 1; // Never have to re-align return values for x86-64 - return 1; + return 0; } /* generate function call with address in (vtop->t, vtop->c) and free function diff --git a/i386-gen.c b/i386-gen.c index 0a6d4d3..eaab2b7 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -374,7 +374,8 @@ static void gcall_or_jmp(int is_jmp) static uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX }; static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; -/* Return 1 if this function returns via an sret pointer, 0 otherwise */ +/* Return the number of registers needed to return the struct, or 0 if + returning via struct pointer. */ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { #ifdef TCC_TARGET_PE @@ -383,11 +384,11 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) *ret_align = 1; // Never have to re-align return values for x86 size = type_size(vt, &align); if (size > 8) { - return 1; + return 0; } else if (size > 4) { ret->ref = NULL; ret->t = VT_LLONG; - return 0; + return 1; } else { ret->ref = NULL; ret->t = VT_INT; @@ -395,7 +396,7 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) } #else *ret_align = 1; // Never have to re-align return values for x86 - return 1; + return 0; #endif } diff --git a/tccgen.c b/tccgen.c index bab4f7c..500e99e 100644 --- a/tccgen.c +++ b/tccgen.c @@ -3927,7 +3927,7 @@ ST_FUNC void unary(void) } else if (tok == '(') { SValue ret; Sym *sa; - int nb_args, sret; + int nb_args, sret, ret_align; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -3951,9 +3951,8 @@ ST_FUNC void unary(void) ret.r2 = VT_CONST; /* compute first implicit argument if a structure is returned */ if ((s->type.t & VT_BTYPE) == VT_STRUCT) { - int ret_align; sret = gfunc_sret(&s->type, &ret.type, &ret_align); - if (sret) { + if (!sret) { /* get some space for the returned structure */ size = type_size(&s->type, &align); loc = (loc - size) & -align; @@ -3966,11 +3965,11 @@ ST_FUNC void unary(void) nb_args++; } } else { - sret = 0; + sret = 1; ret.type = s->type; } - if (!sret) { + if (sret) { /* return in register */ if (is_float(ret.type.t)) { ret.r = reg_fret(ret.type.t); @@ -4010,18 +4009,23 @@ ST_FUNC void unary(void) vtop -= (nb_args + 1); } /* return value */ - vsetc(&ret.type, ret.r, &ret.c); - vtop->r2 = ret.r2; + for (r = ret.r + sret + !sret; r-- > ret.r;) { + vsetc(&ret.type, r, &ret.c); + vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ + } /* handle packed struct return */ - if (((s->type.t & VT_BTYPE) == VT_STRUCT) && !sret) { - int addr; + if (((s->type.t & VT_BTYPE) == VT_STRUCT) && sret) { + int addr, offset; + size = type_size(&s->type, &align); loc = (loc - size) & -align; addr = loc; - vset(&ret.type, VT_LOCAL | VT_LVAL, addr); - vswap(); - vstore(); - vtop--; + for(offset = 0; offset < size; offset += ret_align) { + vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); + vswap(); + vstore(); + vtop--; + } vset(&s->type, VT_LOCAL | VT_LVAL, addr); } } else { @@ -4593,7 +4597,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { CType type, ret_type; int ret_align; - if (gfunc_sret(&func_vt, &ret_type, &ret_align)) { + if (!gfunc_sret(&func_vt, &ret_type, &ret_align)) { /* if returning structure, must copy it to implicit first pointer arg location */ type = func_vt; @@ -4605,7 +4609,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, vstore(); } else { /* returning structure packed into registers */ - int size, addr, align; + int r, size, addr, offset, align; size = type_size(&func_vt,&align); if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1))) && (align & (ret_align-1))) { @@ -4619,9 +4623,17 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, } vtop->type = ret_type; if (is_float(ret_type.t)) - gv(rc_fret(ret_type.t)); + r = rc_fret(ret_type.t); else - gv(RC_IRET); + r = RC_IRET; + /* We assume that when a structure is returned in multiple + registers, their classes are consecutive values of the + suite s(n) = 2^n */ + for (offset = 0; offset < size; offset += ret_align, r<<=1) { + gv(r); + vtop->c.i += ret_align; + vtop->r = VT_LOCAL | VT_LVAL; + } } } else if (is_float(func_vt.t)) { gv(rc_fret(func_vt.t)); diff --git a/x86_64-gen.c b/x86_64-gen.c index 690236e..0962056 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -656,7 +656,8 @@ void gen_offs_sp(int b, int r, int d) } } -/* Return 1 if this function returns via an sret pointer, 0 otherwise */ +/* Return the number of registers needed to return the struct, or 0 if + returning via struct pointer. */ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { int size, align; @@ -664,19 +665,19 @@ ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) size = type_size(vt, &align); ret->ref = NULL; if (size > 8) { - return 1; + return 0; } else if (size > 4) { ret->t = VT_LLONG; - return 0; + return 1; } else if (size > 2) { ret->t = VT_INT; - return 0; + return 1; } else if (size > 1) { ret->t = VT_SHORT; - return 0; + return 1; } else { ret->t = VT_BYTE; - return 0; + return 1; } } @@ -1056,11 +1057,12 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { } } -/* Return 1 if this function returns via an sret pointer, 0 otherwise */ +/* Return the number of registers needed to return the struct, or 0 if + returning via struct pointer. */ int gfunc_sret(CType *vt, CType *ret, int *ret_align) { int size, align, reg_count; *ret_align = 1; // Never have to re-align return values for x86-64 - return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) == x86_64_mode_memory); + return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory); } #define REGN 6 -- cgit v1.3.1 From 59b8007f98eb814f6fd19455ab868ecaa07dfc0d Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Fri, 3 Jan 2014 08:41:34 +0800 Subject: Always set *palign in classify_x86_64_arg Set *palign for VT_BITFIELD and VT_ARRAY types in classify_x86_64_arg as else you happen to have in *palign what was already there. This can cause gfunc_call on !PE systems to consider an array as 16 bytes align and trigger the assert if the previous argument was 16 bytes aligned. --- x86_64-gen.c | 1 + 1 file changed, 1 insertion(+) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 0962056..2f4d8fe 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -993,6 +993,7 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p if (ty->t & (VT_BITFIELD|VT_ARRAY)) { *psize = 8; + *palign = 8; *reg_count = 1; ret_t = ty->t; mode = x86_64_mode_integer; -- cgit v1.3.1 From e0e9a2a29562ac0f07c5d29070e1797fa48b144f Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 31 Dec 2013 23:40:21 +0800 Subject: Report error on NaN comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use comisd / fcompp for float comparison (except TOK_EQ and TOK_NE) instead of ucomisd / fucompp to detect NaN comparison. Thanks Vincent Lefèvre for the bug report and for also giving the solution. --- i386-gen.c | 5 ++++- x86_64-gen.c | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'x86_64-gen.c') diff --git a/i386-gen.c b/i386-gen.c index b26b844..ebc0d14 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -895,7 +895,10 @@ ST_FUNC void gen_opf(int op) swapped = 0; if (swapped) o(0xc9d9); /* fxch %st(1) */ - o(0xe9da); /* fucompp */ + if (op == TOK_EQ || op == TOK_NE) + o(0xe9da); /* fucompp */ + else + o(0xd9de); /* fcompp */ o(0xe0df); /* fnstsw %ax */ if (op == TOK_EQ) { o(0x45e480); /* and $0x45, %ah */ diff --git a/x86_64-gen.c b/x86_64-gen.c index 2f4d8fe..1550c07 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1793,7 +1793,10 @@ void gen_opf(int op) swapped = 0; if (swapped) o(0xc9d9); /* fxch %st(1) */ - o(0xe9da); /* fucompp */ + if (op == TOK_EQ || op == TOK_NE) + o(0xe9da); /* fucompp */ + else + o(0xd9de); /* fcompp */ o(0xe0df); /* fnstsw %ax */ if (op == TOK_EQ) { o(0x45e480); /* and $0x45, %ah */ @@ -1877,8 +1880,11 @@ void gen_opf(int op) if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) o(0x66); - o(0x2e0f); /* ucomisd */ - + if (op == TOK_EQ || op == TOK_NE) + o(0x2e0f); /* ucomisd */ + else + o(0x2f0f); /* comisd */ + if (vtop->r & VT_LVAL) { gen_modrm(vtop[-1].r, r, vtop->sym, fc); } else { -- cgit v1.3.1 From eda2c756edc4dca004ba217d5bf361235dd9de1f Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Tue, 31 Dec 2013 23:51:20 +0800 Subject: 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. --- arm-gen.c | 25 +------------------------ c67-gen.c | 33 +-------------------------------- i386-gen.c | 19 +------------------ il-gen.c | 15 +-------------- tccgen.c | 44 ++++++++++++++++++++++++++++++++------------ x86_64-gen.c | 19 +------------------ 6 files changed, 37 insertions(+), 118 deletions(-) (limited to 'x86_64-gen.c') diff --git a/arm-gen.c b/arm-gen.c index 0aa07b1..eecb7d2 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1390,7 +1390,7 @@ int gtst(int inv, int t) op|=encbranch(r,t,1); o(op); t=r; - } else if (v == VT_JMP || v == VT_JMPI) { + } else { /* VT_JMP || VT_JMPI */ if ((v & 1) == inv) { if(!vtop->c.i) vtop->c.i=t; @@ -1412,29 +1412,6 @@ int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else { - if (is_float(vtop->type.t)) { - r=gv(RC_FLOAT); -#ifdef TCC_ARM_VFP - o(0xEEB50A40|(vfpr(r)<<12)|T2CPR(vtop->type.t)); /* fcmpzX */ - o(0xEEF1FA10); /* fmstat */ -#else - o(0xEE90F118|(fpr(r)<<16)); -#endif - vtop->r = VT_CMP; - vtop->c.i = TOK_NE; - return gtst(inv, t); - } else if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - v = gv(RC_INT); - o(0xE3300000|(intr(v)<<16)); - vtop->r = VT_CMP; - vtop->c.i = TOK_NE; - return gtst(inv, t); - } } vtop--; return t; diff --git a/c67-gen.c b/c67-gen.c index 1189dbb..df4b5d3 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -2103,7 +2103,7 @@ int gtst(int inv, int t) C67_NOP(5); t = ind1; //return where we need to patch - } else if (v == VT_JMP || v == VT_JMPI) { + } else { /* VT_JMP || VT_JMPI */ /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ @@ -2129,37 +2129,6 @@ int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else { - if (is_float(vtop->type.t)) { - vpushi(0); - gen_op(TOK_NE); - } - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - // I think we need to get the value on the stack - // into a register, test it, and generate a branch - // return the address of the branch, so it can be - // later patched - - v = gv(RC_INT); // get value into a reg - ind1 = ind; - C67_MVKL(C67_A0, t); //r=reg to load, constant - C67_MVKH(C67_A0, t); //r=reg to load, constant - - if (v != TREG_EAX && // check if not already in a conditional test reg - v != TREG_EDX && v != TREG_ST0 && v != C67_B2) { - C67_MV(v, C67_B2); - v = C67_B2; - } - - C67_IREG_B_REG(inv, v, C67_A0); // [!R] B.S2x A0 - C67_NOP(5); - t = ind1; //return where we need to patch - ind1 = ind; - } } vtop--; return t; diff --git a/i386-gen.c b/i386-gen.c index ebc0d14..2cb31ff 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -682,7 +682,7 @@ ST_FUNC int gtst(int inv, int t) /* fast case : can jump directly since flags are set */ g(0x0f); t = psym((vtop->c.i - 16) ^ inv, t); - } else if (v == VT_JMP || v == VT_JMPI) { + } else { /* VT_JMP || VT_JMPI */ /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ @@ -695,23 +695,6 @@ ST_FUNC int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else { - if (is_float(vtop->type.t) || - (vtop->type.t & VT_BTYPE) == VT_LLONG) { - vpushi(0); - gen_op(TOK_NE); - } - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - v = gv(RC_INT); - o(0x85); - o(0xc0 + v * 9); - g(0x0f); - t = psym(0x85 ^ inv, t); - } } vtop--; return t; diff --git a/il-gen.c b/il-gen.c index 170f436..33f9f36 100644 --- a/il-gen.c +++ b/il-gen.c @@ -515,7 +515,7 @@ int gtst(int inv, int t) break; } t = out_opj(c, t); - } else if (v == VT_JMP || v == VT_JMPI) { + } else { /* VT_JMP || VT_JMPI */ /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ @@ -528,19 +528,6 @@ int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else { - if (is_float(vtop->t)) { - vpushi(0); - gen_op(TOK_NE); - } - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - v = gv(RC_INT); - t = out_opj(IL_OP_BRTRUE - inv, t); - } } vtop--; return t; diff --git a/tccgen.c b/tccgen.c index e8f7f82..55b03e6 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1095,6 +1095,26 @@ static void gv_dup(void) } } +/* Generate value test + * + * Generate a test for any value (jump, comparison and integers) */ +int gvtst(int inv, int t) +{ + int v = vtop->r & VT_VALMASK; + if (v != VT_CMP && v != VT_JMP && v != VT_JMPI) { + vpushi(0); + gen_op(TOK_NE); + } + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { + /* constant jmp optimization */ + if ((vtop->c.i != 0) != inv) + t = gjmp(t); + vtop--; + return t; + } + return gtst(inv, t); +} + #ifndef TCC_TARGET_X86_64 /* generate CPU independent (unsigned) long long operations */ static void gen_opl(int op) @@ -1293,13 +1313,13 @@ static void gen_opl(int op) b = 0; gen_op(op1); if (op1 != TOK_NE) { - a = gtst(1, 0); + a = gvtst(1, 0); } if (op != TOK_EQ) { /* generate non equal test */ /* XXX: NOT PORTABLE yet */ if (a == 0) { - b = gtst(0, 0); + b = gvtst(0, 0); } else { #if defined(TCC_TARGET_I386) b = psym(0x850f, 0); @@ -1324,7 +1344,7 @@ static void gen_opl(int op) else if (op1 == TOK_GE) op1 = TOK_UGE; gen_op(op1); - a = gtst(1, a); + a = gvtst(1, a); gsym(b); vseti(VT_JMPI, a); break; @@ -3665,7 +3685,7 @@ ST_FUNC void unary(void) vtop->c.i = vtop->c.i ^ 1; else { save_regs(1); - vseti(VT_JMP, gtst(1, 0)); + vseti(VT_JMP, gvtst(1, 0)); } break; case '~': @@ -4182,7 +4202,7 @@ static void expr_land(void) t = 0; save_regs(1); for(;;) { - t = gtst(1, t); + t = gvtst(1, t); if (tok != TOK_LAND) { vseti(VT_JMPI, t); break; @@ -4202,7 +4222,7 @@ static void expr_lor(void) t = 0; save_regs(1); for(;;) { - t = gtst(0, t); + t = gvtst(0, t); if (tok != TOK_LOR) { vseti(VT_JMP, t); break; @@ -4264,9 +4284,9 @@ static void expr_cond(void) } if (tok == ':' && gnu_ext) { gv_dup(); - tt = gtst(1, 0); + tt = gvtst(1, 0); } else { - tt = gtst(1, 0); + tt = gvtst(1, 0); gexpr(); } type1 = vtop->type; @@ -4512,7 +4532,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip('('); gexpr(); skip(')'); - a = gtst(1, 0); + a = gvtst(1, 0); block(bsym, csym, case_sym, def_sym, case_reg, 0); c = tok; if (c == TOK_ELSE) { @@ -4529,7 +4549,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip('('); gexpr(); skip(')'); - a = gtst(1, 0); + a = gvtst(1, 0); b = 0; block(&a, &b, case_sym, def_sym, case_reg, 0); gjmp_addr(d); @@ -4707,7 +4727,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, b = 0; if (tok != ';') { gexpr(); - a = gtst(1, 0); + a = gvtst(1, 0); } skip(';'); if (tok != ')') { @@ -4736,7 +4756,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip('('); gsym(b); gexpr(); - c = gtst(0, 0); + c = gvtst(0, 0); gsym_addr(c, d); skip(')'); gsym(a); diff --git a/x86_64-gen.c b/x86_64-gen.c index 1550c07..fe028d9 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1582,7 +1582,7 @@ int gtst(int inv, int t) } g(0x0f); t = psym((vtop->c.i - 16) ^ inv, t); - } else if (v == VT_JMP || v == VT_JMPI) { + } else { /* VT_JMP || VT_JMPI */ /* && or || optimization */ if ((v & 1) == inv) { /* insert vtop->c jump list in t */ @@ -1595,23 +1595,6 @@ int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else { - if (is_float(vtop->type.t) || - (vtop->type.t & VT_BTYPE) == VT_LLONG) { - vpushi(0); - gen_op(TOK_NE); - } - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - /* constant jmp optimization */ - if ((vtop->c.i != 0) != inv) - t = gjmp(t); - } else { - v = gv(RC_INT); - orex(0,v,v,0x85); - o(0xc0 + REG_VALUE(v) * 9); - g(0x0f); - t = psym(0x85 ^ inv, t); - } } vtop--; return t; -- cgit v1.3.1 From 8efaa711904b897f9a4821656ac10f980c5ae9fe Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Mon, 6 Jan 2014 22:27:39 +0800 Subject: Fix struct ret in variadic fct with ARM hardfloat 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(). --- arm-gen.c | 34 ++++++++++++++++++---------------- c67-gen.c | 3 ++- i386-gen.c | 3 ++- il-gen.c | 1 + tcc.h | 3 ++- tccgen.c | 11 ++++++++--- x86_64-gen.c | 3 ++- 7 files changed, 35 insertions(+), 23 deletions(-) (limited to 'x86_64-gen.c') diff --git a/arm-gen.c b/arm-gen.c index eecb7d2..9e6c638 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -839,12 +839,12 @@ int floats_in_core_regs(SValue *sval) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_ARM_EABI int size, align; size = type_size(vt, &align); #ifdef TCC_ARM_HARDFLOAT - if (is_float(vt->t) || is_hgen_float_aggr(vt)) { + if (!variadic && (is_float(vt->t) || is_hgen_float_aggr(vt))) { *ret_align = 8; ret->ref = NULL; ret->t = VT_DOUBLE; @@ -1221,21 +1221,19 @@ void gfunc_call(int nb_args) void gfunc_prolog(CType *func_type) { Sym *sym,*sym2; - int n,nf,size,align, variadic, struct_ret = 0; + int n, nf, size, align, struct_ret = 0; #ifdef TCC_ARM_HARDFLOAT struct avail_regs avregs = AVAIL_REGS_INITIALIZER; #endif + CType ret_type; sym = func_type->ref; func_vt = sym->type; + func_var = (func_type->ref->c == FUNC_ELLIPSIS); n = nf = 0; - variadic = (func_type->ref->c == FUNC_ELLIPSIS); - if((func_vt.t & VT_BTYPE) == VT_STRUCT -#ifdef TCC_ARM_HARDFLOAT - && (variadic || !is_hgen_float_aggr(&func_vt)) -#endif - && type_size(&func_vt,&align) > 4) + if ((func_vt.t & VT_BTYPE) == VT_STRUCT && + !gfunc_sret(&func_vt, func_var, &ret_type, &align)) { n++; struct_ret = 1; @@ -1244,7 +1242,7 @@ void gfunc_prolog(CType *func_type) for(sym2=sym->next;sym2 && (n<4 || nf<16);sym2=sym2->next) { size = type_size(&sym2->type, &align); #ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(sym2->type.t) + if (!func_var && (is_float(sym2->type.t) || is_hgen_float_aggr(&sym2->type))) { int tmpnf = assign_vfpreg(&avregs, align, size); tmpnf += (size + 3) / 4; @@ -1255,9 +1253,9 @@ void gfunc_prolog(CType *func_type) n += (size + 3) / 4; } o(0xE1A0C00D); /* mov ip,sp */ - if(variadic) + if (func_var) n=4; - if(n) { + if (n) { if(n>4) n=4; #ifdef TCC_ARM_EABI @@ -1289,7 +1287,7 @@ void gfunc_prolog(CType *func_type) size = (size + 3) >> 2; align = (align + 3) & ~3; #ifdef TCC_ARM_HARDFLOAT - if (!variadic && (is_float(sym->type.t) + if (!func_var && (is_float(sym->type.t) || is_hgen_float_aggr(&sym->type))) { int fpn = assign_vfpreg(&avregs, align, size << 2); if (fpn >= 0) { @@ -1329,10 +1327,14 @@ void gfunc_epilog(void) { uint32_t x; int diff; + /* Copy float return value to core register if base standard is used and + float computation is made with VFP */ #ifdef TCC_ARM_EABI - /* Useless but harmless copy of the float result into main register(s) in case - of variadic function in the hardfloat variant */ - if(is_float(func_vt.t)) { + if ( +#ifdef TCC_ARM_HARDFLOAT + func_var && +#endif + is_float(func_vt.t)) { if((func_vt.t & VT_BTYPE) == VT_FLOAT) o(0xEE100A10); /* fmrs r0, s0 */ else { diff --git a/c67-gen.c b/c67-gen.c index df4b5d3..f2baea5 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1881,7 +1881,7 @@ static void gcall_or_jmp(int is_jmp) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { *ret_align = 1; // Never have to re-align return values for x86-64 return 0; } @@ -1971,6 +1971,7 @@ void gfunc_prolog(CType * func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr += 4; diff --git a/i386-gen.c b/i386-gen.c index 4201ac2..2eb6922 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -376,7 +376,7 @@ static uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX }; /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { #ifdef TCC_TARGET_PE int size, align; @@ -527,6 +527,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); #ifdef TCC_TARGET_PE size = type_size(&func_vt,&align); if (((func_vt.t & VT_BTYPE) == VT_STRUCT) && (size > 8)) { diff --git a/il-gen.c b/il-gen.c index 33f9f36..9e1ec64 100644 --- a/il-gen.c +++ b/il-gen.c @@ -441,6 +441,7 @@ void gfunc_prolog(int t) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->t; + func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr++; diff --git a/tcc.h b/tcc.h index 50642b7..21957e7 100644 --- a/tcc.h +++ b/tcc.h @@ -1176,6 +1176,7 @@ ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ +ST_DATA int func_var; /* true if current function is variadic */ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA char *funcname; @@ -1288,7 +1289,7 @@ ST_FUNC void gsym_addr(int t, int a); ST_FUNC void gsym(int t); ST_FUNC void load(int r, SValue *sv); ST_FUNC void store(int r, SValue *v); -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *align); +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align); ST_FUNC void gfunc_call(int nb_args); ST_FUNC void gfunc_prolog(CType *func_type); ST_FUNC void gfunc_epilog(void); diff --git a/tccgen.c b/tccgen.c index 55b03e6..8355aae 100644 --- a/tccgen.c +++ b/tccgen.c @@ -66,6 +66,7 @@ ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */ ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */ ST_DATA CType func_vt; /* current function return type (used by return instruction) */ +ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */ ST_DATA int func_vc; ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and pc */ ST_DATA char *funcname; @@ -3960,7 +3961,7 @@ ST_FUNC void unary(void) } else if (tok == '(') { SValue ret; Sym *sa; - int nb_args, ret_nregs, ret_align; + int nb_args, ret_nregs, ret_align, variadic; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -3984,7 +3985,9 @@ ST_FUNC void unary(void) ret.r2 = VT_CONST; /* compute first implicit argument if a structure is returned */ if ((s->type.t & VT_BTYPE) == VT_STRUCT) { - ret_nregs = gfunc_sret(&s->type, &ret.type, &ret_align); + variadic = (s->c == FUNC_ELLIPSIS); + ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, + &ret_align); if (!ret_nregs) { /* get some space for the returned structure */ size = type_size(&s->type, &align); @@ -4637,7 +4640,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { CType type, ret_type; int ret_align, ret_nregs; - ret_nregs = gfunc_sret(&func_vt, &ret_type, &ret_align); + ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type, + &ret_align); if (0 == ret_nregs) { /* if returning structure, must copy it to implicit first pointer arg location */ @@ -5747,6 +5751,7 @@ static void gen_function(Sym *sym) cur_text_section = NULL; funcname = ""; /* for safety */ func_vt.t = VT_VOID; /* for safety */ + func_var = 0; /* for safety */ ind = 0; /* for safety */ nocode_wanted = saved_nocode_wanted; } diff --git a/x86_64-gen.c b/x86_64-gen.c index fe028d9..9aee875 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -658,7 +658,7 @@ void gen_offs_sp(int b, int r, int d) /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -ST_FUNC int gfunc_sret(CType *vt, CType *ret, int *ret_align) +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) { int size, align; *ret_align = 1; // Never have to re-align return values for x86-64 @@ -833,6 +833,7 @@ void gfunc_prolog(CType *func_type) /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; + func_var = (sym->c == FUNC_ELLIPSIS); size = gfunc_arg_size(&func_vt); if (size > 8) { gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); -- cgit v1.3.1 From 3fe2a95d7fe854c8cf496a009a467bb65cdf030d Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 7 Jan 2014 14:57:07 +0100 Subject: be stricter with aliasing Refactoring (no logical changes): - use memcpy in tccgen.c:ieee_finite(double d) - use union to store attribute flags in Sym Makefile: "CFLAGS+=-fno-strict-aliasing" basically not necessary anymore but I left it for now because gcc sometimes behaves unexpectedly without. Also: - configure: back to mode 100755 - tcc.h: remove unused variables tdata/tbss_section - x86_64-gen.c: adjust gfunc_sret for prototype --- configure | 0 i386-gen.c | 4 +-- libtcc.c | 8 ++--- tcc.h | 57 ++++++++++++++++------------------- tccgen.c | 97 +++++++++++++++++++++++++++++++----------------------------- x86_64-gen.c | 15 ++++++---- 6 files changed, 92 insertions(+), 89 deletions(-) mode change 100644 => 100755 configure (limited to 'x86_64-gen.c') diff --git a/configure b/configure old mode 100644 new mode 100755 diff --git a/i386-gen.c b/i386-gen.c index 4c4a54b..ece054b 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -457,7 +457,7 @@ ST_FUNC void gfunc_call(int nb_args) } save_regs(0); /* save used temporary registers */ func_sym = vtop->type.ref; - func_call = FUNC_CALL(func_sym->r); + func_call = func_sym->a.func_call; /* fast call case */ if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || func_call == FUNC_FASTCALLW) { @@ -505,7 +505,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) CType *type; sym = func_type->ref; - func_call = FUNC_CALL(sym->r); + func_call = sym->a.func_call; addr = 8; loc = 0; func_vc = 0; diff --git a/libtcc.c b/libtcc.c index 072b77f..154a266 100644 --- a/libtcc.c +++ b/libtcc.c @@ -493,11 +493,11 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section, if (sym->type.t & VT_EXPORT) other |= 1; if (sym_type == STT_FUNC && sym->type.ref) { - int attr = sym->type.ref->r; - if (FUNC_EXPORT(attr)) + Sym *ref = sym->type.ref; + if (ref->a.func_export) other |= 1; - if (FUNC_CALL(attr) == FUNC_STDCALL && can_add_underscore) { - sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr) * PTR_SIZE); + if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { + sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); name = buf1; other |= 2; can_add_underscore = 0; diff --git a/tcc.h b/tcc.h index 0933b01..f3d868f 100644 --- a/tcc.h +++ b/tcc.h @@ -326,11 +326,35 @@ typedef struct SValue { struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ } SValue; +struct Attribute { + unsigned + func_call : 3, /* calling convention (0..5), see below */ + aligned : 5, /* alignement (0..16) */ + packed : 1, + func_export : 1, + func_import : 1, + func_args : 5, + func_proto : 1, + mode : 4, + weak : 1, + fill : 10; // 10 bits left to fit well in union below +}; + +/* GNUC attribute definition */ +typedef struct AttributeDef { + struct Attribute a; + struct Section *section; + int alias_target; /* token */ +} AttributeDef; + /* symbol management */ typedef struct Sym { int v; /* symbol token */ char *asm_label; /* associated asm label */ - long r; /* associated register */ + union { + long r; /* associated register */ + struct Attribute a; + }; union { long c; /* associated number */ int *d; /* define token stream */ @@ -381,34 +405,6 @@ typedef struct DLLReference { char name[1]; } DLLReference; -/* GNUC attribute definition */ -typedef struct AttributeDef { - unsigned - func_call : 3, /* calling convention (0..5), see below */ - aligned : 5, /* alignement (0..16) */ - packed : 1, - func_export : 1, - func_import : 1, - func_args : 5, - func_proto : 1, - mode : 4, - weak : 1, - fill : 10; - struct Section *section; - int alias_target; /* token */ -} AttributeDef; - -/* gr: wrappers for casting sym->r for other purposes */ -#define FUNC_CALL(r) (((AttributeDef*)&(r))->func_call) -#define FUNC_EXPORT(r) (((AttributeDef*)&(r))->func_export) -#define FUNC_IMPORT(r) (((AttributeDef*)&(r))->func_import) -#define FUNC_ARGS(r) (((AttributeDef*)&(r))->func_args) -#define FUNC_PROTO(r) (((AttributeDef*)&(r))->func_proto) -#define FUNC_ALIGN(r) (((AttributeDef*)&(r))->aligned) -#define FUNC_PACKED(r) (((AttributeDef*)&(r))->packed) -#define ATTR_MODE(r) (((AttributeDef*)&(r))->mode) -#define INT_ATTR(ad) (*(int*)(ad)) - /* -------------------------------------------------- */ #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */ @@ -1142,7 +1138,6 @@ ST_FUNC void expect(const char *msg); /* ------------ tccgen.c ------------ */ ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */ -ST_DATA Section *tdata_section, *tbss_section; /* thread-local storage sections */ ST_DATA Section *cur_text_section; /* current section where function code is generated */ #ifdef CONFIG_TCC_ASM ST_DATA Section *last_text_section; /* to handle .previous asm directive */ @@ -1268,7 +1263,7 @@ ST_FUNC void build_got_entries(TCCState *s1); ST_FUNC void tcc_add_runtime(TCCState *s1); ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err); -#ifdef TCC_IS_NATIVE +#if defined TCC_IS_NATIVE || defined TCC_TARGET_PE ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #endif diff --git a/tccgen.c b/tccgen.c index f23cd07..7a675cc 100644 --- a/tccgen.c +++ b/tccgen.c @@ -103,7 +103,8 @@ ST_INLN int is_float(int t) /* XXX: endianness dependent */ ST_FUNC int ieee_finite(double d) { - int *p = (int *)&d; + int p[4]; + memcpy(p, &d, sizeof(double)); return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31; } @@ -2172,7 +2173,7 @@ static int is_compatible_func(CType *type1, CType *type2) if (!is_compatible_types(&s1->type, &s2->type)) return 0; /* check func_call */ - if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r)) + if (s1->a.func_call != s2->a.func_call) return 0; /* XXX: not complete */ if (s1->c == FUNC_OLD || s2->c == FUNC_OLD) @@ -2659,15 +2660,15 @@ static void parse_attribute(AttributeDef *ad) } else { n = MAX_ALIGN; } - ad->aligned = n; + ad->a.aligned = n; break; case TOK_PACKED1: case TOK_PACKED2: - ad->packed = 1; + ad->a.packed = 1; break; case TOK_WEAK1: case TOK_WEAK2: - ad->weak = 1; + ad->a.weak = 1; break; case TOK_UNUSED1: case TOK_UNUSED2: @@ -2682,12 +2683,12 @@ static void parse_attribute(AttributeDef *ad) case TOK_CDECL1: case TOK_CDECL2: case TOK_CDECL3: - ad->func_call = FUNC_CDECL; + ad->a.func_call = FUNC_CDECL; break; case TOK_STDCALL1: case TOK_STDCALL2: case TOK_STDCALL3: - ad->func_call = FUNC_STDCALL; + ad->a.func_call = FUNC_STDCALL; break; #ifdef TCC_TARGET_I386 case TOK_REGPARM1: @@ -2699,26 +2700,26 @@ static void parse_attribute(AttributeDef *ad) else if (n < 0) n = 0; if (n > 0) - ad->func_call = FUNC_FASTCALL1 + n - 1; + ad->a.func_call = FUNC_FASTCALL1 + n - 1; skip(')'); break; case TOK_FASTCALL1: case TOK_FASTCALL2: case TOK_FASTCALL3: - ad->func_call = FUNC_FASTCALLW; + ad->a.func_call = FUNC_FASTCALLW; break; #endif case TOK_MODE: skip('('); switch(tok) { case TOK_MODE_DI: - ad->mode = VT_LLONG + 1; + ad->a.mode = VT_LLONG + 1; break; case TOK_MODE_HI: - ad->mode = VT_SHORT + 1; + ad->a.mode = VT_SHORT + 1; break; case TOK_MODE_SI: - ad->mode = VT_INT + 1; + ad->a.mode = VT_INT + 1; break; default: tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL)); @@ -2728,10 +2729,10 @@ static void parse_attribute(AttributeDef *ad) skip(')'); break; case TOK_DLLEXPORT: - ad->func_export = 1; + ad->a.func_export = 1; break; case TOK_DLLIMPORT: - ad->func_import = 1; + ad->a.func_import = 1; break; default: if (tcc_state->warn_unsupported) @@ -2873,10 +2874,10 @@ static void struct_decl(CType *type, int u, int tdef) get_tok_str(v, NULL)); } size = type_size(&type1, &align); - if (ad.aligned) { - if (align < ad.aligned) - align = ad.aligned; - } else if (ad.packed) { + if (ad.a.aligned) { + if (align < ad.a.aligned) + align = ad.a.aligned; + } else if (ad.a.packed) { align = 1; } else if (*tcc_state->pack_stack_ptr) { if (align > *tcc_state->pack_stack_ptr) @@ -3118,8 +3119,8 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE2: parse_attribute(ad); - if (ad->mode) { - u = ad->mode -1; + if (ad->a.mode) { + u = ad->a.mode -1; t = (t & ~VT_BTYPE) | u; } break; @@ -3143,11 +3144,11 @@ static int parse_btype(CType *type, AttributeDef *ad) type->ref = s->type.ref; if (s->r) { /* get attributes from typedef */ - if (0 == ad->aligned) - ad->aligned = FUNC_ALIGN(s->r); - if (0 == ad->func_call) - ad->func_call = FUNC_CALL(s->r); - ad->packed |= FUNC_PACKED(s->r); + if (0 == ad->a.aligned) + ad->a.aligned = s->a.aligned; + if (0 == ad->a.func_call) + ad->a.func_call = s->a.func_call; + ad->a.packed |= s->a.packed; } next(); typespec_found = 1; @@ -3287,8 +3288,9 @@ static void post_type(CType *type, AttributeDef *ad) type->t |= VT_PTR; } /* we push a anonymous symbol which will contain the function prototype */ - ad->func_args = arg_size; - s = sym_push(SYM_FIELD, type, INT_ATTR(ad), l); + ad->a.func_args = arg_size; + s = sym_push(SYM_FIELD, type, 0, l); + s->a = ad->a; s->next = first; type->t = VT_FUNC; type->ref = s; @@ -5484,10 +5486,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (flexible_array) size += flexible_array->type.ref->c * pointed_size(&flexible_array->type); /* take into account specified alignment if bigger */ - if (ad->aligned) { - if (ad->aligned > align) - align = ad->aligned; - } else if (ad->packed) { + if (ad->a.aligned) { + if (ad->a.aligned > align) + align = ad->a.aligned; + } else if (ad->a.packed) { align = 1; } if ((r & VT_VALMASK) == VT_LOCAL) { @@ -5869,12 +5871,12 @@ static int decl0(int l, int is_for_loop_init) parse_attribute(&ad); } - if (ad.weak) + if (ad.a.weak) type.t |= VT_WEAK; #ifdef TCC_TARGET_PE - if (ad.func_import) + if (ad.a.func_import) type.t |= VT_IMPORT; - if (ad.func_export) + if (ad.a.func_export) type.t |= VT_EXPORT; #endif if (tok == '{') { @@ -5895,22 +5897,22 @@ static int decl0(int l, int is_for_loop_init) sym = sym_find(v); if (sym) { + Sym *ref; if ((sym->type.t & VT_BTYPE) != VT_FUNC) goto func_error1; - r = sym->type.ref->r; - - if (!FUNC_PROTO(r)) + ref = sym->type.ref; + if (0 == ref->a.func_proto) tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); /* use func_call from prototype if not defined */ - if (FUNC_CALL(r) != FUNC_CDECL - && FUNC_CALL(type.ref->r) == FUNC_CDECL) - FUNC_CALL(type.ref->r) = FUNC_CALL(r); + if (ref->a.func_call != FUNC_CDECL + && type.ref->a.func_call == FUNC_CDECL) + type.ref->a.func_call = ref->a.func_call; /* use export from prototype */ - if (FUNC_EXPORT(r)) - FUNC_EXPORT(type.ref->r) = 1; + if (ref->a.func_export) + type.ref->a.func_export = 1; /* use static from prototype */ if (sym->type.t & VT_STATIC) @@ -5921,7 +5923,7 @@ static int decl0(int l, int is_for_loop_init) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } - FUNC_PROTO(type.ref->r) = 0; + type.ref->a.func_proto = 0; /* if symbol is already defined, then put complete type */ sym->type = type; } else { @@ -5980,15 +5982,16 @@ static int decl0(int l, int is_for_loop_init) if (btype.t & VT_TYPEDEF) { /* save typedefed type */ /* XXX: test storage specifiers ? */ - sym = sym_push(v, &type, INT_ATTR(&ad), 0); + sym = sym_push(v, &type, 0, 0); + sym->a = ad.a; sym->type.t |= VT_TYPEDEF; } else { r = 0; if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ /* specific case for func_call attribute */ - ad.func_proto = 1; - type.ref->r = INT_ATTR(&ad); + ad.a.func_proto = 1; + type.ref->a = ad.a; } else if (!(type.t & VT_ARRAY)) { /* not lvalue if array */ r |= lvalue_type(type.t); @@ -6039,7 +6042,7 @@ static int decl0(int l, int is_for_loop_init) } next(); } - ad.aligned = 0; + ad.a.aligned = 0; } } return 0; diff --git a/x86_64-gen.c b/x86_64-gen.c index 9aee875..9acca3c 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -933,7 +933,8 @@ typedef enum X86_64_Mode { x86_64_mode_x87 } X86_64_Mode; -static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { +static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) +{ if (a == b) return a; else if (a == x86_64_mode_none) @@ -950,7 +951,8 @@ static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b) { return x86_64_mode_sse; } -static X86_64_Mode classify_x86_64_inner(CType *ty) { +static X86_64_Mode classify_x86_64_inner(CType *ty) +{ X86_64_Mode mode; Sym *f; @@ -988,7 +990,8 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) { assert(0); } -static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) { +static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count) +{ X86_64_Mode mode; int size, align, ret_t = 0; @@ -1045,7 +1048,8 @@ static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *p return mode; } -ST_FUNC int classify_x86_64_va_arg(CType *ty) { +ST_FUNC int classify_x86_64_va_arg(CType *ty) +{ /* This definition must be synced with stdarg.h */ enum __va_arg_type { __va_gen_reg, __va_float_reg, __va_stack @@ -1061,7 +1065,8 @@ ST_FUNC int classify_x86_64_va_arg(CType *ty) { /* Return the number of registers needed to return the struct, or 0 if returning via struct pointer. */ -int gfunc_sret(CType *vt, CType *ret, int *ret_align) { +ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align) +{ int size, align, reg_count; *ret_align = 1; // Never have to re-align return values for x86-64 return (classify_x86_64_arg(vt, ret, &size, &align, ®_count) != x86_64_mode_memory); -- cgit v1.3.1 From d0dae7f2416574bd61df51e6389c2224c685ded9 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Fri, 7 Feb 2014 22:31:44 +0800 Subject: Ignore VT_DEFSIGN in load on x86-64 arch This fixes commit b0b5165d1668373c5d7b7933da599426f33e723b for x86-64 targets. --- x86_64-gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 9acca3c..407bd96 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -366,7 +366,7 @@ void load(int r, SValue *sv) #endif fr = sv->r; - ft = sv->type.t; + ft = sv->type.t & ~VT_DEFSIGN; fc = sv->c.ul; #ifndef TCC_TARGET_PE -- cgit v1.3.1 From fdb3b10d0693cf33ce5a0acf17f0f323d79ee5f1 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 8 Mar 2014 18:36:02 +0800 Subject: Fix various errors uncovered by static analysis Reported-by: Carlos Montiers --- c67-gen.c | 2 -- tccgen.c | 1 - tccpp.c | 2 +- x86_64-gen.c | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) (limited to 'x86_64-gen.c') diff --git a/c67-gen.c b/c67-gen.c index f2baea5..6d9068a 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1901,8 +1901,6 @@ void gfunc_call(int nb_args) for (i = 0; i < nb_args; i++) { if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { ALWAYS_ASSERT(FALSE); - } else if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) { - ALWAYS_ASSERT(FALSE); } else { /* simple type (currently always same size) */ /* XXX: implicit cast ? */ diff --git a/tccgen.c b/tccgen.c index 2f5b366..d8e4614 100644 --- a/tccgen.c +++ b/tccgen.c @@ -162,7 +162,6 @@ ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) tcc_error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); } - s = *ps; s = sym_malloc(); s->asm_label = NULL; s->v = v; diff --git a/tccpp.c b/tccpp.c index e1ccded..b12b120 100644 --- a/tccpp.c +++ b/tccpp.c @@ -276,7 +276,7 @@ ST_FUNC char *get_tok_str(int v, CValue *cv) #ifdef _WIN32 sprintf(p, "%u", (unsigned)cv->ull); #else - sprintf(p, "%Lu", cv->ull); + sprintf(p, "%llu", cv->ull); #endif break; case TOK_LCHAR: diff --git a/x86_64-gen.c b/x86_64-gen.c index 407bd96..fc4178e 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -501,7 +501,7 @@ void load(int r, SValue *sv) o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8); } } else if (r == TREG_ST0) { - assert((v >= TREG_XMM0) || (v <= TREG_XMM7)); + assert((v >= TREG_XMM0) && (v <= TREG_XMM7)); /* gen_cvt_ftof(VT_LDOUBLE); */ /* movsd %xmmN,-0x10(%rsp) */ o(0x110ff2); -- cgit v1.3.1 From 080ad7e62acdf6ccd47927a4c289ff2ae21e83df Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 31 Mar 2014 03:45:35 +0200 Subject: x86-64: Add basic shared lib support Initial support for shared libraries on x86-64. --- tccelf.c | 76 ++++++++++++++++++++++++++++++++---------------------------- x86_64-gen.c | 2 +- 2 files changed, 41 insertions(+), 37 deletions(-) (limited to 'x86_64-gen.c') diff --git a/tccelf.c b/tccelf.c index 932cf03..38d3e3e 100644 --- a/tccelf.c +++ b/tccelf.c @@ -802,9 +802,18 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s) #elif defined(TCC_TARGET_X86_64) case R_X86_64_64: if (s1->output_type == TCC_OUTPUT_DLL) { - qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); - qrel->r_addend = *(long long *)ptr + val; - qrel++; + esym_index = s1->symtab_to_dynsym[sym_index]; + qrel->r_offset = rel->r_offset; + if (esym_index) { + qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); + qrel->r_addend = rel->r_addend; + qrel++; + break; + } else { + qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); + qrel->r_addend = *(long long *)ptr + val; + qrel++; + } } *(long long *)ptr += val; break; @@ -1013,6 +1022,7 @@ static void put_got_entry(TCCState *s1, ElfW(Sym) *sym; unsigned long offset; int *ptr; + struct sym_attr *symattr; if (!s1->got) build_got(s1); @@ -1037,7 +1047,10 @@ static void put_got_entry(TCCState *s1, got_entry_present = 1; } - alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset; + symattr = alloc_sym_attr(s1, sym_index); + /* Only store the GOT offset if it's not generated for the PLT entry. */ + if (!need_plt_entry) + symattr->got_offset = s1->got->data_offset; if (s1->dynsym) { sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; @@ -1048,6 +1061,7 @@ static void put_got_entry(TCCState *s1, Section *plt; uint8_t *p; int modrm; + unsigned long relofs; #if defined(TCC_OUTPUT_DLL_WITH_PLT) modrm = 0x25; @@ -1072,12 +1086,21 @@ static void put_got_entry(TCCState *s1, put32(p + 8, PTR_SIZE * 2); } + /* The PLT slot refers to the relocation entry it needs + via offset. The reloc entry is created below, so its + offset is the current data_offset. */ + relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; p = section_ptr_add(plt, 16); p[0] = 0xff; /* jmp *(got + x) */ p[1] = modrm; put32(p + 2, s1->got->data_offset); p[6] = 0x68; /* push $xxx */ - put32(p + 7, (plt->data_offset - 32) >> 1); +#ifdef TCC_TARGET_X86_64 + /* On x86-64, the relocation is referred to by _index_. */ + put32(p + 7, relofs / sizeof (ElfW_Rel)); +#else + put32(p + 7, relofs); +#endif p[11] = 0xe9; /* jmp plt_start */ put32(p + 12, -(plt->data_offset)); @@ -1087,7 +1110,7 @@ static void put_got_entry(TCCState *s1, if (s1->output_type == TCC_OUTPUT_EXE) #endif offset = plt->data_offset - 16; - s1->sym_attrs[sym_index].has_plt_entry = 1; + symattr->has_plt_entry = 1; } #elif defined(TCC_TARGET_ARM) if (need_plt_entry) { @@ -1109,7 +1132,7 @@ static void put_got_entry(TCCState *s1, put32(p+12, 0xe5bef008); /* ldr pc, [lr, #8]! */ } - if (s1->sym_attrs[sym_index].plt_thumb_stub) { + if (symattr->plt_thumb_stub) { p = section_ptr_add(plt, 20); put32(p, 0x4778); /* bx pc */ put32(p+2, 0x46c0); /* nop */ @@ -1125,27 +1148,23 @@ static void put_got_entry(TCCState *s1, the PLT */ if (s1->output_type == TCC_OUTPUT_EXE) offset = plt->data_offset - 16; - s1->sym_attrs[sym_index].has_plt_entry = 1; + symattr->has_plt_entry = 1; } #elif defined(TCC_TARGET_C67) tcc_error("C67 got not implemented"); #else #error unsupported CPU #endif + /* XXX This might generate multiple syms for name. */ index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, name); - if (got_entry_present) { - put_elf_reloc(s1->dynsym, s1->got, - s1->sym_attrs[sym_index].got_offset, - reloc_type, index); - return; - } - - /* put a got entry */ + /* Create the relocation (it's against the GOT for PLT + and GOT relocs). */ put_elf_reloc(s1->dynsym, s1->got, s1->got->data_offset, reloc_type, index); } + /* And now create the GOT slot itself. */ ptr = section_ptr_add(s1->got, PTR_SIZE); *ptr = 0; } @@ -1697,26 +1716,11 @@ static void export_global_syms(TCCState *s1) s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { -#if defined(TCC_OUTPUT_DLL_WITH_PLT) - int type = ELFW(ST_TYPE)(sym->st_info); - if ((type == STT_FUNC || type == STT_GNU_IFUNC) - && sym->st_shndx == SHN_UNDEF) { - int visibility = ELFW(ST_BIND)(sym->st_info); - put_got_entry(s1, R_JMP_SLOT, sym->st_size, - ELFW(ST_INFO)(visibility, STT_FUNC), - sym - (ElfW(Sym) *) symtab_section->data); - } else if (type == STT_OBJECT) { - put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, sym->st_info, - sym - (ElfW(Sym) *) symtab_section->data); - } else -#endif - { - name = (char *) symtab_section->link->data + sym->st_name; - dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, - sym->st_info, 0, sym->st_shndx, name); - index = sym - (ElfW(Sym) *) symtab_section->data; - s1->symtab_to_dynsym[index] = dynindex; - } + name = (char *) symtab_section->link->data + sym->st_name; + dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, + sym->st_info, 0, sym->st_shndx, name); + index = sym - (ElfW(Sym) *) symtab_section->data; + s1->symtab_to_dynsym[index] = dynindex; } } } diff --git a/x86_64-gen.c b/x86_64-gen.c index fc4178e..9a9221d 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -604,7 +604,7 @@ static void gcall_or_jmp(int is_jmp) if (vtop->r & VT_SYM) { /* relocation case */ greloc(cur_text_section, vtop->sym, - ind + 1, R_X86_64_PC32); + ind + 1, R_X86_64_PLT32); } else { /* put an empty PC32 relocation */ put_elf_reloc(symtab_section, cur_text_section, -- cgit v1.3.1 From a913ee6082af6257416bce04e0e5c87894d6bff3 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Thu, 3 Apr 2014 17:59:41 +0200 Subject: x86-64: Use correct ELF values The x86-64 uses different segment alignment (2MB) and a different start address. --- x86_64-gen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 9a9221d..eb201c8 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -112,8 +112,8 @@ enum { #define R_JMP_SLOT R_X86_64_JUMP_SLOT #define R_COPY R_X86_64_COPY -#define ELF_START_ADDR 0x08048000 -#define ELF_PAGE_SIZE 0x1000 +#define ELF_START_ADDR 0x400000 +#define ELF_PAGE_SIZE 0x200000 /******************************************************/ #else /* ! TARGET_DEFS_ONLY */ -- cgit v1.3.1 From 89f7aea98093b035dd74cfbdd3de41c46ad12b6e Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Mon, 28 Apr 2014 14:05:55 +0800 Subject: fix abitest.c for x86_64 bug --- tests/abitest.c | 2 -- x86_64-gen.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'x86_64-gen.c') diff --git a/tests/abitest.c b/tests/abitest.c index 488de1e..3ad707a 100644 --- a/tests/abitest.c +++ b/tests/abitest.c @@ -138,8 +138,6 @@ static int ret_longdouble_test_callback2(void *ptr) { ret_longdouble_test_type a = {10}; ret_longdouble_test_type r; r = f(a); - printf("%Lf \n", a.x); - printf("%Lf \n", r.x); return ((r.x == a.x*5) && (f(a).x == a.x*5)) ? 0 : -1; } diff --git a/x86_64-gen.c b/x86_64-gen.c index eb201c8..12893a3 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -981,7 +981,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) return x86_64_mode_memory; mode = x86_64_mode_none; - for (; f; f = f->next) + for (f = f->next; f; f = f->next) mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type)); return mode; -- cgit v1.3.1 From e20c1eb99e1003c1e59522c136dbb15c52d7cc7c Mon Sep 17 00:00:00 2001 From: jiang <30155751@qq.com> Date: Mon, 28 Apr 2014 19:43:02 +0800 Subject: fix test3 for x86_64-gen.c --- x86_64-gen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'x86_64-gen.c') diff --git a/x86_64-gen.c b/x86_64-gen.c index 12893a3..ae65328 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -1272,7 +1272,7 @@ void gfunc_call(int nb_args) g(0x00); args_size += size; } else { - assert(mode == x86_64_mode_memory); + //assert(mode == x86_64_mode_memory); /* allocate the necessary size on stack */ o(0x48); -- cgit v1.3.1