From d2115bfb27f18f56fea5ce506b6bbe838f2dfb1b Mon Sep 17 00:00:00 2001 From: bellard Date: Thu, 29 Aug 2002 23:05:59 +0000 Subject: [PATCH] added symbol + relocation handling --- i386-gen.c | 48 ++++++++++++++++++++++-------------------------- tcc.c | 53 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 56 insertions(+), 45 deletions(-) diff --git a/i386-gen.c b/i386-gen.c index 85f101b..35cba2d 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -132,7 +132,7 @@ void gsym(int t) #define psym oad /* instruction + 4 bytes data. Return the address of the data */ -int oad(int c, int s) +static int oad(int c, int s) { int ind1; @@ -147,26 +147,22 @@ int oad(int c, int s) } /* output constant with relocation if 'r & VT_SYM' is true */ -void gen_addr32(int r, int c) +static void gen_addr32(int r, Sym *sym, int c) { - if (!(r & VT_SYM)) { - gen_le32(c); - } else { - greloc(cur_text_section, - (Sym *)c, ind, R_386_32); - gen_le32(0); - } + if (r & VT_SYM) + greloc(cur_text_section, sym, ind, R_386_32); + gen_le32(c); } /* generate a modrm reference. 'op_reg' contains the addtionnal 3 opcode bits */ -void gen_modrm(int op_reg, int r, int c) +static void gen_modrm(int op_reg, int r, Sym *sym, int c) { op_reg = op_reg << 3; if ((r & VT_VALMASK) == VT_CONST) { /* constant memory reference */ o(0x05 | op_reg); - gen_addr32(r, c); + gen_addr32(r, sym, c); } else if ((r & VT_VALMASK) == VT_LOCAL) { /* currently, we use only ebp as base */ if (c == (char)c) { @@ -221,14 +217,14 @@ void load(int r, SValue *sv) } else { o(0x8b); /* movl */ } - gen_modrm(r, fr, fc); + gen_modrm(r, fr, sv->sym, fc); } else { if (v == VT_CONST) { o(0xb8 + r); /* mov $xx, r */ - gen_addr32(fr, fc); + gen_addr32(fr, sv->sym, fc); } else if (v == VT_LOCAL) { o(0x8d); /* lea xxx(%ebp), r */ - gen_modrm(r, VT_LOCAL, fc); + gen_modrm(r, VT_LOCAL, sv->sym, fc); } else if (v == VT_CMP) { oad(0xb8 + r, 0); /* mov $0, r */ o(0x0f); /* setxx %br */ @@ -278,7 +274,7 @@ void store(int r, SValue *v) if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { - gen_modrm(r, v->r, fc); + gen_modrm(r, v->r, v->sym, fc); } else if (fr != r) { o(0xc0 + fr + r * 8); /* mov r, fr */ } @@ -362,9 +358,9 @@ void gfunc_call(GFuncContext *c) /* constant case */ if (vtop->r & VT_SYM) { /* relocation case */ - greloc(cur_text_section, vtop->c.sym, + greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32); - oad(0xe8, -4); + oad(0xe8, vtop->c.ul - 4); } else { oad(0xe8, vtop->c.ul - ind - 5); } @@ -443,7 +439,7 @@ void gfunc_epilog(void) greloc(cur_text_section, sym_data, ind + 1, R_386_32); oad(0xb8, 0); /* mov %eax, xxx */ - sym = external_sym(TOK___bound_local_new, func_old_type, 0); + sym = external_global_sym(TOK___bound_local_new, func_old_type, 0); greloc(cur_text_section, sym, ind + 1, R_386_PC32); oad(0xe8, -4); @@ -453,7 +449,7 @@ void gfunc_epilog(void) greloc(cur_text_section, sym_data, ind + 1, R_386_32); oad(0xb8, 0); /* mov %eax, xxx */ - sym = external_sym(TOK___bound_local_delete, func_old_type, 0); + sym = external_global_sym(TOK___bound_local_delete, func_old_type, 0); greloc(cur_text_section, sym, ind + 1, R_386_PC32); oad(0xe8, -4); @@ -766,7 +762,7 @@ void gen_opf(int op) o(0xdc); else o(0xd8); - gen_modrm(a, r, fc); + gen_modrm(a, r, vtop->sym, fc); } vtop--; } @@ -816,8 +812,8 @@ void gen_cvt_ftoi(int t) size = 4; o(0x2dd9); /* ldcw xxx */ - sym = external_sym(TOK___tcc_int_fpu_control, - VT_SHORT | VT_UNSIGNED, VT_LVAL); + sym = external_global_sym(TOK___tcc_int_fpu_control, + VT_SHORT | VT_UNSIGNED, VT_LVAL); greloc(cur_text_section, sym, ind, R_386_32); gen_le32(0); @@ -829,8 +825,8 @@ void gen_cvt_ftoi(int t) o(0x3cdf); /* fistpll */ o(0x24); o(0x2dd9); /* ldcw xxx */ - sym = external_sym(TOK___tcc_fpu_control, - VT_SHORT | VT_UNSIGNED, VT_LVAL); + sym = external_global_sym(TOK___tcc_fpu_control, + VT_SHORT | VT_UNSIGNED, VT_LVAL); greloc(cur_text_section, sym, ind, R_386_32); gen_le32(0); @@ -871,7 +867,7 @@ void gen_bounded_ptr_add(void) vtop -= 2; save_regs(0); /* do a fast function call */ - sym = external_sym(TOK___bound_ptr_add, func_old_type, 0); + sym = external_global_sym(TOK___bound_ptr_add, func_old_type, 0); greloc(cur_text_section, sym, ind + 1, R_386_PC32); oad(0xe8, -4); @@ -917,7 +913,7 @@ void gen_bounded_ptr_deref(void) /* patch relocation */ /* XXX: find a better solution ? */ rel = (Elf32_Rel *)(cur_text_section->reloc->data + vtop->c.ul); - sym = external_sym(func, func_old_type, 0); + sym = external_global_sym(func, func_old_type, 0); if (!sym->c) put_extern_sym(sym, NULL, 0, 0); rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); diff --git a/tcc.c b/tcc.c index 017b248..1babd27 100644 --- a/tcc.c +++ b/tcc.c @@ -100,7 +100,6 @@ typedef union CValue { long long ll; unsigned long long ull; struct CString *cstr; - struct Sym *sym; void *ptr; int tab[1]; } CValue; @@ -112,6 +111,7 @@ typedef struct SValue { unsigned short r2; /* second register, used for 'long long' type. If not used, set to VT_CONST */ CValue c; /* constant, if VT_CONST */ + struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST) */ } SValue; /* symbol management */ @@ -548,7 +548,7 @@ static char *pstrcat(char *buf, int buf_size, const char *s); void sum(int l); void next(void); void next_nomacro(void); -int expr_const(void); +static int expr_const(void); void expr_eq(void); void gexpr(void); void decl(int l); @@ -2895,8 +2895,9 @@ static void vpush_ref(int t, Section *sec, unsigned long offset, unsigned long s { CValue cval; - cval.sym = get_sym_ref(t, sec, offset, size); + cval.ul = 0; vsetc(t, VT_CONST | VT_SYM, &cval); + vtop->sym = get_sym_ref(t, sec, offset, size); } /* define a new external reference to a symbol 'v' of type 'u' */ @@ -2934,8 +2935,9 @@ static void vpush_global_sym(int t, int v) CValue cval; sym = external_global_sym(v, t, 0); - cval.sym = sym; + cval.ul = 0; vsetc(t, VT_CONST | VT_SYM, &cval); + vtop->sym = sym; } void vset(int t, int r, int v) @@ -3160,7 +3162,8 @@ int gv(int rc) ptr[i] = vtop->c.tab[i]; sym = get_sym_ref(vtop->t, data_section, offset, size << 2); vtop->r |= VT_LVAL | VT_SYM; - vtop->c.sym = sym; + vtop->sym = sym; + vtop->c.ul = 0; } #ifdef CONFIG_TCC_BCHECK if (vtop->r & VT_MUSTBOUND) @@ -3675,6 +3678,14 @@ void gen_opic(int op) op = TOK_SHR; } goto general_case; + } else if (c2 && (op == '+' || op == '-') && + (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) == + (VT_CONST | VT_SYM)) { + /* symbol + constant case */ + if (op == '-') + fc = -fc; + vtop--; + vtop->c.i += fc; } else { general_case: /* call low level op generator */ @@ -5189,8 +5200,10 @@ void unary(void) } vset(s->t, s->r, s->c); /* if forward reference, we must point to s */ - if (vtop->r & VT_SYM) - vtop->c.sym = s; + if (vtop->r & VT_SYM) { + vtop->sym = s; + vtop->c.ul = 0; + } } } @@ -5273,7 +5286,7 @@ void unary(void) tok_str_new(&str); parlevel = 0; while ((parlevel > 0 || (tok != ')' && tok != ',')) && - tok != -1) { + tok != TOK_EOF) { if (tok == '(') parlevel++; else if (tok == ')') @@ -5509,23 +5522,23 @@ void gexpr(void) } } -/* parse a constant expression and return value in vtop */ -void expr_const1(void) +/* parse a constant expression and return value in vtop. */ +static void expr_const1(void) { int a; a = const_wanted; const_wanted = 1; expr_eq(); - if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST) - expect("constant"); const_wanted = a; } -/* parse an integer constant and return its value */ -int expr_const(void) +/* parse an integer constant and return its value. */ +static int expr_const(void) { int c; expr_const1(); + if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) + expect("constant expression"); c = vtop->c.i; vpop(); return c; @@ -5899,6 +5912,9 @@ static void init_putv(int t, Section *sec, unsigned long c, global_expr = 1; expr_const1(); global_expr = saved_global_expr; + /* NOTE: symbols are accepted */ + if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST) + error("initializer element is not constant"); break; case EXPR_ANY: expr_eq(); @@ -5936,11 +5952,9 @@ static void init_putv(int t, Section *sec, unsigned long c, break; default: if (vtop->r & VT_SYM) { - greloc(sec, vtop->c.sym, c, R_DATA_32); - *(int *)ptr = 0; - } else { - *(int *)ptr = vtop->c.i; + greloc(sec, vtop->sym, c, R_DATA_32); } + *(int *)ptr = vtop->c.i; break; } vtop--; @@ -6284,8 +6298,9 @@ static void decl_initializer_alloc(int t, AttributeDef *ad, int r, /* push global reference */ sym = get_sym_ref(t, sec, addr, size); - cval.sym = sym; + cval.ul = 0; vsetc(t, VT_CONST | VT_SYM, &cval); + vtop->sym = sym; } /* handles bounds now because the symbol must be defined