last patches to separate type and value handling

tcc-xref
bellard 2001-12-22 17:05:23 +00:00
parent f7181903bb
commit 498551188e
2 changed files with 160 additions and 143 deletions

View File

@ -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 */

301
tcc.c
View File

@ -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;i<nb;i++) {
init_putv(t1, c + (array_length + i) * size1,
ts->str[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);