diff --git a/arm-gen.c b/arm-gen.c index 8384781..f85c263 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1221,7 +1221,7 @@ void gfunc_call(int nb_args) int variadic; 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])) float_abi = ARM_SOFTFP_FLOAT; } @@ -1279,7 +1279,7 @@ void gfunc_prolog(CType *func_type) sym = func_type->ref; 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; if ((func_vt.t & VT_BTYPE) == VT_STRUCT && diff --git a/arm64-gen.c b/arm64-gen.c index c7a71e6..1ebbd2b 100644 --- a/arm64-gen.c +++ b/arm64-gen.c @@ -428,7 +428,7 @@ static void arm64_sym(int r, Sym *sym, unsigned long addend) // relocation and use only relocations with unlimited range. 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.) greloca(cur_text_section, sym, ind, R_AARCH64_MOVW_UABS_G0_NC, addend); o(0xd2800000 | r); // mov x(rt),#0,lsl #0 diff --git a/c67-gen.c b/c67-gen.c index a480976..bcb4b0e 100644 --- a/c67-gen.c +++ b/c67-gen.c @@ -1951,12 +1951,12 @@ void gfunc_prolog(CType * func_type) CType *type; sym = func_type->ref; - func_call = sym->r; + func_call = sym->f.func_call; addr = 8; /* if the function returns a structure, then add an implicit pointer parameter */ 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) { func_vc = addr; addr += 4; diff --git a/i386-gen.c b/i386-gen.c index 9990676..3646084 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -161,14 +161,14 @@ static int oad(int c, int s) #define gjmp2(instr,lbl) oad(instr,lbl) /* 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) greloc(cur_text_section, sym, ind, R_386_32); 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) 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 */ func_sym = vtop->type.ref; - func_call = func_sym->a.func_call; + func_call = func_sym->f.func_call; /* fast call case */ if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) || func_call == FUNC_FASTCALLW) { @@ -525,7 +525,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) CType *type; sym = func_type->ref; - func_call = sym->a.func_call; + func_call = sym->f.func_call; addr = 8; loc = 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 implicit pointer parameter */ func_vt = sym->type; - func_var = (sym->c == FUNC_ELLIPSIS); + func_var = (sym->f.func_type == FUNC_ELLIPSIS); #ifdef TCC_TARGET_PE size = type_size(&func_vt,&align); if (((func_vt.t & VT_BTYPE) == VT_STRUCT) diff --git a/tcc.h b/tcc.h index 958dae7..77fd938 100644 --- a/tcc.h +++ b/tcc.h @@ -407,49 +407,59 @@ typedef struct SValue { result of unary() for an identifier. */ } 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 - func_call : 3, /* calling convention (0..5), see below */ - aligned : 5, /* alignment as log2+1 (0 == unspecified) */ - packed : 1, - func_export : 1, - 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 + func_call : 3, /* calling convention (0..5), see below */ + func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */ + func_body : 1, /* body was defined */ + func_args : 8; /* PE __stdcall args */ }; /* GNUC attribute definition */ typedef struct AttributeDef { - struct Attribute a; + struct SymAttr a; + struct FuncAttr f; struct Section *section; - int alias_target; /* token */ - int asm_label; /* associated asm label */ + int alias_target; /* token */ + int asm_label; /* associated asm label */ + char attr_mode; /* __attribute__((__mode__(...))) */ } AttributeDef; /* symbol management */ 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 { - int asm_label; /* associated asm label */ - int scope; /* scope level for locals */ + struct { + 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 { - 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 */ + CType type; /* associated type */ union { 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_tok; /* previous symbol for this token */ @@ -498,12 +508,12 @@ typedef struct DLLReference { #define SYM_FIELD 0x20000000 /* struct/union field symbol space */ #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_OLD 2 /* old function prototype */ #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_STDCALL 1 /* pascal c call */ #define FUNC_FASTCALL1 2 /* first param in %eax */ @@ -834,53 +844,48 @@ struct filespec { /* types */ #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_SHORT 2 /* short type */ -#define VT_VOID 3 /* void type */ -#define VT_PTR 4 /* pointer */ -#define VT_ENUM 5 /* enum definition */ +#define VT_INT 3 /* integer type */ +#define VT_LLONG 4 /* 64 bit integer */ +#define VT_PTR 5 /* pointer */ #define VT_FUNC 6 /* function type */ #define VT_STRUCT 7 /* struct/union definition */ -#define VT_FLOAT 8 /* IEEE float */ -#define VT_DOUBLE 9 /* IEEE double */ -#define VT_LDOUBLE 10 /* IEEE long double */ -#define VT_BOOL 11 /* ISOC99 boolean type */ -#define VT_LLONG 12 /* 64 bit integer */ -#define VT_LONG 13 /* long integer (NEVER USED as type, only - during parsing) */ +#define VT_ENUM 8 /* enum definition */ +#define VT_FLOAT 9 /* IEEE float */ +#define VT_DOUBLE 10 /* IEEE double */ +#define VT_LDOUBLE 11 /* IEEE long double */ +#define VT_BOOL 12 /* ISOC99 boolean type */ +#define VT_LONG 13 /* long integer (NEVER USED as type, only during parsing) */ #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_UNSIGNED 0x0010 /* unsigned type */ -#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ -#define VT_BITFIELD 0x0040 /* bitfield modifier */ -#define VT_CONSTANT 0x0800 /* const modifier */ -#define VT_VOLATILE 0x1000 /* volatile modifier */ -#define VT_DEFSIGN 0x2000 /* signed type */ -#define VT_VLA 0x00020000 /* VLA type (also has VT_PTR and VT_ARRAY) */ +#define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */ +#define VT_ARRAY 0x0040 /* array type (also has VT_PTR) */ +#define VT_BITFIELD 0x0080 /* bitfield modifier */ +#define VT_CONSTANT 0x0100 /* const modifier */ +#define VT_VOLATILE 0x0200 /* volatile modifier */ +#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 */ -#define VT_EXTERN 0x00000080 /* extern definition */ -#define VT_STATIC 0x00000100 /* static variable */ -#define VT_TYPEDEF 0x00000200 /* typedef definition */ -#define VT_INLINE 0x00000400 /* inline definition */ -#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ -#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_EXTERN 0x00001000 /* extern definition */ +#define VT_STATIC 0x00002000 /* static variable */ +#define VT_TYPEDEF 0x00004000 /* typedef definition */ +#define VT_INLINE 0x00008000 /* inline definition */ +/* currently unused: 0x0800, 0x000[1248]0000 */ +#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) */ -#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_IMPORT | VT_EXPORT | VT_WEAK | VT_VIS_MASK) -#define VT_TYPE (~(VT_STORAGE)) +#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_STRUCT_MASK) +#define VT_TYPE (~VT_STORAGE) + /* token values */ @@ -1117,13 +1122,13 @@ ST_FUNC void cstr_free(CString *cstr); ST_FUNC void cstr_reset(CString *cstr); 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_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_INLN Sym *struct_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 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 vpushi(int v); 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 vpush_global_sym(CType *type, int v); 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 gen_le16(int c); ST_FUNC void gen_le32(int c); -ST_FUNC void gen_addr32(int r, Sym *sym, long c); -ST_FUNC void gen_addrpc32(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, int c); #endif #ifdef CONFIG_TCC_BCHECK diff --git a/tccasm.c b/tccasm.c index f22ed9f..59264ce 100644 --- a/tccasm.c +++ b/tccasm.c @@ -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 and so might have local decls on the identifier stack. Search for the first global one. */ - while (csym && csym->scope) + while (csym && csym->sym_scope) csym = csym->prev_tok; } /* 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. */ sym->type.t &= ~VT_EXTERN; /* Mark that this asm symbol doesn't need to be fed back. */ - sym->type.t |= VT_IMPORT; + sym->a.dllimport = 1; } } return sym; @@ -418,7 +418,7 @@ static void asm_free_labels(TCCState *st) s1 = s->prev; /* define symbol value in object file */ s->type.t &= ~VT_EXTERN; - if (s->r && !(s->type.t & VT_IMPORT)) { + if (s->r && !s->a.dllimport) { if (s->r == SHN_ABS) sec = SECTION_ABS; else @@ -693,9 +693,9 @@ static void asm_parse_directive(TCCState *s1, int global) if (tok1 != TOK_ASMDIR_hidden) sym->type.t &= ~VT_STATIC; if (tok1 == TOK_ASMDIR_weak) - sym->type.t |= VT_WEAK; + sym->a.weak = 1; else if (tok1 == TOK_ASMDIR_hidden) - sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; + sym->a.visibility = STV_HIDDEN; next(); } while (tok == ','); break; diff --git a/tccgen.c b/tccgen.c index 40bed59..4f2b501 100644 --- a/tccgen.c +++ b/tccgen.c @@ -71,6 +71,7 @@ ST_DATA struct switch_t { /* ------------------------------------------------------------------------- */ static void gen_cast(CType *type); +static void gen_cast_s(int t); static inline CType *pointed_type(CType *type); static int is_compatible_types(CType *type1, CType *type2); 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 vpush(CType *type); 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 skip_or_save_block(TokenString **str); @@ -240,7 +240,9 @@ ST_FUNC void tccgen_start(TCCState *s1) size_type.t = VT_LLONG; #endif 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); @@ -262,26 +264,30 @@ ST_FUNC void tccgen_end(TCCState *s1) static void update_storage(Sym *sym) { - int t; ElfW(Sym) *esym; - if (0 == sym->c) return; - - t = sym->type.t; esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; - - if (t & VT_VIS_MASK) + if (sym->a.visibility) esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) - | ((t & VT_VIS_MASK) >> VT_VIS_SHIFT); - - if (t & VT_WEAK) + | sym->a.visibility; + if (sym->a.weak) esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info)); - #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; #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 if (sym_type == STT_FUNC && sym->type.ref) { Sym *ref = sym->type.ref; - if (ref->a.func_call == FUNC_STDCALL && can_add_underscore) { - sprintf(buf1, "_%s@%d", name, ref->a.func_args * PTR_SIZE); + if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) { + sprintf(buf1, "_%s@%d", name, ref->f.func_args * PTR_SIZE); name = buf1; other |= ST_PE_STDCALL; can_add_underscore = 0; } } - if (t & VT_IMPORT) - other |= ST_PE_IMPORT; #endif if (tcc_state->leading_underscore && can_add_underscore) { buf1[0] = '_'; @@ -459,20 +463,15 @@ ST_INLN void sym_free(Sym *sym) } /* 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; s = sym_malloc(); - s->scope = 0; + memset(s, 0, sizeof *s); s->v = v; s->type.t = t; - s->type.ref = NULL; -#ifdef _WIN64 - s->d = NULL; -#endif s->c = c; - s->next = NULL; /* add in stack */ s->prev = *ps; *ps = s; @@ -512,7 +511,7 @@ ST_INLN Sym *sym_find(int v) } /* 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; TokenSym *ts; @@ -535,8 +534,8 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, long c) ps = &ts->sym_identifier; s->prev_tok = *ps; *ps = s; - s->scope = local_scope; - if (s->prev_tok && s->prev_tok->scope == s->scope) + s->sym_scope = local_scope; + if (s->prev_tok && s->prev_tok->sym_scope == s->sym_scope) tcc_error("redeclaration of '%s'", 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 */ -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; 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 */ ST_FUNC void vpush(CType *type) { - CValue cval; - vsetc(type, VT_CONST, &cval); + vset(type, VT_CONST, 0); } /* push integer constant */ @@ -698,7 +696,7 @@ static inline void vpushll(long long 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; @@ -710,7 +708,7 @@ static void vseti(int r, int v) { CType type; type.t = VT_INT; - type.ref = 0; + type.ref = NULL; vset(&type, r, v); } @@ -808,32 +806,36 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r) } /* 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 (!is_compatible_types(&sym->type, type)) + if (type && !is_compatible_types(&sym->type, type)) tcc_error("incompatible types for redefinition of '%s'", - get_tok_str(sym->v, NULL)); - t = type->t; + get_tok_str(sym->v, NULL)); #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'", get_tok_str(sym->v, NULL)); #endif - sym->type.t |= t & (VT_EXPORT|VT_WEAK); - if (t & VT_VIS_MASK) { - int vis = sym->type.t & VT_VIS_MASK; - int vis2 = t & VT_VIS_MASK; - if (vis == (STV_DEFAULT << VT_VIS_SHIFT)) + sym->a.dllexport |= ad->a.dllexport; + sym->a.weak |= ad->a.weak; + if (ad->a.visibility) { + int vis = sym->a.visibility; + int vis2 = ad->a.visibility; + if (vis == STV_DEFAULT) vis = vis2; - else if (vis2 != (STV_DEFAULT << VT_VIS_SHIFT)) + else if (vis2 != STV_DEFAULT) 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' */ -static Sym *external_sym(int v, CType *type, int r) +static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) { Sym *s; s = sym_find(v); @@ -841,14 +843,15 @@ static Sym *external_sym(int v, CType *type, int r) /* push forward reference */ s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); s->type.t |= VT_EXTERN; + s->a = ad->a; + s->sym_scope = 0; } else { if (s->type.ref == func_old_type.ref) { s->type.ref = type->ref; s->r = r | VT_CONST | VT_SYM; s->type.t |= VT_EXTERN; } - patch_storage(s, type); - update_storage(s); + patch_storage(s, ad, type); } return s; } @@ -2024,7 +2027,7 @@ redo: #if PTR_SIZE == 4 if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG) /* XXX: truncate here because gen_opl can't handle ptr + long long */ - gen_cast(&int_type); + gen_cast_s(VT_INT); #endif type1 = vtop[-1].type; type1.t &= ~VT_ARRAY; @@ -2132,6 +2135,7 @@ redo: } vswap(); type1.t = t; + type1.ref = NULL; gen_cast(&type1); vswap(); /* 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. */ +static void gen_cast_s(int t) +{ + CType type; + type.t = t; + type.ref = NULL; + gen_cast(&type); +} + static void gen_cast(CType *type) { int sbt, dbt, sf, df, c, p; @@ -2373,7 +2385,7 @@ static void gen_cast(CType *type) if (sbt == VT_PTR) { /* cast from pointer to int before we apply shift operation, which pointers don't support*/ - gen_cast(&int_type); + gen_cast_s(VT_INT); } gv_dup(); vpushi(31); @@ -2556,12 +2568,12 @@ static int is_compatible_func(CType *type1, CType *type2) if (!is_compatible_types(&s1->type, &s2->type)) return 0; /* check func_call */ - if (s1->a.func_call != s2->a.func_call) + if (s1->f.func_call != s2->f.func_call) return 0; /* 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; - if (s1->c != s2->c) + if (s1->f.func_type != s2->f.func_type) return 0; while (s1 != NULL) { if (s2 == NULL) @@ -2741,7 +2753,7 @@ static void type_to_str(char *buf, int buf_size, case VT_PTR: s = type->ref; 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); goto no_var; } @@ -2880,8 +2892,7 @@ ST_FUNC void vstore(void) && !(vtop->type.t & VT_BITFIELD)) { /* optimize char/short casts */ delayed_cast = VT_MUSTCAST; - vtop->type.t = (ft & VT_TYPE & ~VT_BITFIELD & - ((1 << VT_STRUCT_SHIFT) - 1)); + vtop->type.t = ft & VT_TYPE; /* XXX: factorize */ if (ft & VT_CONSTANT) tcc_warning("assignment of read-only location"); @@ -3084,20 +3095,15 @@ static int exact_log2p1(int i) return ret; } -/* Parse GNUC __attribute__ extension. Currently, the following - 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) - */ +/* Parse __attribute__((...)) GNUC extension. */ static void parse_attribute(AttributeDef *ad) { int t, n; CString astr; - while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) { +redo: + if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2) + return; next(); skip('('); skip('('); @@ -3178,12 +3184,12 @@ static void parse_attribute(AttributeDef *ad) case TOK_CDECL1: case TOK_CDECL2: case TOK_CDECL3: - ad->a.func_call = FUNC_CDECL; + ad->f.func_call = FUNC_CDECL; break; case TOK_STDCALL1: case TOK_STDCALL2: case TOK_STDCALL3: - ad->a.func_call = FUNC_STDCALL; + ad->f.func_call = FUNC_STDCALL; break; #ifdef TCC_TARGET_I386 case TOK_REGPARM1: @@ -3195,30 +3201,30 @@ static void parse_attribute(AttributeDef *ad) else if (n < 0) n = 0; if (n > 0) - ad->a.func_call = FUNC_FASTCALL1 + n - 1; + ad->f.func_call = FUNC_FASTCALL1 + n - 1; skip(')'); break; case TOK_FASTCALL1: case TOK_FASTCALL2: case TOK_FASTCALL3: - ad->a.func_call = FUNC_FASTCALLW; + ad->f.func_call = FUNC_FASTCALLW; break; #endif case TOK_MODE: skip('('); switch(tok) { case TOK_MODE_DI: - ad->a.mode = VT_LLONG + 1; + ad->attr_mode = VT_LLONG + 1; break; case TOK_MODE_QI: - ad->a.mode = VT_BYTE + 1; + ad->attr_mode = VT_BYTE + 1; break; case TOK_MODE_HI: - ad->a.mode = VT_SHORT + 1; + ad->attr_mode = VT_SHORT + 1; break; case TOK_MODE_SI: case TOK_MODE_word: - ad->a.mode = VT_INT + 1; + ad->attr_mode = VT_INT + 1; break; default: tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL)); @@ -3228,10 +3234,10 @@ static void parse_attribute(AttributeDef *ad) skip(')'); break; case TOK_DLLEXPORT: - ad->a.func_export = 1; + ad->a.dllexport = 1; break; case TOK_DLLIMPORT: - ad->a.func_import = 1; + ad->a.dllimport = 1; break; default: if (tcc_state->warn_unsupported) @@ -3255,7 +3261,7 @@ static void parse_attribute(AttributeDef *ad) } skip(')'); skip(')'); - } + goto redo; } static Sym * find_field (CType *type, int v) @@ -3327,7 +3333,7 @@ static void struct_layout(CType *type, AttributeDef *ad) } else { align = typealign; } - if (type->ref->type.t != TOK_STRUCT) { + if (type->ref->type.t == VT_UNION) { if (pcc && bit_size >= 0) size = (bit_size + 7) >> 3; /* 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 */ -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; - long c; + int v, c, size, align, flexible, alignoverride; int bit_size, bsize, bt; Sym *s, *ss, **ps; - AttributeDef ad1; + AttributeDef ad, ad1; CType type1, btype; - a = tok; /* save decl type */ + memset(&ad, 0, sizeof ad); next(); - if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) - parse_attribute(ad); + parse_attribute(&ad); if (tok != '{') { v = tok; next(); @@ -3501,8 +3505,8 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) if (v < TOK_IDENT) expect("struct/union/enum name"); s = struct_find(v); - if (s && (s->scope == local_scope || tok != '{')) { - if (s->type.t != a) + if (s && (s->sym_scope == local_scope || tok != '{')) { + if ((s->type.t & (VT_BTYPE|VT_UNION)) != u) tcc_error("redefinition of '%s'", get_tok_str(v, NULL)); goto do_decl; } @@ -3510,16 +3514,15 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) v = anon_sym++; } /* Record the original enum/struct/union token. */ - type1.t = a; + type1.t = u; type1.ref = NULL; /* we put an undefined size for struct/union */ s = sym_push(v | SYM_STRUCT, &type1, 0, -1); s->r = 0; /* default alignment is zero as gcc */ - /* put struct/union/enum name in type */ - do_decl: - type->t = u; +do_decl: + type->t = u & VT_BTYPE; /* VT_UNION becomes VT_STRUCT */ type->ref = s; - + if (tok == '{') { next(); if (s->c != -1) @@ -3527,7 +3530,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) /* cannot be empty */ c = 0; /* non empty enums are not allowed */ - if (a == TOK_ENUM) { + if (u == VT_ENUM) { int seen_neg = 0; int seen_wide = 0; for(;;) { @@ -3602,7 +3605,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) } } 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; else 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) tcc_error("zero width for bit-field '%s'", get_tok_str(v, NULL)); - if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) - parse_attribute(&ad1); + parse_attribute(&ad1); } size = type_size(&type1, &align); /* Only remember non-default alignment. */ @@ -3632,7 +3634,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) if (ad1.a.aligned) { int speca = 1 << (ad1.a.aligned - 1); alignoverride = speca; - } else if (ad1.a.packed || ad->a.packed) { + } else if (ad1.a.packed || ad.a.packed) { alignoverride = 1; } else if (*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('}'); - if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) - parse_attribute(ad); - struct_layout(type, ad); + parse_attribute(&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 are added to the element type, copied because it could be a typedef. */ 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) { - int t, u, bt_size, complete, type_found, typespec_found, g; + int t, u, bt, st, type_found, typespec_found, g; Sym *s; CType type1; memset(ad, 0, sizeof(AttributeDef)); - complete = 0; type_found = 0; typespec_found = 0; - t = 0; + t = VT_INT; + bt = st = -1; + type->ref = NULL; + while(1) { switch(tok) { case TOK_EXTENSION: @@ -3735,12 +3732,17 @@ static int parse_btype(CType *type, AttributeDef *ad) basic_type: next(); basic_type1: - if (complete) - tcc_error("too many basic types"); - t |= u; - bt_size = is_btype_size (u & VT_BTYPE); - if (u == VT_INT || (!bt_size && !(t & VT_TYPEDEF))) - complete = 1; + if (u == VT_SHORT || u == VT_LONG) { + if (st != -1 || (bt != -1 && bt != VT_INT)) + tmbt: tcc_error("too many basic types"); + st = u; + } else { + if (bt != -1 || (st != -1 && u != VT_INT)) + goto tmbt; + bt = u; + } + if (u != VT_INT) + t = (t & ~VT_BTYPE) | u; typespec_found = 1; break; case TOK_VOID: @@ -3753,7 +3755,6 @@ static int parse_btype(CType *type, AttributeDef *ad) u = VT_INT; goto basic_type; case TOK_LONG: - next(); if ((t & VT_BTYPE) == VT_DOUBLE) { #ifndef TCC_TARGET_PE t = (t & ~VT_BTYPE) | VT_LDOUBLE; @@ -3762,8 +3763,9 @@ static int parse_btype(CType *type, AttributeDef *ad) t = (t & ~VT_BTYPE) | VT_LLONG; } else { u = VT_LONG; - goto basic_type1; + goto basic_type; } + next(); break; #ifdef TCC_TARGET_ARM64 case TOK_UINT128: @@ -3779,7 +3781,6 @@ static int parse_btype(CType *type, AttributeDef *ad) u = VT_FLOAT; goto basic_type; case TOK_DOUBLE: - next(); if ((t & VT_BTYPE) == VT_LONG) { #ifdef TCC_TARGET_PE t = (t & ~VT_BTYPE) | VT_DOUBLE; @@ -3788,18 +3789,21 @@ static int parse_btype(CType *type, AttributeDef *ad) #endif } else { u = VT_DOUBLE; - goto basic_type1; + goto basic_type; } + next(); break; case TOK_ENUM: - struct_decl(&type1, ad, VT_ENUM); + struct_decl(&type1, VT_ENUM); basic_type2: u = type1.t; type->ref = type1.ref; goto basic_type1; case TOK_STRUCT: + struct_decl(&type1, VT_STRUCT); + goto basic_type2; case TOK_UNION: - struct_decl(&type1, ad, VT_STRUCT); + struct_decl(&type1, VT_UNION); goto basic_type2; /* type modifiers */ @@ -3824,9 +3828,9 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_SIGNED3: if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED)) tcc_error("signed and unsigned modifier"); - typespec_found = 1; t |= VT_DEFSIGN; next(); + typespec_found = 1; break; case TOK_REGISTER: case TOK_AUTO: @@ -3870,8 +3874,8 @@ static int parse_btype(CType *type, AttributeDef *ad) case TOK_ATTRIBUTE1: case TOK_ATTRIBUTE2: parse_attribute(ad); - if (ad->a.mode) { - u = ad->a.mode -1; + if (ad->attr_mode) { + u = ad->attr_mode -1; t = (t & ~VT_BTYPE) | u; } break; @@ -3890,24 +3894,23 @@ static int parse_btype(CType *type, AttributeDef *ad) s = sym_find(tok); if (!s || !(s->type.t & VT_TYPEDEF)) goto the_end; - - type->t = ((s->type.t & ~VT_TYPEDEF) | - (t & ~(VT_CONSTANT | VT_VOLATILE))); + t &= ~VT_BTYPE; + u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u; + type->t = (s->type.t & ~VT_TYPEDEF) | u; type->ref = s->type.ref; - if (t & (VT_CONSTANT | VT_VOLATILE)) - parse_btype_qualify(type, t & (VT_CONSTANT | VT_VOLATILE)); + if (t) + parse_btype_qualify(type, t); t = type->t; - - if (s->r) { - /* get attributes from typedef */ - 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; - } + /* get attributes from typedef */ + if (s->a.aligned && 0 == ad->a.aligned) + ad->a.aligned = s->a.aligned; + if (s->f.func_call && 0 == ad->f.func_call) + ad->f.func_call = s->f.func_call; + if (s->a.packed) + ad->a.packed = 1; next(); typespec_found = 1; + st = bt = -2; break; } type_found = 1; @@ -4037,9 +4040,11 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) mk_pointer(type); } /* we push a anonymous symbol which will contain the function prototype */ - ad->a.func_args = arg_size; - s = sym_push(SYM_FIELD, type, 0, l); + ad->f.func_args = arg_size; + ad->f.func_type = l; + s = sym_push(SYM_FIELD, type, 0, 0); s->a = ad->a; + s->f = ad->f; s->next = first; type->t = VT_FUNC; 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). */ /* XXX: this is not correct to modify 'ad' at this point, but 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); skip(')'); } @@ -4174,8 +4178,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td) *v = 0; } post_type(post, ad, storage, 0); - if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) - parse_attribute(ad); + parse_attribute(ad); type->t |= storage; return ret; } @@ -4226,13 +4229,12 @@ static void gfunc_param_typed(Sym *func, Sym *arg) int func_type; CType type; - func_type = func->c; + func_type = func->f.func_type; if (func_type == FUNC_OLD || (func_type == FUNC_ELLIPSIS && arg == NULL)) { /* default casting : only need to convert float to double */ if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) { - type.t = VT_DOUBLE; - gen_cast(&type); + gen_cast_s(VT_DOUBLE); } else if (vtop->type.t & VT_BITFIELD) { type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); type.ref = vtop->type.ref; @@ -4318,6 +4320,7 @@ ST_FUNC void unary(void) sizeof_caller = in_sizeof; in_sizeof = 0; + type.ref = NULL; /* XXX: GCC 2.95.3 does not generate a table although it should be better here */ tok_next: @@ -4331,7 +4334,6 @@ ST_FUNC void unary(void) t = VT_INT; push_tokc: type.t = t; - type.ref = 0; vsetc(&type, VT_CONST, &tokc); next(); break; @@ -4464,9 +4466,7 @@ ST_FUNC void unary(void) next(); unary(); if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - CType boolean; - boolean.t = VT_BOOL; - gen_cast(&boolean); + gen_cast_s(VT_BOOL); vtop->c.i = !vtop->c.i; } else if ((vtop->r & VT_VALMASK) == VT_CMP) vtop->c.i ^= 1; @@ -4567,7 +4567,6 @@ ST_FUNC void unary(void) { int tok1 = tok; int level; - CType type; next(); skip('('); if (tok != TOK_CINT) { @@ -4629,7 +4628,6 @@ ST_FUNC void unary(void) break; } case TOK___va_arg: { - CType type; parse_builtin_params(0, "et"); type = vtop->type; vpop(); @@ -4895,7 +4893,7 @@ 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) { - variadic = (s->c == FUNC_ELLIPSIS); + variadic = (s->f.func_type == FUNC_ELLIPSIS); ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, &ret_align, ®size); if (!ret_nregs) { @@ -5100,9 +5098,7 @@ static void expr_land(void) int t = 0; for(;;) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - CType ctb; - ctb.t = VT_BOOL; - gen_cast(&ctb); + gen_cast_s(VT_BOOL); if (vtop->c.i) { vpop(); } else { @@ -5115,7 +5111,7 @@ static void expr_land(void) nocode_wanted--; if (t) gsym(t); - gen_cast(&int_type); + gen_cast_s(VT_INT); break; } } else { @@ -5143,9 +5139,7 @@ static void expr_lor(void) int t = 0; for(;;) { if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - CType ctb; - ctb.t = VT_BOOL; - gen_cast(&ctb); + gen_cast_s(VT_BOOL); if (!vtop->c.i) { vpop(); } else { @@ -5158,7 +5152,7 @@ static void expr_lor(void) nocode_wanted--; if (t) gsym(t); - gen_cast(&int_type); + gen_cast_s(VT_INT); break; } } else { @@ -5186,12 +5180,9 @@ static int condition_3way(void) { int c = -1; if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && - (!(vtop->r & VT_SYM) || - !(vtop->sym->type.t & VT_WEAK))) { - CType boolean; - boolean.t = VT_BOOL; + (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { vdup(); - gen_cast(&boolean); + gen_cast_s(VT_BOOL); c = vtop->c.i; vpop(); } @@ -5262,6 +5253,8 @@ static void expr_cond(void) bt1 = t1 & VT_BTYPE; t2 = type2.t; bt2 = t2 & VT_BTYPE; + type.ref = NULL; + /* cast operands to correct type according to ISOC rules */ if (is_float(bt1) || is_float(bt2)) { 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->sym->v < SYM_FIRST_ANOM)) #ifdef TCC_TARGET_PE - || (vtop->type.t & VT_IMPORT) + || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport) #endif - ) + ) tcc_error("initializer element is not constant"); break; case EXPR_ANY: @@ -6448,7 +6441,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, if (no_oblock && len >= n*size1) break; } else { - if (s->type.t == TOK_UNION) + if (s->type.t == VT_UNION) f = NULL; else f = f->next; @@ -6521,6 +6514,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, TokenString *init_str = NULL; Section *sec; Sym *flexible_array; + Sym *sym = NULL; flexible_array = NULL; 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; } #endif - sym_push(v, type, r, addr); + sym = sym_push(v, type, r, addr); + sym->a = ad->a; } else { /* push local reference */ vset(type, r, addr); } } else { - Sym *sym = NULL; if (v && scope == VT_CONST) { /* see if the symbol was already defined */ sym = sym_find(v); if (sym) { - patch_storage(sym, type); + patch_storage(sym, ad, type); if (sym->type.t & VT_EXTERN) { /* if the variable is extern, it was not allocated */ 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 must play with the SHN_COMMON type of the symbol */ /* no init data, we won't add more to the symbol */ - update_storage(sym); goto no_alloc; } else if (sym->c) { ElfW(Sym) *esym; @@ -6679,7 +6672,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if (v) { if (!sym) { sym = sym_push(v, type, r | VT_SYM, 0); - sym->asm_label = ad->asm_label; + patch_storage(sym, ad, NULL); } /* update symbol definition */ 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 declaration list */ 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); } @@ -6913,20 +6906,18 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) expect(";"); } - if (ad.a.weak) - type.t |= VT_WEAK; #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)) tcc_error("cannot have dll linkage with static or typedef"); - if (ad.a.func_export) - type.t |= VT_EXPORT; - else if ((type.t & VT_BTYPE) != VT_FUNC) - type.t |= VT_IMPORT|VT_EXTERN; + if (ad.a.dllimport) { + if ((type.t & VT_BTYPE) == VT_FUNC) + ad.a.dllimport = 0; + else + type.t |= VT_EXTERN; + } } #endif - type.t |= ad.a.visibility << VT_VIS_SHIFT; - if (tok == '{') { if (l != VT_CONST) 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; /* use func_call from prototype if not defined */ - if (ref->a.func_call != FUNC_CDECL - && type.ref->a.func_call == FUNC_CDECL) - type.ref->a.func_call = ref->a.func_call; + if (ref->f.func_call != FUNC_CDECL + && type.ref->f.func_call == FUNC_CDECL) + type.ref->f.func_call = ref->f.func_call; /* use static from prototype */ 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 one from prototype. */ - if (! (type.t & VT_VIS_MASK)) - type.t |= sym->type.t & VT_VIS_MASK; - + if (!type.ref->a.visibility) + type.ref->a.visibility = ref->a.visibility; /* 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)) { func_error1: tcc_error("incompatible types for redefinition of '%s'", 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)); /* if symbol is already defined, then put complete 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->a.func_body = 1; + sym->type.ref->f.func_body = 1; sym->r = VT_SYM | VT_CONST; + patch_storage(sym, &ad, NULL); /* static inline functions are just recorded as a kind of macro. Their code will be emitted at the end of @@ -7035,7 +7027,7 @@ found: /* save typedefed type */ /* XXX: test storage specifiers ? */ sym = sym_find(v); - if (sym && sym->scope == local_scope) { + if (sym && sym->sym_scope == local_scope) { if (!is_compatible_types(&sym->type, &type) || !(sym->type.t & VT_TYPEDEF)) tcc_error("incompatible redefinition of '%s'", @@ -7066,13 +7058,11 @@ found: /* NOTE: as GCC, uninitialized global static arrays of null size are considered as extern */ - sym = external_sym(v, &type, r); - sym->asm_label = ad.asm_label; + sym = external_sym(v, &type, r, &ad); if (ad.alias_target) { Section tsec; ElfW(Sym) *esym; Sym *alias_target; - alias_target = sym_find(ad.alias_target); if (!alias_target || !alias_target->c) tcc_error("unsupported forward __alias__ attribute"); diff --git a/tccpe.c b/tccpe.c index 78a43c5..366f0e7 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1477,7 +1477,7 @@ ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2) int r2; if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST)) return sv; - if (!(sv->sym->type.t & VT_IMPORT)) + if (!sv->sym->a.dllimport) 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)); memset(v2, 0, sizeof *v2); diff --git a/x86_64-gen.c b/x86_64-gen.c index 1873a9d..feedc12 100644 --- a/x86_64-gen.c +++ b/x86_64-gen.c @@ -239,7 +239,7 @@ static int oad(int c, int s) /* generate jmp to a label */ #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) 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 */ -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) 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 implicit pointer parameter */ func_vt = sym->type; - func_var = (sym->c == FUNC_ELLIPSIS); + func_var = (sym->f.func_type == FUNC_ELLIPSIS); size = gfunc_arg_size(&func_vt); if (!using_regs(size)) { 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) { - 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); 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 */ gcall_or_jmp(0); if (args_size) @@ -1425,7 +1425,7 @@ void gfunc_prolog(CType *func_type) func_sub_sp_offset = ind; 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; seen_reg_num = seen_sse_num = 0; /* frame pointer and return address */