From 498551188e84ac5297db8a7e025fd0beef7b50e3 Mon Sep 17 00:00:00 2001 From: bellard Date: Sat, 22 Dec 2001 17:05:23 +0000 Subject: [PATCH] last patches to separate type and value handling --- i386-gen.c | 2 +- tcc.c | 301 ++++++++++++++++++++++++++++------------------------- 2 files changed, 160 insertions(+), 143 deletions(-) diff --git a/i386-gen.c b/i386-gen.c index b52eec9a..8e7c2f46 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -122,7 +122,7 @@ void greloc_patch(Sym *s, int val) p = p1; } s->c = val; - s->t &= ~VT_FORWARD; + s->r &= ~VT_FORWARD; } /* output a symbol and patch all calls to it */ diff --git a/tcc.c b/tcc.c index aec3d473..855e8e9e 100644 --- a/tcc.c +++ b/tcc.c @@ -79,6 +79,7 @@ typedef struct SValue { typedef struct Sym { int v; /* symbol token */ int t; /* associated type */ + int r; /* associated register */ int c; /* associated number */ struct Sym *next; /* next related symbol */ struct Sym *prev; /* prev symbol in stack */ @@ -165,49 +166,47 @@ int gnu_ext = 1; int tcc_ext = 1; /* The current value can be: */ -#define VT_VALMASK 0x000f -#define VT_CONST 0x000a /* constant in vc +#define VT_VALMASK 0x00ff +#define VT_CONST 0x00f0 /* constant in vc (must be first non register value) */ -#define VT_LLOCAL 0x000b /* lvalue, offset on stack */ -#define VT_LOCAL 0x000c /* offset on stack */ -#define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */ -#define VT_JMP 0x000e /* value is the consequence of jmp true */ -#define VT_JMPI 0x000f /* value is the consequence of jmp false */ -#define VT_LVAL 0x0010 /* var is an lvalue */ -#define VT_LVALN -17 /* ~VT_LVAL */ -#define VT_FORWARD 0x0020 /* value is forward reference - (only used for functions) */ -/* storage */ -#define VT_EXTERN 0x00000040 /* extern definition */ -#define VT_STATIC 0x00000080 /* static variable */ -#define VT_TYPEDEF 0x00000100 /* typedef definition */ +#define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */ +#define VT_LOCAL 0x00f2 /* offset on stack */ +#define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */ +#define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */ +#define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */ +#define VT_LVAL 0x0100 /* var is an lvalue */ +#define VT_FORWARD 0x0200 /* value is forward reference */ /* types */ #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */ -#define VT_BTYPE_SHIFT 9 -#define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */ -#define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */ -#define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */ -#define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */ -#define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */ -#define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */ -#define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */ -#define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */ -#define VT_FLOAT (8 << VT_BTYPE_SHIFT) /* IEEE float */ -#define VT_DOUBLE (9 << VT_BTYPE_SHIFT) /* IEEE double */ -#define VT_LDOUBLE (10 << VT_BTYPE_SHIFT) /* IEEE long double */ -#define VT_BOOL (11 << VT_BTYPE_SHIFT) /* ISOC99 boolean type */ -#define VT_LLONG (12 << VT_BTYPE_SHIFT) /* 64 bit integer */ -#define VT_LONG (13 << VT_BTYPE_SHIFT) /* long integer (NEVER - USED as type, only - during parsing) */ -#define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */ -#define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */ -#define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */ -#define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */ +#define VT_INT 0 /* integer 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 increment */ +#define VT_ENUM 5 /* enum definition */ +#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_BTYPE 0x000f /* mask for basic type */ +#define VT_UNSIGNED 0x0010 /* unsigned type */ +#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ +#define VT_BITFIELD 0x0040 /* bitfield modifier */ -#define VT_TYPE 0xfffffe00 /* type mask */ +/* storage */ +#define VT_EXTERN 0x00000080 /* extern definition */ +#define VT_STATIC 0x00000100 /* static variable */ +#define VT_TYPEDEF 0x00000200 /* typedef definition */ + +/* type mask (except storage) */ +#define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF)) /* token values */ @@ -339,8 +338,8 @@ int expr_const(void); void expr_eq(void); void gexpr(void); void decl(int l); -void decl_initializer(int t, int c, int first, int size_only); -int decl_initializer_alloc(int t, int has_init); +void decl_initializer(int t, int r, int c, int first, int size_only); +int decl_initializer_alloc(int t, int sec, int has_init); int gv(void); void move_reg(int r, int s); void save_reg(int r); @@ -358,7 +357,7 @@ void vstore(void); int type_size(int t, int *a); int pointed_type(int t); int pointed_size(int t); -int ist(void); +int parse_btype(int *type_ptr); int type_decl(int *v, int t, int td); void error(const char *fmt, ...); void vset(int t, int r, int v); @@ -668,12 +667,15 @@ Sym *sym_find(int v) } /* push a given symbol on the symbol stack */ -Sym *sym_push(int v, int t, int c) +Sym *sym_push(int v, int t, int r, int c) { + Sym *s; if (local_stack.top) - return sym_push1(&local_stack, v, t, c); + s = sym_push1(&local_stack, v, t, c); else - return sym_push1(&global_stack, v, t, c); + s = sym_push1(&global_stack, v, t, c); + s->r = r; + return s; } /* pop symbols until top reaches 'b' */ @@ -2354,9 +2356,9 @@ void gen_cast(int t) do_ftoi: gen_cvt_ftoi(dt1); } - if (dt1 == VT_INT && (t & (VT_TYPE | VT_UNSIGNED)) != dt1) { + if (dt1 == VT_INT && (t & (VT_BTYPE | VT_UNSIGNED)) != dt1) { /* additionnal cast for char/short/bool... */ - vtop->t = (vtop->t & ~VT_TYPE) | dt1; + vtop->t = dt1; gen_cast(t); } } else if (dbt == VT_BOOL) { @@ -2436,7 +2438,7 @@ int mk_pointer(int t) { int p; p = anon_sym++; - sym_push(p, t, -1); + sym_push(p, t, 0, -1); return VT_PTR | (p << VT_STRUCT_SHIFT) | (t & ~VT_TYPE); } @@ -2744,7 +2746,7 @@ int struct_decl(int u) } else { v = anon_sym++; } - s = sym_push(v | SYM_STRUCT, a, 0); + s = sym_push(v | SYM_STRUCT, a, 0, 0); /* put struct/union/enum name in type */ do_decl: u = u | (v << VT_STRUCT_SHIFT); @@ -2768,12 +2770,12 @@ int struct_decl(int u) c = expr_const(); } /* enum symbols have static storage */ - sym_push(v, VT_CONST | VT_STATIC, c); + sym_push(v, VT_STATIC | VT_INT, VT_CONST, c); if (tok == ',') next(); c++; } else { - b = ist(); + parse_btype(&b); while (1) { bit_size = -1; v = 0; @@ -2858,7 +2860,7 @@ int struct_decl(int u) } printf("\n"); #endif - ss = sym_push(v | SYM_FIELD, t, offset); + ss = sym_push(v | SYM_FIELD, t, 0, offset); *ps = ss; ps = &ss->next; } @@ -2880,13 +2882,13 @@ int struct_decl(int u) /* return 0 if no type declaration. otherwise, return the basic type and skip it. - XXX: A '2' is ored to ensure non zero return if int type. */ -int ist(void) +int parse_btype(int *type_ptr) { - int t, u; + int t, u, type_found; Sym *s; + type_found = 0; t = 0; while(1) { switch(tok) { @@ -2979,13 +2981,14 @@ int ist(void) next(); break; } - t |= 2; + type_found = 1; } the_end: /* long is never used as type */ if ((t & VT_BTYPE) == VT_LONG) t = (t & ~VT_BTYPE) | VT_INT; - return t; + *type_ptr = t; + return type_found; } int post_type(int t) @@ -3002,7 +3005,7 @@ int post_type(int t) while (tok != ')') { /* read param name and compute offset */ if (l != FUNC_OLD) { - if (!(pt = ist())) { + if (!parse_btype(&pt)) { if (l) { error("invalid type"); } else { @@ -3024,7 +3027,7 @@ int post_type(int t) } /* array must be transformed to pointer according to ANSI C */ pt &= ~VT_ARRAY; - s = sym_push(n | SYM_FIELD, pt, 0); + s = sym_push(n | SYM_FIELD, pt, 0, 0); *plast = s; plast = &s->next; if (tok == ',') { @@ -3044,7 +3047,7 @@ int post_type(int t) t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN)); /* we push a anonymous symbol which will contain the function prototype */ p = anon_sym++; - s = sym_push(p, t, l); + s = sym_push(p, t, 0, l); s->next = first; t = t1 | VT_FUNC | (p << VT_STRUCT_SHIFT); } else if (tok == '[') { @@ -3064,7 +3067,7 @@ int post_type(int t) /* we push a anonymous symbol which will contain the array element type */ p = anon_sym++; - sym_push(p, t, n); + sym_push(p, t, 0, n); t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT); } return t; @@ -3077,7 +3080,6 @@ int type_decl(int *v, int t, int td) int u, p; Sym *s; - t = t & -3; /* suppress the ored '2' */ while (tok == '*') { next(); while (tok == TOK_CONST || tok == TOK_VOLATILE || tok == TOK_RESTRICT) @@ -3120,14 +3122,15 @@ int type_decl(int *v, int t, int td) } /* define a new external reference to a function 'v' of type 'u' */ -Sym *external_sym(int v, int u) +Sym *external_sym(int v, int u, int r) { Sym *s; s = sym_find(v); if (!s) { /* push forward reference */ s = sym_push1(&global_stack, - v, u | VT_CONST | VT_FORWARD, 0); + v, u, 0); + s->r = r | VT_CONST | VT_FORWARD; } return s; } @@ -3163,7 +3166,7 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg) void unary(void) { - int n, t, ft, fc, p, align, size; + int n, t, ft, fc, p, align, size, r; Sym *s; GFuncContext gf; @@ -3197,8 +3200,8 @@ void unary(void) glo = (glo + align - 1) & -align; fc = glo; /* we must declare it as an array first to use initializer parser */ - t = VT_CONST | VT_ARRAY | mk_pointer(t); - decl_initializer(t, glo, 1, 0); + t = VT_ARRAY | mk_pointer(t); + decl_initializer(t, VT_CONST, glo, 1, 0); glo += type_size(t, &align); /* put it as pointer */ vset(t & ~VT_ARRAY, VT_CONST, fc); @@ -3207,21 +3210,21 @@ void unary(void) next(); if (t == '(') { /* cast ? */ - if (t = ist()) { + if (parse_btype(&t)) { ft = type_decl(&n, t, TYPE_ABSTRACT); skip(')'); /* check ISOC99 compound literal */ if (tok == '{') { /* data is allocated locally by default */ if (global_expr) - ft |= VT_CONST; + r = VT_CONST; else - ft |= VT_LOCAL; + r = VT_LOCAL; /* all except arrays are lvalues */ if (!(ft & VT_ARRAY)) - ft |= VT_LVAL; - fc = decl_initializer_alloc(ft, 1); - vset(ft & VT_TYPE, ft & (VT_VALMASK | VT_LVAL), fc); + r |= VT_LVAL; + fc = decl_initializer_alloc(ft, r, 1); + vset(ft, r, fc); } else { unary(); gen_cast(ft); @@ -3264,9 +3267,9 @@ void unary(void) if (t == TOK_SIZEOF) { if (tok == '(') { next(); - if (t = ist()) + if (parse_btype(&t)) { t = type_decl(&n, t, TYPE_ABSTRACT); - else { + } else { /* XXX: some code could be generated: add eval flag */ gexpr(); @@ -3299,10 +3302,9 @@ void unary(void) p = anon_sym++; sym_push1(&global_stack, p, 0, FUNC_OLD); /* int() function */ - s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT)); + s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0); } - vset(s->t & VT_TYPE, - s->t & (VT_VALMASK | VT_LVAL | VT_FORWARD), s->c); + vset(s->t, s->r, s->c); /* if forward reference, we must point to s */ if (vtop->r & VT_FORWARD) vtop->c.sym = s; @@ -3880,7 +3882,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) address. cur_index/cur_field is the pointer to the current value. 'size_only' is true if only size info is needed (only used in arrays) */ -void decl_designator(int t, int c, +void decl_designator(int t, int r, int c, int *cur_index, Sym **cur_field, int size_only) { @@ -3949,25 +3951,36 @@ void decl_designator(int t, int c, c += f->c; } } - decl_initializer(t, c, 0, size_only); + decl_initializer(t, r, c, 0, size_only); } -/* store a value or an expression directly in global data or in local array */ +#define EXPR_VAL 0 +#define EXPR_CONST 1 +#define EXPR_ANY 2 -void init_putv(int t, int c, int v, int is_expr) +/* store a value or an expression directly in global data or in local array */ +void init_putv(int t, int r, int c, + int v, int expr_type) { int saved_global_expr, bt; - if ((t & VT_VALMASK) == VT_CONST) { - if (is_expr) { - /* compound literals must be allocated globally in this case */ - saved_global_expr = global_expr; - global_expr = 1; - expr_const1(); - global_expr = saved_global_expr; - } else { - vpushi(v); - } + switch(expr_type) { + case EXPR_VAL: + vpushi(v); + break; + case EXPR_CONST: + /* compound literals must be allocated globally in this case */ + saved_global_expr = global_expr; + global_expr = 1; + expr_const1(); + global_expr = saved_global_expr; + break; + case EXPR_ANY: + expr_eq(); + break; + } + + if ((r & VT_VALMASK) == VT_CONST) { /* XXX: do casting */ /* XXX: not portable */ bt = vtop->t & VT_BTYPE; @@ -3995,22 +4008,19 @@ void init_putv(int t, int c, int v, int is_expr) } vpop(); } else { - vset(t & VT_TYPE, t & (VT_VALMASK | VT_LVAL | VT_FORWARD), c); - if (is_expr) - expr_eq(); - else - vpushi(v); + vset(t, r, c); + vswap(); vstore(); vpop(); } } /* put zeros for variable based init */ -void init_putz(int t, int c, int size) +void init_putz(int t, int r, int c, int size) { GFuncContext gf; - if ((t & VT_VALMASK) == VT_CONST) { + if ((r & VT_VALMASK) == VT_CONST) { /* nothing to do because global are already set to zero */ } else { gfunc_start(&gf); @@ -4029,10 +4039,10 @@ void init_putz(int t, int c, int size) object. 'first' is true if array '{' must be read (multi dimension implicit array init handling). 'size_only' is true if size only evaluation is wanted (only for arrays). */ -void decl_initializer(int t, int c, int first, int size_only) +void decl_initializer(int t, int r, int c, int first, int size_only) { int index, array_length, n, no_oblock, nb, parlevel, i; - int t1, size1, align1; + int t1, size1, align1, expr_type; Sym *s, *f; TokenSym *ts; @@ -4067,8 +4077,8 @@ void decl_initializer(int t, int c, int first, int size_only) if (ts->len > nb) warning("initializer-string for array is too long"); for(i=0;istr[i], 0); + init_putv(t1, r, c + (array_length + i) * size1, + ts->str[i], EXPR_VAL); } } array_length += nb; @@ -4078,20 +4088,20 @@ void decl_initializer(int t, int c, int first, int size_only) warning in this case since it is standard) */ if (n < 0 || array_length < n) { if (!size_only) { - init_putv(t1, c + (array_length * size1), 0, 0); + init_putv(t1, r, c + (array_length * size1), 0, EXPR_VAL); } array_length++; } } else { index = 0; while (tok != '}') { - decl_designator(t, c, &index, NULL, size_only); + decl_designator(t, r, c, &index, NULL, size_only); if (n >= 0 && index >= n) error("index too large"); /* must put zero in holes (note that doing it that way ensures that it even works with designators) */ if (!size_only && array_length < index) { - init_putz(t1, c + array_length * size1, + init_putz(t1, r, c + array_length * size1, (index - array_length) * size1); } index++; @@ -4111,7 +4121,7 @@ void decl_initializer(int t, int c, int first, int size_only) skip('}'); /* put zeros at the end */ if (!size_only && n >= 0 && array_length < n) { - init_putz(t1, c + array_length * size1, + init_putz(t1, r, c + array_length * size1, (n - array_length) * size1); } /* patch type size if needed */ @@ -4126,11 +4136,11 @@ void decl_initializer(int t, int c, int first, int size_only) index = 0; n = s->c; while (tok != '}') { - decl_designator(t, c, NULL, &f, size_only); + decl_designator(t, r, c, NULL, &f, size_only); /* fill with zero between fields */ index = f->c; if (!size_only && array_length < index) { - init_putz(t, c + array_length, + init_putz(t, r, c + array_length, index - array_length); } index = index + type_size(f->t, &align1); @@ -4143,13 +4153,13 @@ void decl_initializer(int t, int c, int first, int size_only) } /* put zeros at the end */ if (!size_only && array_length < n) { - init_putz(t, c + array_length, + init_putz(t, r, c + array_length, n - array_length); } skip('}'); } else if (tok == '{') { next(); - decl_initializer(t, c, first, size_only); + decl_initializer(t, r, c, first, size_only); skip('}'); } else if (size_only) { /* just skip expression */ @@ -4163,14 +4173,19 @@ void decl_initializer(int t, int c, int first, int size_only) next(); } } else { - init_putv(t, c, 0, 1); + /* currently, we always use constant expression for globals + (may change for scripting case) */ + expr_type = EXPR_CONST; + if ((r & VT_VALMASK) == VT_LOCAL) + expr_type = EXPR_ANY; + init_putv(t, r, c, 0, expr_type); } } /* parse an initializer for type 't' if 'has_init' is true, and - allocate space in local or global data space. The allocated address - in returned */ -int decl_initializer_alloc(int t, int has_init) + allocate space in local or global data space ('r' is either + VT_LOCAL or VT_CONST). The allocated address in returned */ +int decl_initializer_alloc(int t, int r, int has_init) { int size, align, addr, tok1; int *init_str, init_len, level, *saved_macro_ptr; @@ -4212,7 +4227,7 @@ int decl_initializer_alloc(int t, int has_init) saved_macro_ptr = macro_ptr; macro_ptr = init_str; next(); - decl_initializer(t, 0, 1, 1); + decl_initializer(t, r, 0, 1, 1); /* prepare second initializer parsing */ macro_ptr = init_str; next(); @@ -4222,7 +4237,7 @@ int decl_initializer_alloc(int t, int has_init) if (size < 0) error("unknown type size"); } - if ((t & VT_VALMASK) == VT_LOCAL) { + if ((r & VT_VALMASK) == VT_LOCAL) { loc = (loc - size) & -align; addr = loc; } else { @@ -4235,7 +4250,7 @@ int decl_initializer_alloc(int t, int has_init) glo += size; } if (has_init) { - decl_initializer(t, addr, 1, 0); + decl_initializer(t, r, addr, 1, 0); /* restore parse state if needed */ if (init_str) { free(init_str); @@ -4250,12 +4265,11 @@ int decl_initializer_alloc(int t, int has_init) /* 'l' is VT_LOCAL or VT_CONST to define default storage type */ void decl(int l) { - int *a, t, b, v, u, addr, has_init, size, align; + int *a, t, b, v, addr, has_init, size, align, r, u; Sym *sym; while (1) { - b = ist(); - if (!b) { + if (!parse_btype(&b)) { /* skip redundant ';' */ /* XXX: find more elegant solution */ if (tok == ';') { @@ -4290,13 +4304,14 @@ void decl(int l) if (!(t & VT_FUNC)) expect("function definition"); /* patch forward references */ - if ((sym = sym_find(v)) && (sym->t & VT_FORWARD)) { + if ((sym = sym_find(v)) && (sym->r & VT_FORWARD)) { greloc_patch(sym, ind); - sym->t = VT_CONST | t; + sym->t = t; } else { /* put function address */ - sym_push1(&global_stack, v, VT_CONST | t, ind); + sym = sym_push1(&global_stack, v, t, ind); } + sym->r = VT_CONST; funcname = get_tok_str(v, NULL); /* push a dummy symbol to enable local sym storage */ sym_push1(&local_stack, 0, 0, 0); @@ -4314,9 +4329,8 @@ void decl(int l) } while (sym = sym->next) { u = sym->t; - sym_push(sym->v & ~SYM_FIELD, - u | VT_LOCAL | VT_LVAL, - addr); + sym_push(sym->v & ~SYM_FIELD, u, + VT_LOCAL | VT_LVAL, addr); size = type_size(u, &align); size = (size + 3) & ~3; #ifdef FUNC_STRUCT_PARAM_AS_PTR @@ -4345,40 +4359,42 @@ void decl(int l) if (b & VT_TYPEDEF) { /* save typedefed type */ /* XXX: test storage specifiers ? */ - sym_push(v, t | VT_TYPEDEF, 0); + sym_push(v, t | VT_TYPEDEF, 0, 0); } else if ((t & VT_BTYPE) == VT_FUNC) { /* external function definition */ - external_sym(v, t); + external_sym(v, t, 0); } else { /* not lvalue if array */ + r = 0; if (!(t & VT_ARRAY)) - t |= VT_LVAL; + r |= VT_LVAL; if (b & VT_EXTERN) { /* external variable */ - external_sym(v, t); + external_sym(v, t, r); } else { - u = l; if (t & VT_STATIC) - u = VT_CONST; - u |= t; + r |= VT_CONST; + else + r |= l; has_init = (tok == '='); if (has_init) next(); - addr = decl_initializer_alloc(u, has_init); + addr = decl_initializer_alloc(t, r, + has_init); if (l == VT_CONST) { /* global scope: see if already defined */ sym = sym_find(v); if (!sym) goto do_def; - if (!is_compatible_types(sym->t, u)) + if (!is_compatible_types(sym->t, t)) error("incompatible types for redefinition of '%s'", get_tok_str(v, NULL)); - if (!(sym->t & VT_FORWARD)) + if (!(sym->r & VT_FORWARD)) error("redefinition of '%s'", get_tok_str(v, NULL)); greloc_patch(sym, addr); } else { do_def: - sym_push(v, u, addr); + sym_push(v, t, r, addr); } } } @@ -4411,11 +4427,12 @@ void resolve_global_syms(void) ext_sym = sym_find1(&extern_stack, s->v); if (!ext_sym) { /* if the symbol do not exist, we simply save it */ - sym_push1(&extern_stack, s->v, s->t, s->c); - } else if (ext_sym->t & VT_FORWARD) { + ext_sym = sym_push1(&extern_stack, s->v, s->t, s->c); + ext_sym->r = s->r; + } else if (ext_sym->r & VT_FORWARD) { /* external symbol already exists, but only as forward definition */ - if (!(s->t & VT_FORWARD)) { + if (!(s->r & VT_FORWARD)) { /* s is not forward, so we can relocate all symbols */ greloc_patch(ext_sym, s->c); } else { @@ -4428,7 +4445,7 @@ void resolve_global_syms(void) } else { /* external symbol already exists and is defined : patch all references to it */ - if (!(s->t & VT_FORWARD)) + if (!(s->r & VT_FORWARD)) error("'%s' defined twice", get_tok_str(s->v, NULL)); greloc_patch(s, ext_sym->c); } @@ -4497,7 +4514,7 @@ void resolve_extern_syms(void) s = extern_stack.top; while (s != NULL) { s1 = s->prev; - if (s->t & VT_FORWARD) { + if (s->r & VT_FORWARD) { /* if there is at least one relocation to do, then find it and patch it */ if (s->c) { @@ -4601,7 +4618,7 @@ int main(int argc, char **argv) return 0; } else { s = sym_find1(&extern_stack, TOK_MAIN); - if (!s || (s->t & VT_FORWARD)) + if (!s || (s->r & VT_FORWARD)) error("main() not defined"); t = (int (*)())s->c; return (*t)(argc - optind, argv + optind);