refactor sym & attributes

tcc.h:
* cleanup struct 'Sym'
* include some 'Attributes' into 'Sym'
* in turn get rid of VT_IM/EXPORT, VT_WEAK
* re-number VT_XXX flags
* replace some 'long' function args by 'int'

tccgen.c:
* refactor parse_btype()
master
grischka 2017-07-09 12:34:11 +02:00
parent 9f79b62ec4
commit 9ba76ac834
9 changed files with 286 additions and 291 deletions

View File

@ -1221,7 +1221,7 @@ void gfunc_call(int nb_args)
int variadic; int variadic;
if (float_abi == ARM_HARD_FLOAT) { if (float_abi == ARM_HARD_FLOAT) {
variadic = (vtop[-nb_args].type.ref->c == FUNC_ELLIPSIS); variadic = (vtop[-nb_args].type.ref->f.func_type == FUNC_ELLIPSIS);
if (variadic || floats_in_core_regs(&vtop[-nb_args])) if (variadic || floats_in_core_regs(&vtop[-nb_args]))
float_abi = ARM_SOFTFP_FLOAT; float_abi = ARM_SOFTFP_FLOAT;
} }
@ -1279,7 +1279,7 @@ void gfunc_prolog(CType *func_type)
sym = func_type->ref; sym = func_type->ref;
func_vt = sym->type; func_vt = sym->type;
func_var = (func_type->ref->c == FUNC_ELLIPSIS); func_var = (func_type->ref->f.func_type == FUNC_ELLIPSIS);
n = nf = 0; n = nf = 0;
if ((func_vt.t & VT_BTYPE) == VT_STRUCT && if ((func_vt.t & VT_BTYPE) == VT_STRUCT &&

View File

@ -428,7 +428,7 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend)
// relocation and use only relocations with unlimited range. // relocation and use only relocations with unlimited range.
int avoid_adrp = 1; int avoid_adrp = 1;
if (avoid_adrp || (sym->type.t & VT_WEAK)) { if (avoid_adrp || sym->a.weak) {
// (GCC uses a R_AARCH64_ABS64 in this case.) // (GCC uses a R_AARCH64_ABS64 in this case.)
greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend); greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend);
o(0xd2800000 | r); // mov x(rt),#0,lsl #0 o(0xd2800000 | r); // mov x(rt),#0,lsl #0

View File

@ -1951,12 +1951,12 @@ void gfunc_prolog(CType * func_type)
CType *type; CType *type;
sym = func_type->ref; sym = func_type->ref;
func_call = sym->r; func_call = sym->f.func_call;
addr = 8; addr = 8;
/* if the function returns a structure, then add an /* if the function returns a structure, then add an
implicit pointer parameter */ implicit pointer parameter */
func_vt = sym->type; func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS); func_var = (sym->f.func_type == FUNC_ELLIPSIS);
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
func_vc = addr; func_vc = addr;
addr += 4; addr += 4;

View File

@ -161,14 +161,14 @@ static int oad(int c, int s)
#define gjmp2(instr,lbl) oad(instr,lbl) #define gjmp2(instr,lbl) oad(instr,lbl)
/* output constant with relocation if 'r & VT_SYM' is true */ /* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addr32(int r, Sym *sym, long c) ST_FUNC void gen_addr32(int r, Sym *sym, int c)
{ {
if (r & VT_SYM) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_32); greloc(cur_text_section, sym, ind, R_386_32);
gen_le32(c); gen_le32(c);
} }
ST_FUNC void gen_addrpc32(int r, Sym *sym, long c) ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
{ {
if (r & VT_SYM) if (r & VT_SYM)
greloc(cur_text_section, sym, ind, R_386_PC32); greloc(cur_text_section, sym, ind, R_386_PC32);
@ -477,7 +477,7 @@ ST_FUNC void gfunc_call(int nb_args)
} }
save_regs(0); /* save used temporary registers */ save_regs(0); /* save used temporary registers */
func_sym = vtop->type.ref; func_sym = vtop->type.ref;
func_call = func_sym->a.func_call; func_call = func_sym->f.func_call;
/* fast call case */ /* fast call case */
if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
func_call == FUNC_FASTCALLW) { func_call == FUNC_FASTCALLW) {
@ -525,7 +525,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
CType *type; CType *type;
sym = func_type->ref; sym = func_type->ref;
func_call = sym->a.func_call; func_call = sym->f.func_call;
addr = 8; addr = 8;
loc = 0; loc = 0;
func_vc = 0; func_vc = 0;
@ -547,7 +547,7 @@ ST_FUNC void gfunc_prolog(CType *func_type)
/* if the function returns a structure, then add an /* if the function returns a structure, then add an
implicit pointer parameter */ implicit pointer parameter */
func_vt = sym->type; func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS); func_var = (sym->f.func_type == FUNC_ELLIPSIS);
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
size = type_size(&func_vt,&align); size = type_size(&func_vt,&align);
if (((func_vt.t & VT_BTYPE) == VT_STRUCT) if (((func_vt.t & VT_BTYPE) == VT_STRUCT)

149
tcc.h
View File

@ -407,49 +407,59 @@ typedef struct SValue {
result of unary() for an identifier. */ result of unary() for an identifier. */
} SValue; } SValue;
struct Attribute { /* symbol attributes */
struct SymAttr {
unsigned short
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
packed : 1,
weak : 1,
visibility : 2,
dllexport : 1,
dllimport : 1,
unsigned_enum : 1,
unused : 4;
};
/* function attributes or temporary attributes for parsing */
struct FuncAttr {
unsigned unsigned
func_call : 3, /* calling convention (0..5), see below */ func_call : 3, /* calling convention (0..5), see below */
aligned : 5, /* alignment as log2+1 (0 == unspecified) */ func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
packed : 1, func_body : 1, /* body was defined */
func_export : 1, func_args : 8; /* PE __stdcall args */
func_import : 1,
func_args : 5,
func_body : 1,
mode : 4,
weak : 1,
visibility : 2,
unsigned_enum : 1,
fill : 7; // 7 bits left to fit well in union below
}; };
/* GNUC attribute definition */ /* GNUC attribute definition */
typedef struct AttributeDef { typedef struct AttributeDef {
struct Attribute a; struct SymAttr a;
struct FuncAttr f;
struct Section *section; struct Section *section;
int alias_target; /* token */ int alias_target; /* token */
int asm_label; /* associated asm label */ int asm_label; /* associated asm label */
char attr_mode; /* __attribute__((__mode__(...))) */
} AttributeDef; } AttributeDef;
/* symbol management */ /* symbol management */
typedef struct Sym { typedef struct Sym {
int v; /* symbol token */ int v; /* symbol token */
unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
struct SymAttr a; /* symbol attributes */
union { union {
int asm_label; /* associated asm label */ struct {
int scope; /* scope level for locals */ int c; /* associated number or Elf symbol index */
union {
int sym_scope; /* scope level for locals */
int jnext; /* next jump label */
struct FuncAttr f; /* function attributes */
};
};
long long enum_val; /* enum constant if IS_ENUM_VAL */
int *d; /* define token stream */
}; };
union { CType type; /* associated type */
long r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
struct Attribute a;
};
union {
long c; /* associated number */
int *d; /* define token stream */
};
CType type; /* associated type */
union { union {
struct Sym *next; /* next related symbol (for fields and anoms) */ struct Sym *next; /* next related symbol (for fields and anoms) */
long jnext; /* next jump label */ int asm_label; /* associated asm label */
}; };
struct Sym *prev; /* prev symbol in stack */ struct Sym *prev; /* prev symbol in stack */
struct Sym *prev_tok; /* previous symbol for this token */ struct Sym *prev_tok; /* previous symbol for this token */
@ -498,12 +508,12 @@ typedef struct DLLReference {
#define SYM_FIELD 0x20000000 /* struct/union field symbol space */ #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */ #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
/* stored in 'Sym.c' field */ /* stored in 'Sym->f.func_type' field */
#define FUNC_NEW 1 /* ansi function prototype */ #define FUNC_NEW 1 /* ansi function prototype */
#define FUNC_OLD 2 /* old function prototype */ #define FUNC_OLD 2 /* old function prototype */
#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */ #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
/* stored in 'Sym.r' field */ /* stored in 'Sym->f.func_call' field */
#define FUNC_CDECL 0 /* standard c call */ #define FUNC_CDECL 0 /* standard c call */
#define FUNC_STDCALL 1 /* pascal c call */ #define FUNC_STDCALL 1 /* pascal c call */
#define FUNC_FASTCALL1 2 /* first param in %eax */ #define FUNC_FASTCALL1 2 /* first param in %eax */
@ -834,53 +844,48 @@ struct filespec {
/* types */ /* types */
#define VT_BTYPE 0x000f /* mask for basic type */ #define VT_BTYPE 0x000f /* mask for basic type */
#define VT_INT 0 /* integer type */ #define VT_VOID 0 /* void type */
#define VT_BYTE 1 /* signed byte type */ #define VT_BYTE 1 /* signed byte type */
#define VT_SHORT 2 /* short type */ #define VT_SHORT 2 /* short type */
#define VT_VOID 3 /* void type */ #define VT_INT 3 /* integer type */
#define VT_PTR 4 /* pointer */ #define VT_LLONG 4 /* 64 bit integer */
#define VT_ENUM 5 /* enum definition */ #define VT_PTR 5 /* pointer */
#define VT_FUNC 6 /* function type */ #define VT_FUNC 6 /* function type */
#define VT_STRUCT 7 /* struct/union definition */ #define VT_STRUCT 7 /* struct/union definition */
#define VT_FLOAT 8 /* IEEE float */ #define VT_ENUM 8 /* enum definition */
#define VT_DOUBLE 9 /* IEEE double */ #define VT_FLOAT 9 /* IEEE float */
#define VT_LDOUBLE 10 /* IEEE long double */ #define VT_DOUBLE 10 /* IEEE double */
#define VT_BOOL 11 /* ISOC99 boolean type */ #define VT_LDOUBLE 11 /* IEEE long double */
#define VT_LLONG 12 /* 64 bit integer */ #define VT_BOOL 12 /* ISOC99 boolean type */
#define VT_LONG 13 /* long integer (NEVER USED as type, only #define VT_LONG 13 /* long integer (NEVER USED as type, only during parsing) */
during parsing) */
#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */ #define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */
#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */ #define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */
#define VT_UNSIGNED 0x0010 /* unsigned type */ #define VT_UNSIGNED 0x0010 /* unsigned type */
#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ #define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
#define VT_BITFIELD 0x0040 /* bitfield modifier */ #define VT_ARRAY 0x0040 /* array type (also has VT_PTR) */
#define VT_CONSTANT 0x0800 /* const modifier */ #define VT_BITFIELD 0x0080 /* bitfield modifier */
#define VT_VOLATILE 0x1000 /* volatile modifier */ #define VT_CONSTANT 0x0100 /* const modifier */
#define VT_DEFSIGN 0x2000 /* signed type */ #define VT_VOLATILE 0x0200 /* volatile modifier */
#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ #define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
#define VT_UNION (VT_STRUCT|VT_UNSIGNED) /* VT_STRUCT type with some modifier */
/* storage */ /* storage */
#define VT_EXTERN 0x00000080 /* extern definition */ #define VT_EXTERN 0x00001000 /* extern definition */
#define VT_STATIC 0x00000100 /* static variable */ #define VT_STATIC 0x00002000 /* static variable */
#define VT_TYPEDEF 0x00000200 /* typedef definition */ #define VT_TYPEDEF 0x00004000 /* typedef definition */
#define VT_INLINE 0x00000400 /* inline definition */ #define VT_INLINE 0x00008000 /* inline definition */
#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ /* currently unused: 0x0800, 0x000[1248]0000 */
#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
#define VT_WEAK 0x00010000 /* weak symbol */
#define VT_TLS 0x00040000 /* thread-local storage */
#define VT_VIS_SHIFT 19 /* shift for symbol visibility, overlapping
bitfield values, because bitfields never
have linkage and hence never have
visibility. */
#define VT_VIS_SIZE 2 /* We have four visibilities. */
#define VT_VIS_MASK (((1 << VT_VIS_SIZE)-1) << VT_VIS_SHIFT)
#define VT_STRUCT_SHIFT 19 /* shift for bitfield shift values (max: 32 - 2*6) */
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
#define VT_STRUCT_MASK (((1 << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
/* type mask (except storage) */ /* type mask (except storage) */
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK | VT_VIS_MASK) #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_STRUCT_MASK)
#define VT_TYPE (~(VT_STORAGE)) #define VT_TYPE (~VT_STORAGE)
/* token values */ /* token values */
@ -1117,13 +1122,13 @@ ST_FUNC void cstr_free(CString *cstr);
ST_FUNC void cstr_reset(CString *cstr); ST_FUNC void cstr_reset(CString *cstr);
ST_INLN void sym_free(Sym *sym); ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c); ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
ST_FUNC Sym *sym_find2(Sym *s, int v); ST_FUNC Sym *sym_find2(Sym *s, int v);
ST_FUNC Sym *sym_push(int v, CType *type, int r, long c); ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep); ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_INLN Sym *struct_find(int v); ST_INLN Sym *struct_find(int v);
ST_INLN Sym *sym_find(int v); ST_INLN Sym *sym_find(int v);
ST_FUNC Sym *global_identifier_push(int v, int t, long c); ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen); ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *s1, const char *filename); ST_FUNC int tcc_open(TCCState *s1, const char *filename);
@ -1296,7 +1301,7 @@ ST_FUNC int ieee_finite(double d);
ST_FUNC void test_lvalue(void); ST_FUNC void test_lvalue(void);
ST_FUNC void vpushi(int v); ST_FUNC void vpushi(int v);
ST_FUNC Sym *external_global_sym(int v, CType *type, int r); ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
ST_FUNC void vset(CType *type, int r, long v); ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vswap(void); ST_FUNC void vswap(void);
ST_FUNC void vpush_global_sym(CType *type, int v); ST_FUNC void vpush_global_sym(CType *type, int v);
ST_FUNC void vrote(SValue *e, int n); ST_FUNC void vrote(SValue *e, int n);
@ -1513,8 +1518,8 @@ static inline void add64le(unsigned char *p, int64_t x) {
ST_FUNC void g(int c); ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c); ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c); ST_FUNC void gen_le32(int c);
ST_FUNC void gen_addr32(int r, Sym *sym, long c); ST_FUNC void gen_addr32(int r, Sym *sym, int c);
ST_FUNC void gen_addrpc32(int r, Sym *sym, long c); ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
#endif #endif
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK

View File

@ -58,7 +58,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
/* We might be called for an asm block from inside a C routine /* We might be called for an asm block from inside a C routine
and so might have local decls on the identifier stack. Search and so might have local decls on the identifier stack. Search
for the first global one. */ for the first global one. */
while (csym && csym->scope) while (csym && csym->sym_scope)
csym = csym->prev_tok; csym = csym->prev_tok;
} }
/* Now, if we have a defined global symbol copy over /* Now, if we have a defined global symbol copy over
@ -74,7 +74,7 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
/* XXX can't yet store st_size anywhere. */ /* XXX can't yet store st_size anywhere. */
sym->type.t &= ~VT_EXTERN; sym->type.t &= ~VT_EXTERN;
/* Mark that this asm symbol doesn't need to be fed back. */ /* Mark that this asm symbol doesn't need to be fed back. */
sym->type.t |= VT_IMPORT; sym->a.dllimport = 1;
} }
} }
return sym; return sym;
@ -418,7 +418,7 @@ static void asm_free_labels(TCCState *st)
s1 = s->prev; s1 = s->prev;
/* define symbol value in object file */ /* define symbol value in object file */
s->type.t &= ~VT_EXTERN; s->type.t &= ~VT_EXTERN;
if (s->r && !(s->type.t & VT_IMPORT)) { if (s->r && !s->a.dllimport) {
if (s->r == SHN_ABS) if (s->r == SHN_ABS)
sec = SECTION_ABS; sec = SECTION_ABS;
else else
@ -693,9 +693,9 @@ static void asm_parse_directive(TCCState *s1, int global)
if (tok1 != TOK_ASMDIR_hidden) if (tok1 != TOK_ASMDIR_hidden)
sym->type.t &= ~VT_STATIC; sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASMDIR_weak) if (tok1 == TOK_ASMDIR_weak)
sym->type.t |= VT_WEAK; sym->a.weak = 1;
else if (tok1 == TOK_ASMDIR_hidden) else if (tok1 == TOK_ASMDIR_hidden)
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; sym->a.visibility = STV_HIDDEN;
next(); next();
} while (tok == ','); } while (tok == ',');
break; break;

384
tccgen.c
View File

@ -71,6 +71,7 @@ ST_DATA struct switch_t {
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
static void gen_cast(CType *type); static void gen_cast(CType *type);
static void gen_cast_s(int t);
static inline CType *pointed_type(CType *type); static inline CType *pointed_type(CType *type);
static int is_compatible_types(CType *type1, CType *type2); static int is_compatible_types(CType *type1, CType *type2);
static int parse_btype(CType *type, AttributeDef *ad); static int parse_btype(CType *type, AttributeDef *ad);
@ -90,7 +91,6 @@ static inline int64_t expr_const64(void);
ST_FUNC void vpush64(int ty, unsigned long long v); ST_FUNC void vpush64(int ty, unsigned long long v);
ST_FUNC void vpush(CType *type); ST_FUNC void vpush(CType *type);
ST_FUNC int gvtst(int inv, int t); ST_FUNC int gvtst(int inv, int t);
ST_FUNC int is_btype_size(int bt);
static void gen_inline_functions(TCCState *s); static void gen_inline_functions(TCCState *s);
static void skip_or_save_block(TokenString **str); static void skip_or_save_block(TokenString **str);
@ -240,7 +240,9 @@ ST_FUNC void tccgen_start(TCCState *s1)
size_type.t = VT_LLONG; size_type.t = VT_LLONG;
#endif #endif
func_old_type.t = VT_FUNC; func_old_type.t = VT_FUNC;
func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD); func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
func_old_type.ref->f.func_call = FUNC_CDECL;
func_old_type.ref->f.func_type = FUNC_OLD;
tcc_debug_start(s1); tcc_debug_start(s1);
@ -262,26 +264,30 @@ ST_FUNC void tccgen_end(TCCState *s1)
static void update_storage(Sym *sym) static void update_storage(Sym *sym)
{ {
int t;
ElfW(Sym) *esym; ElfW(Sym) *esym;
if (0 == sym->c) if (0 == sym->c)
return; return;
t = sym->type.t;
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
if (sym->a.visibility)
if (t & VT_VIS_MASK)
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
| ((t & VT_VIS_MASK) >> VT_VIS_SHIFT); | sym->a.visibility;
if (sym->a.weak)
if (t & VT_WEAK)
esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info)); esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info));
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if (t & VT_EXPORT) if (sym->a.dllimport)
esym->st_other |= ST_PE_IMPORT;
if (sym->a.dllexport)
esym->st_other |= ST_PE_EXPORT; esym->st_other |= ST_PE_EXPORT;
#endif #endif
#if 0
printf("storage %s: vis=%d weak=%d exp=%d imp=%d\n",
get_tok_str(sym->v, NULL),
sym->a.visibility,
sym->a.weak,
sym->a.dllexport,
sym->a.dllimport
);
#endif
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -352,15 +358,13 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if (sym_type == STT_FUNC && sym->type.ref) { if (sym_type == STT_FUNC && sym->type.ref) {
Sym *ref = sym->type.ref; Sym *ref = sym->type.ref;
if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) {
sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); sprintf(buf1, "_%s@%d", name, ref->f.func_args * PTR_SIZE);
name = buf1; name = buf1;
other |= ST_PE_STDCALL; other |= ST_PE_STDCALL;
can_add_underscore = 0; can_add_underscore = 0;
} }
} }
if (t & VT_IMPORT)
other |= ST_PE_IMPORT;
#endif #endif
if (tcc_state->leading_underscore && can_add_underscore) { if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_'; buf1[0] = '_';
@ -459,20 +463,15 @@ ST_INLN void sym_free(Sym *sym)
} }
/* push, without hashing */ /* push, without hashing */
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
{ {
Sym *s; Sym *s;
s = sym_malloc(); s = sym_malloc();
s->scope = 0; memset(s, 0, sizeof *s);
s->v = v; s->v = v;
s->type.t = t; s->type.t = t;
s->type.ref = NULL;
#ifdef _WIN64
s->d = NULL;
#endif
s->c = c; s->c = c;
s->next = NULL;
/* add in stack */ /* add in stack */
s->prev = *ps; s->prev = *ps;
*ps = s; *ps = s;
@ -512,7 +511,7 @@ ST_INLN Sym *sym_find(int v)
} }
/* push a given symbol on the symbol stack */ /* push a given symbol on the symbol stack */
ST_FUNC Sym *sym_push(int v, CType *type, int r, long c) ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
{ {
Sym *s, **ps; Sym *s, **ps;
TokenSym *ts; TokenSym *ts;
@ -535,8 +534,8 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, long c)
ps = &ts->sym_identifier; ps = &ts->sym_identifier;
s->prev_tok = *ps; s->prev_tok = *ps;
*ps = s; *ps = s;
s->scope = local_scope; s->sym_scope = local_scope;
if (s->prev_tok && s->prev_tok->scope == s->scope) if (s->prev_tok && s->prev_tok->sym_scope == s->sym_scope)
tcc_error("redeclaration of '%s'", tcc_error("redeclaration of '%s'",
get_tok_str(v & ~SYM_STRUCT, NULL)); get_tok_str(v & ~SYM_STRUCT, NULL));
} }
@ -544,7 +543,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, long c)
} }
/* push a global identifier */ /* push a global identifier */
ST_FUNC Sym *global_identifier_push(int v, int t, long c) ST_FUNC Sym *global_identifier_push(int v, int t, int c)
{ {
Sym *s, **ps; Sym *s, **ps;
s = sym_push2(&global_stack, v, t, c); s = sym_push2(&global_stack, v, t, c);
@ -661,8 +660,7 @@ ST_FUNC void vpop(void)
/* push constant of type "type" with useless value */ /* push constant of type "type" with useless value */
ST_FUNC void vpush(CType *type) ST_FUNC void vpush(CType *type)
{ {
CValue cval; vset(type, VT_CONST, 0);
vsetc(type, VT_CONST, &cval);
} }
/* push integer constant */ /* push integer constant */
@ -698,7 +696,7 @@ static inline void vpushll(long long v)
vpush64(VT_LLONG, v); vpush64(VT_LLONG, v);
} }
ST_FUNC void vset(CType *type, int r, long v) ST_FUNC void vset(CType *type, int r, int v)
{ {
CValue cval; CValue cval;
@ -710,7 +708,7 @@ static void vseti(int r, int v)
{ {
CType type; CType type;
type.t = VT_INT; type.t = VT_INT;
type.ref = 0; type.ref = NULL;
vset(&type, r, v); vset(&type, r, v);
} }
@ -808,32 +806,36 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
} }
/* Merge some storage attributes. */ /* Merge some storage attributes. */
static void patch_storage(Sym *sym, CType *type) static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
{ {
int t; if (type && !is_compatible_types(&sym->type, type))
if (!is_compatible_types(&sym->type, type))
tcc_error("incompatible types for redefinition of '%s'", tcc_error("incompatible types for redefinition of '%s'",
get_tok_str(sym->v, NULL)); get_tok_str(sym->v, NULL));
t = type->t;
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if ((sym->type.t ^ t) & VT_IMPORT) if (sym->a.dllimport != ad->a.dllimport)
tcc_error("incompatible dll linkage for redefinition of '%s'", tcc_error("incompatible dll linkage for redefinition of '%s'",
get_tok_str(sym->v, NULL)); get_tok_str(sym->v, NULL));
#endif #endif
sym->type.t |= t & (VT_EXPORT|VT_WEAK); sym->a.dllexport |= ad->a.dllexport;
if (t & VT_VIS_MASK) { sym->a.weak |= ad->a.weak;
int vis = sym->type.t & VT_VIS_MASK; if (ad->a.visibility) {
int vis2 = t & VT_VIS_MASK; int vis = sym->a.visibility;
if (vis == (STV_DEFAULT << VT_VIS_SHIFT)) int vis2 = ad->a.visibility;
if (vis == STV_DEFAULT)
vis = vis2; vis = vis2;
else if (vis2 != (STV_DEFAULT << VT_VIS_SHIFT)) else if (vis2 != STV_DEFAULT)
vis = (vis < vis2) ? vis : vis2; vis = (vis < vis2) ? vis : vis2;
sym->type.t = (sym->type.t & ~VT_VIS_MASK) | vis; sym->a.visibility = vis;
} }
if (ad->a.aligned)
sym->a.aligned = ad->a.aligned;
if (ad->asm_label)
sym->asm_label = ad->asm_label;
update_storage(sym);
} }
/* define a new external reference to a symbol 'v' */ /* define a new external reference to a symbol 'v' */
static Sym *external_sym(int v, CType *type, int r) static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
{ {
Sym *s; Sym *s;
s = sym_find(v); s = sym_find(v);
@ -841,14 +843,15 @@ static Sym *external_sym(int v, CType *type, int r)
/* push forward reference */ /* push forward reference */
s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
s->type.t |= VT_EXTERN; s->type.t |= VT_EXTERN;
s->a = ad->a;
s->sym_scope = 0;
} else { } else {
if (s->type.ref == func_old_type.ref) { if (s->type.ref == func_old_type.ref) {
s->type.ref = type->ref; s->type.ref = type->ref;
s->r = r | VT_CONST | VT_SYM; s->r = r | VT_CONST | VT_SYM;
s->type.t |= VT_EXTERN; s->type.t |= VT_EXTERN;
} }
patch_storage(s, type); patch_storage(s, ad, type);
update_storage(s);
} }
return s; return s;
} }
@ -2024,7 +2027,7 @@ redo:
#if PTR_SIZE == 4 #if PTR_SIZE == 4
if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
/* XXX: truncate here because gen_opl can't handle ptr + long long */ /* XXX: truncate here because gen_opl can't handle ptr + long long */
gen_cast(&int_type); gen_cast_s(VT_INT);
#endif #endif
type1 = vtop[-1].type; type1 = vtop[-1].type;
type1.t &= ~VT_ARRAY; type1.t &= ~VT_ARRAY;
@ -2132,6 +2135,7 @@ redo:
} }
vswap(); vswap();
type1.t = t; type1.t = t;
type1.ref = NULL;
gen_cast(&type1); gen_cast(&type1);
vswap(); vswap();
/* special case for shifts and long long: we keep the shift as /* special case for shifts and long long: we keep the shift as
@ -2244,6 +2248,14 @@ static void force_charshort_cast(int t)
} }
/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */ /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
static void gen_cast_s(int t)
{
CType type;
type.t = t;
type.ref = NULL;
gen_cast(&type);
}
static void gen_cast(CType *type) static void gen_cast(CType *type)
{ {
int sbt, dbt, sf, df, c, p; int sbt, dbt, sf, df, c, p;
@ -2373,7 +2385,7 @@ static void gen_cast(CType *type)
if (sbt == VT_PTR) { if (sbt == VT_PTR) {
/* cast from pointer to int before we apply /* cast from pointer to int before we apply
shift operation, which pointers don't support*/ shift operation, which pointers don't support*/
gen_cast(&int_type); gen_cast_s(VT_INT);
} }
gv_dup(); gv_dup();
vpushi(31); vpushi(31);
@ -2556,12 +2568,12 @@ static int is_compatible_func(CType *type1, CType *type2)
if (!is_compatible_types(&s1->type, &s2->type)) if (!is_compatible_types(&s1->type, &s2->type))
return 0; return 0;
/* check func_call */ /* check func_call */
if (s1->a.func_call != s2->a.func_call) if (s1->f.func_call != s2->f.func_call)
return 0; return 0;
/* XXX: not complete */ /* XXX: not complete */
if (s1->c == FUNC_OLD || s2->c == FUNC_OLD) if (s1->f.func_type == FUNC_OLD || s2->f.func_type == FUNC_OLD)
return 1; return 1;
if (s1->c != s2->c) if (s1->f.func_type != s2->f.func_type)
return 0; return 0;
while (s1 != NULL) { while (s1 != NULL) {
if (s2 == NULL) if (s2 == NULL)
@ -2741,7 +2753,7 @@ static void type_to_str(char *buf, int buf_size,
case VT_PTR: case VT_PTR:
s = type->ref; s = type->ref;
if (t & VT_ARRAY) { if (t & VT_ARRAY) {
snprintf(buf1, sizeof(buf1), "%s[%ld]", varstr ? varstr : "", s->c); snprintf(buf1, sizeof(buf1), "%s[%d]", varstr ? varstr : "", s->c);
type_to_str(buf, buf_size, &s->type, buf1); type_to_str(buf, buf_size, &s->type, buf1);
goto no_var; goto no_var;
} }
@ -2880,8 +2892,7 @@ ST_FUNC void vstore(void)
&& !(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 & vtop->type.t = ft & VT_TYPE;
((1 << VT_STRUCT_SHIFT) - 1));
/* XXX: factorize */ /* XXX: factorize */
if (ft & VT_CONSTANT) if (ft & VT_CONSTANT)
tcc_warning("assignment of read-only location"); tcc_warning("assignment of read-only location");
@ -3084,20 +3095,15 @@ static int exact_log2p1(int i)
return ret; return ret;
} }
/* Parse GNUC __attribute__ extension. Currently, the following /* Parse __attribute__((...)) GNUC extension. */
extensions are recognized:
- aligned(n) : set data/function alignment.
- packed : force data alignment to 1
- section(x) : generate data/code in this section.
- unused : currently ignored, but may be used someday.
- regparm(n) : pass function parameters in registers (i386 only)
*/
static void parse_attribute(AttributeDef *ad) static void parse_attribute(AttributeDef *ad)
{ {
int t, n; int t, n;
CString astr; CString astr;
while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) { redo:
if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2)
return;
next(); next();
skip('('); skip('(');
skip('('); skip('(');
@ -3178,12 +3184,12 @@ static void parse_attribute(AttributeDef *ad)
case TOK_CDECL1: case TOK_CDECL1:
case TOK_CDECL2: case TOK_CDECL2:
case TOK_CDECL3: case TOK_CDECL3:
ad->a.func_call = FUNC_CDECL; ad->f.func_call = FUNC_CDECL;
break; break;
case TOK_STDCALL1: case TOK_STDCALL1:
case TOK_STDCALL2: case TOK_STDCALL2:
case TOK_STDCALL3: case TOK_STDCALL3:
ad->a.func_call = FUNC_STDCALL; ad->f.func_call = FUNC_STDCALL;
break; break;
#ifdef TCC_TARGET_I386 #ifdef TCC_TARGET_I386
case TOK_REGPARM1: case TOK_REGPARM1:
@ -3195,30 +3201,30 @@ static void parse_attribute(AttributeDef *ad)
else if (n < 0) else if (n < 0)
n = 0; n = 0;
if (n > 0) if (n > 0)
ad->a.func_call = FUNC_FASTCALL1 + n - 1; ad->f.func_call = FUNC_FASTCALL1 + n - 1;
skip(')'); skip(')');
break; break;
case TOK_FASTCALL1: case TOK_FASTCALL1:
case TOK_FASTCALL2: case TOK_FASTCALL2:
case TOK_FASTCALL3: case TOK_FASTCALL3:
ad->a.func_call = FUNC_FASTCALLW; ad->f.func_call = FUNC_FASTCALLW;
break; break;
#endif #endif
case TOK_MODE: case TOK_MODE:
skip('('); skip('(');
switch(tok) { switch(tok) {
case TOK_MODE_DI: case TOK_MODE_DI:
ad->a.mode = VT_LLONG + 1; ad->attr_mode = VT_LLONG + 1;
break; break;
case TOK_MODE_QI: case TOK_MODE_QI:
ad->a.mode = VT_BYTE + 1; ad->attr_mode = VT_BYTE + 1;
break; break;
case TOK_MODE_HI: case TOK_MODE_HI:
ad->a.mode = VT_SHORT + 1; ad->attr_mode = VT_SHORT + 1;
break; break;
case TOK_MODE_SI: case TOK_MODE_SI:
case TOK_MODE_word: case TOK_MODE_word:
ad->a.mode = VT_INT + 1; ad->attr_mode = VT_INT + 1;
break; break;
default: default:
tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL)); tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL));
@ -3228,10 +3234,10 @@ static void parse_attribute(AttributeDef *ad)
skip(')'); skip(')');
break; break;
case TOK_DLLEXPORT: case TOK_DLLEXPORT:
ad->a.func_export = 1; ad->a.dllexport = 1;
break; break;
case TOK_DLLIMPORT: case TOK_DLLIMPORT:
ad->a.func_import = 1; ad->a.dllimport = 1;
break; break;
default: default:
if (tcc_state->warn_unsupported) if (tcc_state->warn_unsupported)
@ -3255,7 +3261,7 @@ static void parse_attribute(AttributeDef *ad)
} }
skip(')'); skip(')');
skip(')'); skip(')');
} goto redo;
} }
static Sym * find_field (CType *type, int v) static Sym * find_field (CType *type, int v)
@ -3327,7 +3333,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
} else { } else {
align = typealign; align = typealign;
} }
if (type->ref->type.t != TOK_STRUCT) { if (type->ref->type.t == VT_UNION) {
if (pcc && bit_size >= 0) if (pcc && bit_size >= 0)
size = (bit_size + 7) >> 3; size = (bit_size + 7) >> 3;
/* Bit position is already zero from our caller. */ /* Bit position is already zero from our caller. */
@ -3481,19 +3487,17 @@ static void struct_layout(CType *type, AttributeDef *ad)
} }
/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
static void struct_decl(CType *type, AttributeDef *ad, int u) static void struct_decl(CType *type, int u)
{ {
int a, v, size, align, flexible, alignoverride; int v, c, size, align, flexible, alignoverride;
long c;
int bit_size, bsize, bt; int bit_size, bsize, bt;
Sym *s, *ss, **ps; Sym *s, *ss, **ps;
AttributeDef ad1; AttributeDef ad, ad1;
CType type1, btype; CType type1, btype;
a = tok; /* save decl type */ memset(&ad, 0, sizeof ad);
next(); next();
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(&ad);
parse_attribute(ad);
if (tok != '{') { if (tok != '{') {
v = tok; v = tok;
next(); next();
@ -3501,8 +3505,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (v < TOK_IDENT) if (v < TOK_IDENT)
expect("struct/union/enum name"); expect("struct/union/enum name");
s = struct_find(v); s = struct_find(v);
if (s && (s->scope == local_scope || tok != '{')) { if (s && (s->sym_scope == local_scope || tok != '{')) {
if (s->type.t != a) if ((s->type.t & (VT_BTYPE|VT_UNION)) != u)
tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
goto do_decl; goto do_decl;
} }
@ -3510,16 +3514,15 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
v = anon_sym++; v = anon_sym++;
} }
/* Record the original enum/struct/union token. */ /* Record the original enum/struct/union token. */
type1.t = a; type1.t = u;
type1.ref = NULL; type1.ref = NULL;
/* we put an undefined size for struct/union */ /* we put an undefined size for struct/union */
s = sym_push(v | SYM_STRUCT, &type1, 0, -1); s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
s->r = 0; /* default alignment is zero as gcc */ s->r = 0; /* default alignment is zero as gcc */
/* put struct/union/enum name in type */ do_decl:
do_decl: type->t = u & VT_BTYPE; /* VT_UNION becomes VT_STRUCT */
type->t = u;
type->ref = s; type->ref = s;
if (tok == '{') { if (tok == '{') {
next(); next();
if (s->c != -1) if (s->c != -1)
@ -3527,7 +3530,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
/* cannot be empty */ /* cannot be empty */
c = 0; c = 0;
/* non empty enums are not allowed */ /* non empty enums are not allowed */
if (a == TOK_ENUM) { if (u == VT_ENUM) {
int seen_neg = 0; int seen_neg = 0;
int seen_wide = 0; int seen_wide = 0;
for(;;) { for(;;) {
@ -3602,7 +3605,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
} }
} }
if (type_size(&type1, &align) < 0) { if (type_size(&type1, &align) < 0) {
if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) if ((u == VT_STRUCT) && (type1.t & VT_ARRAY) && c)
flexible = 1; flexible = 1;
else else
tcc_error("field '%s' has incomplete type", tcc_error("field '%s' has incomplete type",
@ -3623,8 +3626,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (v && bit_size == 0) if (v && bit_size == 0)
tcc_error("zero width for bit-field '%s'", tcc_error("zero width for bit-field '%s'",
get_tok_str(v, NULL)); get_tok_str(v, NULL));
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(&ad1);
parse_attribute(&ad1);
} }
size = type_size(&type1, &align); size = type_size(&type1, &align);
/* Only remember non-default alignment. */ /* Only remember non-default alignment. */
@ -3632,7 +3634,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (ad1.a.aligned) { if (ad1.a.aligned) {
int speca = 1 << (ad1.a.aligned - 1); int speca = 1 << (ad1.a.aligned - 1);
alignoverride = speca; alignoverride = speca;
} else if (ad1.a.packed || ad->a.packed) { } else if (ad1.a.packed || ad.a.packed) {
alignoverride = 1; alignoverride = 1;
} else if (*tcc_state->pack_stack_ptr) { } else if (*tcc_state->pack_stack_ptr) {
if (align >= *tcc_state->pack_stack_ptr) if (align >= *tcc_state->pack_stack_ptr)
@ -3684,19 +3686,12 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
skip(';'); skip(';');
} }
skip('}'); skip('}');
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(&ad);
parse_attribute(ad); struct_layout(type, &ad);
struct_layout(type, ad);
} }
} }
} }
/* return 1 if basic type is a type size (short, long, long long) */
ST_FUNC int is_btype_size(int bt)
{
return bt == VT_SHORT || bt == VT_LONG || bt == VT_LLONG;
}
/* Add type qualifiers to a type. If the type is an array then the qualifiers /* Add type qualifiers to a type. If the type is an array then the qualifiers
are added to the element type, copied because it could be a typedef. */ are added to the element type, copied because it could be a typedef. */
static void parse_btype_qualify(CType *type, int qualifiers) static void parse_btype_qualify(CType *type, int qualifiers)
@ -3713,15 +3708,17 @@ static void parse_btype_qualify(CType *type, int qualifiers)
*/ */
static int parse_btype(CType *type, AttributeDef *ad) static int parse_btype(CType *type, AttributeDef *ad)
{ {
int t, u, bt_size, complete, type_found, typespec_found, g; int t, u, bt, st, type_found, typespec_found, g;
Sym *s; Sym *s;
CType type1; CType type1;
memset(ad, 0, sizeof(AttributeDef)); memset(ad, 0, sizeof(AttributeDef));
complete = 0;
type_found = 0; type_found = 0;
typespec_found = 0; typespec_found = 0;
t = 0; t = VT_INT;
bt = st = -1;
type->ref = NULL;
while(1) { while(1) {
switch(tok) { switch(tok) {
case TOK_EXTENSION: case TOK_EXTENSION:
@ -3735,12 +3732,17 @@ static int parse_btype(CType *type, AttributeDef *ad)
basic_type: basic_type:
next(); next();
basic_type1: basic_type1:
if (complete) if (u == VT_SHORT || u == VT_LONG) {
tcc_error("too many basic types"); if (st != -1 || (bt != -1 && bt != VT_INT))
t |= u; tmbt: tcc_error("too many basic types");
bt_size = is_btype_size (u & VT_BTYPE); st = u;
if (u == VT_INT || (!bt_size && !(t & VT_TYPEDEF))) } else {
complete = 1; if (bt != -1 || (st != -1 && u != VT_INT))
goto tmbt;
bt = u;
}
if (u != VT_INT)
t = (t & ~VT_BTYPE) | u;
typespec_found = 1; typespec_found = 1;
break; break;
case TOK_VOID: case TOK_VOID:
@ -3753,7 +3755,6 @@ static int parse_btype(CType *type, AttributeDef *ad)
u = VT_INT; u = VT_INT;
goto basic_type; goto basic_type;
case TOK_LONG: case TOK_LONG:
next();
if ((t & VT_BTYPE) == VT_DOUBLE) { if ((t & VT_BTYPE) == VT_DOUBLE) {
#ifndef TCC_TARGET_PE #ifndef TCC_TARGET_PE
t = (t & ~VT_BTYPE) | VT_LDOUBLE; t = (t & ~VT_BTYPE) | VT_LDOUBLE;
@ -3762,8 +3763,9 @@ static int parse_btype(CType *type, AttributeDef *ad)
t = (t & ~VT_BTYPE) | VT_LLONG; t = (t & ~VT_BTYPE) | VT_LLONG;
} else { } else {
u = VT_LONG; u = VT_LONG;
goto basic_type1; goto basic_type;
} }
next();
break; break;
#ifdef TCC_TARGET_ARM64 #ifdef TCC_TARGET_ARM64
case TOK_UINT128: case TOK_UINT128:
@ -3779,7 +3781,6 @@ static int parse_btype(CType *type, AttributeDef *ad)
u = VT_FLOAT; u = VT_FLOAT;
goto basic_type; goto basic_type;
case TOK_DOUBLE: case TOK_DOUBLE:
next();
if ((t & VT_BTYPE) == VT_LONG) { if ((t & VT_BTYPE) == VT_LONG) {
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
t = (t & ~VT_BTYPE) | VT_DOUBLE; t = (t & ~VT_BTYPE) | VT_DOUBLE;
@ -3788,18 +3789,21 @@ static int parse_btype(CType *type, AttributeDef *ad)
#endif #endif
} else { } else {
u = VT_DOUBLE; u = VT_DOUBLE;
goto basic_type1; goto basic_type;
} }
next();
break; break;
case TOK_ENUM: case TOK_ENUM:
struct_decl(&type1, ad, VT_ENUM); struct_decl(&type1, VT_ENUM);
basic_type2: basic_type2:
u = type1.t; u = type1.t;
type->ref = type1.ref; type->ref = type1.ref;
goto basic_type1; goto basic_type1;
case TOK_STRUCT: case TOK_STRUCT:
struct_decl(&type1, VT_STRUCT);
goto basic_type2;
case TOK_UNION: case TOK_UNION:
struct_decl(&type1, ad, VT_STRUCT); struct_decl(&type1, VT_UNION);
goto basic_type2; goto basic_type2;
/* type modifiers */ /* type modifiers */
@ -3824,9 +3828,9 @@ static int parse_btype(CType *type, AttributeDef *ad)
case TOK_SIGNED3: case TOK_SIGNED3:
if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED)) if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED))
tcc_error("signed and unsigned modifier"); tcc_error("signed and unsigned modifier");
typespec_found = 1;
t |= VT_DEFSIGN; t |= VT_DEFSIGN;
next(); next();
typespec_found = 1;
break; break;
case TOK_REGISTER: case TOK_REGISTER:
case TOK_AUTO: case TOK_AUTO:
@ -3870,8 +3874,8 @@ static int parse_btype(CType *type, AttributeDef *ad)
case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE1:
case TOK_ATTRIBUTE2: case TOK_ATTRIBUTE2:
parse_attribute(ad); parse_attribute(ad);
if (ad->a.mode) { if (ad->attr_mode) {
u = ad->a.mode -1; u = ad->attr_mode -1;
t = (t & ~VT_BTYPE) | u; t = (t & ~VT_BTYPE) | u;
} }
break; break;
@ -3890,24 +3894,23 @@ static int parse_btype(CType *type, AttributeDef *ad)
s = sym_find(tok); s = sym_find(tok);
if (!s || !(s->type.t & VT_TYPEDEF)) if (!s || !(s->type.t & VT_TYPEDEF))
goto the_end; goto the_end;
t &= ~VT_BTYPE;
type->t = ((s->type.t & ~VT_TYPEDEF) | u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u;
(t & ~(VT_CONSTANT | VT_VOLATILE))); type->t = (s->type.t & ~VT_TYPEDEF) | u;
type->ref = s->type.ref; type->ref = s->type.ref;
if (t & (VT_CONSTANT | VT_VOLATILE)) if (t)
parse_btype_qualify(type, t & (VT_CONSTANT | VT_VOLATILE)); parse_btype_qualify(type, t);
t = type->t; t = type->t;
/* get attributes from typedef */
if (s->r) { if (s->a.aligned && 0 == ad->a.aligned)
/* get attributes from typedef */ ad->a.aligned = s->a.aligned;
if (0 == ad->a.aligned) if (s->f.func_call && 0 == ad->f.func_call)
ad->a.aligned = s->a.aligned; ad->f.func_call = s->f.func_call;
if (0 == ad->a.func_call) if (s->a.packed)
ad->a.func_call = s->a.func_call; ad->a.packed = 1;
ad->a.packed |= s->a.packed;
}
next(); next();
typespec_found = 1; typespec_found = 1;
st = bt = -2;
break; break;
} }
type_found = 1; type_found = 1;
@ -4037,9 +4040,11 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td)
mk_pointer(type); mk_pointer(type);
} }
/* we push a anonymous symbol which will contain the function prototype */ /* we push a anonymous symbol which will contain the function prototype */
ad->a.func_args = arg_size; ad->f.func_args = arg_size;
s = sym_push(SYM_FIELD, type, 0, l); ad->f.func_type = l;
s = sym_push(SYM_FIELD, type, 0, 0);
s->a = ad->a; s->a = ad->a;
s->f = ad->f;
s->next = first; s->next = first;
type->t = VT_FUNC; type->t = VT_FUNC;
type->ref = s; type->ref = s;
@ -4159,8 +4164,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
apply to the innermost pointed to type (if any). */ apply to the innermost pointed to type (if any). */
/* XXX: this is not correct to modify 'ad' at this point, but /* XXX: this is not correct to modify 'ad' at this point, but
the syntax is not clear */ the syntax is not clear */
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(ad);
parse_attribute(ad);
post = type_decl(type, ad, v, td); post = type_decl(type, ad, v, td);
skip(')'); skip(')');
} }
@ -4174,8 +4178,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
*v = 0; *v = 0;
} }
post_type(post, ad, storage, 0); post_type(post, ad, storage, 0);
if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) parse_attribute(ad);
parse_attribute(ad);
type->t |= storage; type->t |= storage;
return ret; return ret;
} }
@ -4226,13 +4229,12 @@ static void gfunc_param_typed(Sym *func, Sym *arg)
int func_type; int func_type;
CType type; CType type;
func_type = func->c; func_type = func->f.func_type;
if (func_type == FUNC_OLD || if (func_type == FUNC_OLD ||
(func_type == FUNC_ELLIPSIS && arg == NULL)) { (func_type == FUNC_ELLIPSIS && arg == NULL)) {
/* default casting : only need to convert float to double */ /* default casting : only need to convert float to double */
if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) { if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
type.t = VT_DOUBLE; gen_cast_s(VT_DOUBLE);
gen_cast(&type);
} else if (vtop->type.t & VT_BITFIELD) { } else if (vtop->type.t & VT_BITFIELD) {
type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
type.ref = vtop->type.ref; type.ref = vtop->type.ref;
@ -4318,6 +4320,7 @@ ST_FUNC void unary(void)
sizeof_caller = in_sizeof; sizeof_caller = in_sizeof;
in_sizeof = 0; in_sizeof = 0;
type.ref = NULL;
/* XXX: GCC 2.95.3 does not generate a table although it should be /* XXX: GCC 2.95.3 does not generate a table although it should be
better here */ better here */
tok_next: tok_next:
@ -4331,7 +4334,6 @@ ST_FUNC void unary(void)
t = VT_INT; t = VT_INT;
push_tokc: push_tokc:
type.t = t; type.t = t;
type.ref = 0;
vsetc(&type, VT_CONST, &tokc); vsetc(&type, VT_CONST, &tokc);
next(); next();
break; break;
@ -4464,9 +4466,7 @@ ST_FUNC void unary(void)
next(); next();
unary(); unary();
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
CType boolean; gen_cast_s(VT_BOOL);
boolean.t = VT_BOOL;
gen_cast(&boolean);
vtop->c.i = !vtop->c.i; vtop->c.i = !vtop->c.i;
} else if ((vtop->r & VT_VALMASK) == VT_CMP) } else if ((vtop->r & VT_VALMASK) == VT_CMP)
vtop->c.i ^= 1; vtop->c.i ^= 1;
@ -4567,7 +4567,6 @@ ST_FUNC void unary(void)
{ {
int tok1 = tok; int tok1 = tok;
int level; int level;
CType type;
next(); next();
skip('('); skip('(');
if (tok != TOK_CINT) { if (tok != TOK_CINT) {
@ -4629,7 +4628,6 @@ ST_FUNC void unary(void)
break; break;
} }
case TOK___va_arg: { case TOK___va_arg: {
CType type;
parse_builtin_params(0, "et"); parse_builtin_params(0, "et");
type = vtop->type; type = vtop->type;
vpop(); vpop();
@ -4895,7 +4893,7 @@ ST_FUNC void unary(void)
ret.r2 = VT_CONST; ret.r2 = VT_CONST;
/* compute first implicit argument if a structure is returned */ /* compute first implicit argument if a structure is returned */
if ((s->type.t & VT_BTYPE) == VT_STRUCT) { if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
variadic = (s->c == FUNC_ELLIPSIS); variadic = (s->f.func_type == FUNC_ELLIPSIS);
ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
&ret_align, &regsize); &ret_align, &regsize);
if (!ret_nregs) { if (!ret_nregs) {
@ -5100,9 +5098,7 @@ static void expr_land(void)
int t = 0; int t = 0;
for(;;) { for(;;) {
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
CType ctb; gen_cast_s(VT_BOOL);
ctb.t = VT_BOOL;
gen_cast(&ctb);
if (vtop->c.i) { if (vtop->c.i) {
vpop(); vpop();
} else { } else {
@ -5115,7 +5111,7 @@ static void expr_land(void)
nocode_wanted--; nocode_wanted--;
if (t) if (t)
gsym(t); gsym(t);
gen_cast(&int_type); gen_cast_s(VT_INT);
break; break;
} }
} else { } else {
@ -5143,9 +5139,7 @@ static void expr_lor(void)
int t = 0; int t = 0;
for(;;) { for(;;) {
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
CType ctb; gen_cast_s(VT_BOOL);
ctb.t = VT_BOOL;
gen_cast(&ctb);
if (!vtop->c.i) { if (!vtop->c.i) {
vpop(); vpop();
} else { } else {
@ -5158,7 +5152,7 @@ static void expr_lor(void)
nocode_wanted--; nocode_wanted--;
if (t) if (t)
gsym(t); gsym(t);
gen_cast(&int_type); gen_cast_s(VT_INT);
break; break;
} }
} else { } else {
@ -5186,12 +5180,9 @@ static int condition_3way(void)
{ {
int c = -1; int c = -1;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
(!(vtop->r & VT_SYM) || (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) {
!(vtop->sym->type.t & VT_WEAK))) {
CType boolean;
boolean.t = VT_BOOL;
vdup(); vdup();
gen_cast(&boolean); gen_cast_s(VT_BOOL);
c = vtop->c.i; c = vtop->c.i;
vpop(); vpop();
} }
@ -5262,6 +5253,8 @@ static void expr_cond(void)
bt1 = t1 & VT_BTYPE; bt1 = t1 & VT_BTYPE;
t2 = type2.t; t2 = type2.t;
bt2 = t2 & VT_BTYPE; bt2 = t2 & VT_BTYPE;
type.ref = NULL;
/* cast operands to correct type according to ISOC rules */ /* cast operands to correct type according to ISOC rules */
if (is_float(bt1) || is_float(bt2)) { if (is_float(bt1) || is_float(bt2)) {
if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) { if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
@ -6000,9 +5993,9 @@ static void parse_init_elem(int expr_type)
&& ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL) && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
|| vtop->sym->v < SYM_FIRST_ANOM)) || vtop->sym->v < SYM_FIRST_ANOM))
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
|| (vtop->type.t & VT_IMPORT) || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport)
#endif #endif
) )
tcc_error("initializer element is not constant"); tcc_error("initializer element is not constant");
break; break;
case EXPR_ANY: case EXPR_ANY:
@ -6448,7 +6441,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
if (no_oblock && len >= n*size1) if (no_oblock && len >= n*size1)
break; break;
} else { } else {
if (s->type.t == TOK_UNION) if (s->type.t == VT_UNION)
f = NULL; f = NULL;
else else
f = f->next; f = f->next;
@ -6521,6 +6514,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
TokenString *init_str = NULL; TokenString *init_str = NULL;
Section *sec; Section *sec;
Sym *flexible_array; Sym *flexible_array;
Sym *sym = NULL;
flexible_array = NULL; flexible_array = NULL;
if ((type->t & VT_BTYPE) == VT_STRUCT) { if ((type->t & VT_BTYPE) == VT_STRUCT) {
@ -6618,18 +6612,18 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
r = (r & ~VT_VALMASK) | reg; r = (r & ~VT_VALMASK) | reg;
} }
#endif #endif
sym_push(v, type, r, addr); sym = sym_push(v, type, r, addr);
sym->a = ad->a;
} else { } else {
/* push local reference */ /* push local reference */
vset(type, r, addr); vset(type, r, addr);
} }
} else { } else {
Sym *sym = NULL;
if (v && scope == VT_CONST) { if (v && scope == VT_CONST) {
/* see if the symbol was already defined */ /* see if the symbol was already defined */
sym = sym_find(v); sym = sym_find(v);
if (sym) { if (sym) {
patch_storage(sym, type); patch_storage(sym, ad, type);
if (sym->type.t & VT_EXTERN) { if (sym->type.t & VT_EXTERN) {
/* if the variable is extern, it was not allocated */ /* if the variable is extern, it was not allocated */
sym->type.t &= ~VT_EXTERN; sym->type.t &= ~VT_EXTERN;
@ -6644,7 +6638,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
global variable. this is tricky, because we global variable. this is tricky, because we
must play with the SHN_COMMON type of the symbol */ must play with the SHN_COMMON type of the symbol */
/* no init data, we won't add more to the symbol */ /* no init data, we won't add more to the symbol */
update_storage(sym);
goto no_alloc; goto no_alloc;
} else if (sym->c) { } else if (sym->c) {
ElfW(Sym) *esym; ElfW(Sym) *esym;
@ -6679,7 +6672,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
if (v) { if (v) {
if (!sym) { if (!sym) {
sym = sym_push(v, type, r | VT_SYM, 0); sym = sym_push(v, type, r | VT_SYM, 0);
sym->asm_label = ad->asm_label; patch_storage(sym, ad, NULL);
} }
/* update symbol definition */ /* update symbol definition */
put_extern_sym(sym, sec, addr, size); put_extern_sym(sym, sec, addr, size);
@ -6901,7 +6894,7 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
/* if old style function prototype, we accept a /* if old style function prototype, we accept a
declaration list */ declaration list */
sym = type.ref; sym = type.ref;
if (sym->c == FUNC_OLD && l == VT_CONST) if (sym->f.func_type == FUNC_OLD && l == VT_CONST)
decl0(VT_CMP, 0, sym); decl0(VT_CMP, 0, sym);
} }
@ -6913,20 +6906,18 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
expect(";"); expect(";");
} }
if (ad.a.weak)
type.t |= VT_WEAK;
#ifdef TCC_TARGET_PE #ifdef TCC_TARGET_PE
if (ad.a.func_import || ad.a.func_export) { if (ad.a.dllimport || ad.a.dllexport) {
if (type.t & (VT_STATIC|VT_TYPEDEF)) if (type.t & (VT_STATIC|VT_TYPEDEF))
tcc_error("cannot have dll linkage with static or typedef"); tcc_error("cannot have dll linkage with static or typedef");
if (ad.a.func_export) if (ad.a.dllimport) {
type.t |= VT_EXPORT; if ((type.t & VT_BTYPE) == VT_FUNC)
else if ((type.t & VT_BTYPE) != VT_FUNC) ad.a.dllimport = 0;
type.t |= VT_IMPORT|VT_EXTERN; else
type.t |= VT_EXTERN;
}
} }
#endif #endif
type.t |= ad.a.visibility << VT_VIS_SHIFT;
if (tok == '{') { if (tok == '{') {
if (l != VT_CONST) if (l != VT_CONST)
tcc_error("cannot use local functions"); tcc_error("cannot use local functions");
@ -6956,9 +6947,9 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
ref = sym->type.ref; ref = sym->type.ref;
/* use func_call from prototype if not defined */ /* use func_call from prototype if not defined */
if (ref->a.func_call != FUNC_CDECL if (ref->f.func_call != FUNC_CDECL
&& type.ref->a.func_call == FUNC_CDECL) && type.ref->f.func_call == FUNC_CDECL)
type.ref->a.func_call = ref->a.func_call; type.ref->f.func_call = ref->f.func_call;
/* use static from prototype */ /* use static from prototype */
if (sym->type.t & VT_STATIC) if (sym->type.t & VT_STATIC)
@ -6966,18 +6957,18 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
/* If the definition has no visibility use the /* If the definition has no visibility use the
one from prototype. */ one from prototype. */
if (! (type.t & VT_VIS_MASK)) if (!type.ref->a.visibility)
type.t |= sym->type.t & VT_VIS_MASK; type.ref->a.visibility = ref->a.visibility;
/* apply other storage attributes from prototype */ /* apply other storage attributes from prototype */
type.t |= sym->type.t & (VT_EXPORT|VT_WEAK); type.ref->a.dllexport |= ref->a.dllexport;
type.ref->a.weak |= ref->a.weak;
if (!is_compatible_types(&sym->type, &type)) { if (!is_compatible_types(&sym->type, &type)) {
func_error1: func_error1:
tcc_error("incompatible types for redefinition of '%s'", tcc_error("incompatible types for redefinition of '%s'",
get_tok_str(v, NULL)); get_tok_str(v, NULL));
} }
if (ref->a.func_body) if (ref->f.func_body)
tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
/* if symbol is already defined, then put complete type */ /* if symbol is already defined, then put complete type */
sym->type = type; sym->type = type;
@ -6988,8 +6979,9 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
sym->type.ref = type.ref; sym->type.ref = type.ref;
} }
sym->type.ref->a.func_body = 1; sym->type.ref->f.func_body = 1;
sym->r = VT_SYM | VT_CONST; sym->r = VT_SYM | VT_CONST;
patch_storage(sym, &ad, NULL);
/* static inline functions are just recorded as a kind /* static inline functions are just recorded as a kind
of macro. Their code will be emitted at the end of of macro. Their code will be emitted at the end of
@ -7035,7 +7027,7 @@ found:
/* save typedefed type */ /* save typedefed type */
/* XXX: test storage specifiers ? */ /* XXX: test storage specifiers ? */
sym = sym_find(v); sym = sym_find(v);
if (sym && sym->scope == local_scope) { if (sym && sym->sym_scope == local_scope) {
if (!is_compatible_types(&sym->type, &type) if (!is_compatible_types(&sym->type, &type)
|| !(sym->type.t & VT_TYPEDEF)) || !(sym->type.t & VT_TYPEDEF))
tcc_error("incompatible redefinition of '%s'", tcc_error("incompatible redefinition of '%s'",
@ -7066,13 +7058,11 @@ found:
/* NOTE: as GCC, uninitialized global static /* NOTE: as GCC, uninitialized global static
arrays of null size are considered as arrays of null size are considered as
extern */ extern */
sym = external_sym(v, &type, r); sym = external_sym(v, &type, r, &ad);
sym->asm_label = ad.asm_label;
if (ad.alias_target) { if (ad.alias_target) {
Section tsec; Section tsec;
ElfW(Sym) *esym; ElfW(Sym) *esym;
Sym *alias_target; Sym *alias_target;
alias_target = sym_find(ad.alias_target); alias_target = sym_find(ad.alias_target);
if (!alias_target || !alias_target->c) if (!alias_target || !alias_target->c)
tcc_error("unsupported forward __alias__ attribute"); tcc_error("unsupported forward __alias__ attribute");

View File

@ -1477,7 +1477,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
int r2; int r2;
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST)) if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
return sv; return sv;
if (!(sv->sym->type.t & VT_IMPORT)) if (!sv->sym->a.dllimport)
return sv; return sv;
// printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL)); // printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
memset(v2, 0, sizeof *v2); memset(v2, 0, sizeof *v2);

View File

@ -239,7 +239,7 @@ static int oad(int c, int s)
/* generate jmp to a label */ /* generate jmp to a label */
#define gjmp2(instr,lbl) oad(instr,lbl) #define gjmp2(instr,lbl) oad(instr,lbl)
ST_FUNC void gen_addr32(int r, Sym *sym, long c) ST_FUNC void gen_addr32(int r, Sym *sym, int c)
{ {
if (r & VT_SYM) if (r & VT_SYM)
greloca(cur_text_section, sym, ind, R_X86_64_32S, c), c=0; greloca(cur_text_section, sym, ind, R_X86_64_32S, c), c=0;
@ -255,7 +255,7 @@ ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
} }
/* output constant with relocation if 'r & VT_SYM' is true */ /* output constant with relocation if 'r & VT_SYM' is true */
ST_FUNC void gen_addrpc32(int r, Sym *sym, long c) ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
{ {
if (r & VT_SYM) if (r & VT_SYM)
greloca(cur_text_section, sym, ind, R_X86_64_PC32, c-4), c=4; greloca(cur_text_section, sym, ind, R_X86_64_PC32, c-4), c=4;
@ -950,7 +950,7 @@ void gfunc_prolog(CType *func_type)
/* if the function returns a structure, then add an /* if the function returns a structure, then add an
implicit pointer parameter */ implicit pointer parameter */
func_vt = sym->type; func_vt = sym->type;
func_var = (sym->c == FUNC_ELLIPSIS); func_var = (sym->f.func_type == FUNC_ELLIPSIS);
size = gfunc_arg_size(&func_vt); size = gfunc_arg_size(&func_vt);
if (!using_regs(size)) { if (!using_regs(size)) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
@ -988,7 +988,7 @@ void gfunc_prolog(CType *func_type)
} }
while (reg_param_index < REGN) { while (reg_param_index < REGN) {
if (func_type->ref->c == FUNC_ELLIPSIS) { if (func_type->ref->f.func_type == FUNC_ELLIPSIS) {
gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr); gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
addr += 8; addr += 8;
} }
@ -1393,7 +1393,7 @@ void gfunc_call(int nb_args)
} }
} }
if (vtop->type.ref->c != FUNC_NEW) /* implies FUNC_OLD or FUNC_ELLIPSIS */ if (vtop->type.ref->f.func_type != FUNC_NEW) /* implies FUNC_OLD or FUNC_ELLIPSIS */
oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */ oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
gcall_or_jmp(0); gcall_or_jmp(0);
if (args_size) if (args_size)
@ -1425,7 +1425,7 @@ void gfunc_prolog(CType *func_type)
func_sub_sp_offset = ind; func_sub_sp_offset = ind;
func_ret_sub = 0; func_ret_sub = 0;
if (func_type->ref->c == FUNC_ELLIPSIS) { if (sym->f.func_type == FUNC_ELLIPSIS) {
int seen_reg_num, seen_sse_num, seen_stack_size; int seen_reg_num, seen_sse_num, seen_stack_size;
seen_reg_num = seen_sse_num = 0; seen_reg_num = seen_sse_num = 0;
/* frame pointer and return address */ /* frame pointer and return address */