From 6cdecbe4e622194c5ba311d0e944a1b33a0e18a3 Mon Sep 17 00:00:00 2001 From: bellard Date: Mon, 22 Jul 2002 23:37:39 +0000 Subject: [PATCH] added runtime library - fixed more relocations --- i386-gen.c | 41 ++-- libtcc1.c | 556 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tcc.c | 174 ++++++----------- tcctok.h | 39 ++++ 4 files changed, 678 insertions(+), 132 deletions(-) create mode 100644 libtcc1.c create mode 100644 tcctok.h diff --git a/i386-gen.c b/i386-gen.c index c4e6bc2..7486da2 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -822,27 +822,33 @@ void gen_cvt_ftof(int t) /* generate a bounded pointer addition */ void gen_bounded_ptr_add(void) { - int addr; + Sym *sym; + /* prepare fast i386 function call (args in eax and edx) */ gv2(RC_EAX, RC_EDX); /* save all temporary registers */ vtop -= 2; save_regs(0); /* do a fast function call */ - addr = ind; - oad(0xe8, (int)__bound_ptr_add - ind - 5); + sym = external_sym(TOK___bound_ptr_add, func_old_type, 0); + greloc(cur_text_section, sym, + ind + 1 - (int)cur_text_section->data, R_386_PC32); + oad(0xe8, -4); /* returned pointer is in eax */ vtop++; vtop->r = REG_EAX | VT_BOUNDED; - vtop->c.ul = addr; /* address of bounding function call point */ + /* address of bounding function call point */ + vtop->c.ptr = (cur_text_section->reloc->data_ptr - sizeof(Elf32_Rel)); } /* patch pointer addition in vtop so that pointer dereferencing is also tested */ void gen_bounded_ptr_deref(void) { - void *func; - int size, align, addr; + int func; + int size, align; + Elf32_Rel *rel; + Sym *sym; size = 0; /* XXX: put that code in generic part of tcc */ @@ -855,20 +861,25 @@ void gen_bounded_ptr_deref(void) if (!size) size = type_size(vtop->t, &align); switch(size) { - case 1: func = __bound_ptr_indir1; break; - case 2: func = __bound_ptr_indir2; break; - case 4: func = __bound_ptr_indir4; break; - case 8: func = __bound_ptr_indir8; break; - case 12: func = __bound_ptr_indir12; break; - case 16: func = __bound_ptr_indir16; break; + case 1: func = TOK___bound_ptr_indir1; break; + case 2: func = TOK___bound_ptr_indir2; break; + case 4: func = TOK___bound_ptr_indir4; break; + case 8: func = TOK___bound_ptr_indir8; break; + case 12: func = TOK___bound_ptr_indir12; break; + case 16: func = TOK___bound_ptr_indir16; break; default: error("unhandled size when derefencing bounded pointer"); - func = NULL; + func = 0; break; } - addr = vtop->c.ul; - *(int *)(addr + 1) = (int)func - addr - 5; + /* patch relocation */ + /* XXX: find a better solution ? */ + rel = vtop->c.ptr; + sym = external_sym(func, func_old_type, 0); + if (!sym->c) + put_extern_sym(sym, NULL, 0); + rel->r_info = ELF32_R_INFO(sym->c, ELF32_R_TYPE(rel->r_info)); } #endif diff --git a/libtcc1.c b/libtcc1.c new file mode 100644 index 0000000..00c7192 --- /dev/null +++ b/libtcc1.c @@ -0,0 +1,556 @@ +/* TCC runtime library. + Parts of this code are (c) 2002 Fabrice Bellard + + Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +In addition to the permissions in the GNU General Public License, the +Free Software Foundation gives you unlimited permission to link the +compiled version of this file into combinations with other programs, +and to distribute those combinations without any restriction coming +from the use of this file. (The General Public License restrictions +do apply in other respects; for example, they cover modification of +the file, and distribution when not linked into a combine +executable.) + +This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. +*/ + +#define W_TYPE_SIZE 32 +#define BITS_PER_UNIT 8 + +typedef int Wtype; +typedef unsigned int UWtype; +typedef unsigned int USItype; +typedef long long DWtype; +typedef unsigned long long UDWtype; + +struct DWstruct { + Wtype low, high; +}; + +typedef union +{ + struct DWstruct s; + DWtype ll; +} DWunion; + +typedef long double XFtype; +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) +#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) + +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126 +#define SIGNBIT 0x80000000 +#define HIDDEN (1 << 23) +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23) & 0xFF) +#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) +#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) + +/* the following deal with IEEE double-precision numbers */ +#define EXCESSD 1022 +#define HIDDEND (1 << 20) +#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) +#define SIGND(fp) ((fp.l.upper) & SIGNBIT) +#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ + (fp.l.lower >> 22)) +#define HIDDEND_LL ((long long)1 << 52) +#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) +#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m)) + +/* the following deal with x86 long double-precision numbers */ +#define EXCESSLD 16382 +#define EXPLD(fp) (fp.l.upper & 0x7fff) +#define SIGNLD(fp) ((fp.l.upper) & 0x8000) + +/* only for x86 */ +union ldouble_long { + long double ld; + struct { + unsigned long long lower; + unsigned short upper; + } l; +}; + +union double_long { + double d; +#if 1 + struct { + unsigned long lower; + long upper; + } l; +#else + struct { + long upper; + unsigned long lower; + } l; +#endif + long long ll; +}; + +union float_long { + float f; + long l; +}; + +/* XXX: use gcc/tcc intrinsic ? */ +#if defined(__i386__) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("divl %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#else +#error unsupported CPU type +#endif + +/* most of this code is taken from libgcc2.c from gcc */ + +static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + DWunion ww; + DWunion nn, dd; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + nn.ll = n; + dd.ll = d; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !UDIV_NEEDS_NORMALIZATION + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) + { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + UWtype m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) + { + sub_ddmmss (n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + ww.s.low = q0; + ww.s.high = q1; + return ww.ll; +} + +#define __negdi2(a) (-(a)) + +long long __divdi3(long long u, long long v) +{ + int c = 0; + DWunion uu, vv; + DWtype w; + + uu.ll = u; + vv.ll = v; + + if (uu.s.high < 0) { + c = ~c; + uu.ll = __negdi2 (uu.ll); + } + if (vv.s.high < 0) { + c = ~c; + vv.ll = __negdi2 (vv.ll); + } + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); + if (c) + w = __negdi2 (w); + return w; +} + +long long __moddi3(long long u, long long v) +{ + int c = 0; + DWunion uu, vv; + DWtype w; + + uu.ll = u; + vv.ll = v; + + if (uu.s.high < 0) { + c = ~c; + uu.ll = __negdi2 (uu.ll); + } + if (vv.s.high < 0) + vv.ll = __negdi2 (vv.ll); + + __udivmoddi4 (uu.ll, vv.ll, &w); + if (c) + w = __negdi2 (w); + return w; +} + +unsigned long long __udivdi3(unsigned long long u, unsigned long long v) +{ + return __udivmoddi4 (u, v, (UDWtype *) 0); +} + +unsigned long long __umoddi3(unsigned long long u, unsigned long long v) +{ + UDWtype w; + + __udivmoddi4 (u, v, &w); + return w; +} + +/* XXX: suppress that and patch tcc to do it */ +long long __sardi3(long long a, int b) +{ + return a >> b; +} + +/* XXX: suppress that and patch tcc to do it */ +unsigned long long __shrdi3(unsigned long long a, int b) +{ + return a >> b; +} + +/* XXX: suppress that and patch tcc to do it */ +long long __shldi3(long long a, int b) +{ + return a << b; +} + +/* XXX: suppress that and patch tcc to do it */ +float __ulltof(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (float)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (float)r; + } +} + +double __ulltod(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (double)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (double)r; + } +} + +long double __ulltold(unsigned long long a) +{ + DWunion uu; + XFtype r; + + uu.ll = a; + if (uu.s.high >= 0) { + return (long double)uu.ll; + } else { + r = (XFtype)uu.ll; + r += 18446744073709551616.0; + return (long double)r; + } +} + +unsigned long long __fixunssfdi (float a1) +{ + register union float_long fl1; + register int exp; + register unsigned long l; + + fl1.f = a1; + + if (fl1.l == 0) + return (0); + + exp = EXP (fl1.l) - EXCESS - 24; + + l = MANT(fl1.l); + if (exp >= 41) + return (unsigned long long)-1; + else if (exp >= 0) + return (unsigned long long)l << exp; + else if (exp >= -23) + return l >> -exp; + else + return 0; +} + +unsigned long long __fixunsdfdi (double a1) +{ + register union double_long dl1; + register int exp; + register unsigned long long l; + + dl1.d = a1; + + if (dl1.ll == 0) + return (0); + + exp = EXPD (dl1) - EXCESSD - 53; + + l = MANTD_LL(dl1); + + if (exp >= 12) + return (unsigned long long)-1; + else if (exp >= 0) + return l << exp; + else if (exp >= -52) + return l >> -exp; + else + return 0; +} + +unsigned long long __fixunsxfdi (long double a1) +{ + register union ldouble_long dl1; + register int exp; + register unsigned long long l; + + dl1.ld = a1; + + if (dl1.l.lower == 0 && dl1.l.upper == 0) + return (0); + + exp = EXPLD (dl1) - EXCESSLD - 64; + + l = dl1.l.lower; + + if (exp > 0) + return (unsigned long long)-1; + else if (exp >= -63) + return l >> -exp; + else + return 0; +} + diff --git a/tcc.c b/tcc.c index 9b50dac..8bfc50b 100644 --- a/tcc.c +++ b/tcc.c @@ -100,6 +100,7 @@ typedef union CValue { unsigned long long ull; struct TokenSym *ts; struct Sym *sym; + void *ptr; int tab[1]; } CValue; @@ -284,6 +285,7 @@ int ifdef_stack[IFDEF_STACK_SIZE], *ifdef_stack_ptr; char **include_paths; int nb_include_paths; int char_pointer_type; +int func_old_type; /* compile with debug symbol (and use them if error during execution) */ int do_debug = 0; @@ -493,21 +495,9 @@ enum { /* special identifiers */ TOK___FUNC__, TOK_MAIN, - /* attribute identifiers */ - TOK_SECTION, - TOK___SECTION__, - TOK_ALIGNED, - TOK___ALIGNED__, - TOK_UNUSED, - TOK___UNUSED__, - TOK_CDECL, - TOK___CDECL, - TOK___CDECL__, - TOK_STDCALL, - TOK___STDCALL, - TOK___STDCALL__, - TOK_NORETURN, - TOK___NORETURN__, +#define DEF(id, str) id, +#include "tcctok.h" +#undef DEF }; char *tcc_keywords = @@ -521,10 +511,10 @@ char *tcc_keywords = "defined\0undef\0error\0line\0" "__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0" "__func__\0main\0" -/* attributes */ -"section\0__section__\0aligned\0__aligned__\0unused\0__unused__\0" -"cdecl\0__cdecl\0__cdecl__\0stdcall\0__stdcall\0__stdcall__\0" -"noreturn\0__noreturn__\0" +/* builtin functions */ +#define DEF(id, str) str "\0" +#include "tcctok.h" +#undef DEF ; #ifdef WIN32 @@ -595,6 +585,7 @@ void vset(int t, int r, int v); void type_to_str(char *buf, int buf_size, int t, const char *varstr); char *get_tok_str(int v, CValue *cv); +Sym *external_sym(int v, int u, int r); /* section generation */ void put_extern_sym(Sym *sym, Section *section, unsigned long value); @@ -680,77 +671,6 @@ void *dlsym(void *handle, const char *symbol) #endif -/********************************************************/ -/* runtime library is there */ -/* XXX: we suppose that the host compiler handles 'long long'. It - would not be difficult to suppress this assumption */ - -long long __divll(long long a, long long b) -{ - return a / b; -} - -long long __modll(long long a, long long b) -{ - return a % b; -} - -unsigned long long __divull(unsigned long long a, unsigned long long b) -{ - return a / b; -} - -unsigned long long __modull(unsigned long long a, unsigned long long b) -{ - return a % b; -} - -long long __sardi3(long long a, int b) -{ - return a >> b; -} - -unsigned long long __shrdi3(unsigned long long a, int b) -{ - return a >> b; -} - -long long __shldi3(long long a, int b) -{ - return a << b; -} - -float __ulltof(unsigned long long a) -{ - return (float)a; -} - -double __ulltod(unsigned long long a) -{ - return (double)a; -} - -long double __ulltold(unsigned long long a) -{ - return (long double)a; -} - -unsigned long long __ftoull(float a) -{ - return (unsigned long long)a; -} - -unsigned long long __dtoull(double a) -{ - return (unsigned long long)a; -} - -unsigned long long __ldtoull(long double a) -{ - return (unsigned long long)a; -} - - /********************************************************/ /* we use our own 'finite' function to avoid potential problems with @@ -2589,6 +2509,17 @@ void vpush_ref(int t, Section *sec, unsigned long offset) vsetc(t, VT_CONST | VT_SYM, &cval); } +/* push a reference to symbol v */ +void vpush_sym(int t, int v) +{ + Sym *sym; + CValue cval; + + sym = external_sym(v, t, 0); + cval.sym = sym; + vsetc(t, VT_CONST | VT_SYM, &cval); +} + void vset(int t, int r, int v) { CValue cval; @@ -3019,29 +2950,29 @@ void gv_dup(void) void gen_opl(int op) { int t, a, b, op1, c, i; - void *func; + int func; GFuncContext gf; SValue tmp; switch(op) { case '/': case TOK_PDIV: - func = __divll; + func = TOK___divdi3; goto gen_func; case TOK_UDIV: - func = __divull; + func = TOK___udivdi3; goto gen_func; case '%': - func = __modll; + func = TOK___moddi3; goto gen_func; case TOK_UMOD: - func = __modull; + func = TOK___umoddi3; gen_func: /* call generic long long function */ gfunc_start(&gf, FUNC_CDECL); gfunc_param(&gf); gfunc_param(&gf); - vpushi((int)func); + vpush_sym(func_old_type, func); gfunc_call(&gf); vpushi(0); vtop->r = REG_IRET; @@ -3166,13 +3097,13 @@ void gen_opl(int op) /* XXX: should provide a faster fallback on x86 ? */ switch(op) { case TOK_SAR: - func = __sardi3; + func = TOK___sardi3; goto gen_func; case TOK_SHR: - func = __shrdi3; + func = TOK___shrdi3; goto gen_func; case TOK_SHL: - func = __shldi3; + func = TOK___shldi3; goto gen_func; } } @@ -3561,11 +3492,11 @@ void gen_cvt_itof1(int t) gfunc_start(&gf, FUNC_CDECL); gfunc_param(&gf); if (t == VT_FLOAT) - vpushi((int)&__ulltof); + vpush_sym(func_old_type, TOK___ulltof); else if (t == VT_DOUBLE) - vpushi((int)&__ulltod); + vpush_sym(func_old_type, TOK___ulltod); else - vpushi((int)&__ulltold); + vpush_sym(func_old_type, TOK___ulltold); gfunc_call(&gf); vpushi(0); vtop->r = REG_FRET; @@ -3586,11 +3517,11 @@ void gen_cvt_ftoi1(int t) st = vtop->t & VT_BTYPE; gfunc_param(&gf); if (st == VT_FLOAT) - vpushi((int)&__ftoull); + vpush_sym(func_old_type, TOK___fixunssfdi); else if (st == VT_DOUBLE) - vpushi((int)&__dtoull); + vpush_sym(func_old_type, TOK___fixunsdfdi); else - vpushi((int)&__ldtoull); + vpush_sym(func_old_type, TOK___fixunsxfdi); gfunc_call(&gf); vpushi(0); vtop->r = REG_IRET; @@ -4049,7 +3980,7 @@ void vstore(void) gfunc_param(&gf); save_regs(0); - vpushi((int)&memcpy); + vpush_sym(func_old_type, TOK_memcpy); gfunc_call(&gf); /* leave source on stack */ } else if (ft & VT_BITFIELD) { @@ -4697,7 +4628,7 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg) void unary(void) { - int n, t, ft, fc, p, align, size, r, data_offset; + int n, t, ft, fc, align, size, r, data_offset; Sym *s; GFuncContext gf; AttributeDef ad; @@ -4847,11 +4778,8 @@ void unary(void) if (tok != '(') error("'%s' undeclared", get_tok_str(t, NULL)); /* for simple function calls, we tolerate undeclared - external reference */ - p = anon_sym++; - sym_push1(&global_stack, p, 0, FUNC_OLD); - /* int() function */ - s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT), 0); + external reference to int() function */ + s = external_sym(t, func_old_type, 0); } vset(s->t, s->r, s->c); /* if forward reference, we must point to s */ @@ -5633,7 +5561,7 @@ void init_putz(int t, Section *sec, unsigned long c, int size) gfunc_param(&gf); vset(VT_INT, VT_LOCAL, c); gfunc_param(&gf); - vpushi((int)&memset); + vpush_sym(func_old_type, TOK_memset); gfunc_call(&gf); } } @@ -6190,7 +6118,8 @@ static int tcc_compile(TCCState *s) { Sym *define_start; char buf[512]; - + int p; + funcname = ""; include_stack_ptr = include_stack; ifdef_stack_ptr = ifdef_stack; @@ -6215,6 +6144,10 @@ static int tcc_compile(TCCState *s) /* define common 'char *' type because it is often used internally for arrays and struct dereference */ char_pointer_type = mk_pointer(VT_BYTE); + /* define an old type function 'int func()' */ + p = anon_sym++; + sym_push1(&global_stack, p, 0, FUNC_OLD); + func_old_type = VT_FUNC | (p << VT_STRUCT_SHIFT); define_start = define_stack.top; inp(); @@ -6807,8 +6740,6 @@ static void put32(unsigned char *p, unsigned int val) static void build_got(void) { /* if no got, then create it */ - /* a got is needed even if static link for the symbol - _GLOBAL_OFFSET_TABLE_ */ got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); got->sh_entsize = 4; add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), @@ -6933,6 +6864,12 @@ static void put_dt(Section *dynamic, int dt, unsigned long val) dynamic->data_ptr += sizeof(Elf32_Dyn); } +/* add tcc runtime libraries */ +static void tcc_add_runtime(TCCState *s1) +{ + tcc_add_file(s1, CONFIG_TCC_PREFIX "/lib/tcc/libtcc1.o"); +} + /* add dynamic sections so that the executable is dynamically linked */ static char elf_interp[] = "/lib/ld-linux.so.2"; @@ -6963,8 +6900,9 @@ int tcc_output_file(TCCState *s1, const char *filename) /* add libc crtn object */ if (file_type != TCC_OUTPUT_OBJ) { - tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); + tcc_add_runtime(s1); tcc_add_library(s1, "c"); + tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); } interp = NULL; @@ -8076,6 +8014,8 @@ int tcc_run(TCCState *s1, int argc, char **argv) int (*prog_main)(int, char **); int i; + tcc_add_runtime(s1); + relocate_common_syms(); /* compute relocation address : section are relocated in place */ diff --git a/tcctok.h b/tcctok.h new file mode 100644 index 0000000..d593ad7 --- /dev/null +++ b/tcctok.h @@ -0,0 +1,39 @@ +/* attribute identifiers */ +DEF(TOK_SECTION, "section") +DEF(TOK___SECTION__, "__section__") +DEF(TOK_ALIGNED, "aligned") +DEF(TOK___ALIGNED__, "__aligned__") +DEF(TOK_UNUSED, "unused") +DEF(TOK___UNUSED__, "__unused__") +DEF(TOK_CDECL, "cdecl") +DEF(TOK___CDECL, "__cdecl") +DEF(TOK___CDECL__, "__cdecl__") +DEF(TOK_STDCALL, "stdcall") +DEF(TOK___STDCALL, "__stdcall") +DEF(TOK___STDCALL__, "__stdcall__") +DEF(TOK_NORETURN, "noreturn") +DEF(TOK___NORETURN__, "__noreturn__") + +/* builtin functions */ +DEF(TOK_memcpy, "memcpy") +DEF(TOK_memset, "memset") +DEF(TOK___divdi3, "__divdi3") +DEF(TOK___moddi3, "__moddi3") +DEF(TOK___udivdi3, "__udivdi3") +DEF(TOK___umoddi3, "__umoddi3") +DEF(TOK___sardi3, "__sardi3") +DEF(TOK___shrdi3, "__shrdi3") +DEF(TOK___shldi3, "__shldi3") +DEF(TOK___ulltof, "__ulltof") +DEF(TOK___ulltod, "__ulltod") +DEF(TOK___ulltold, "__ulltold") +DEF(TOK___fixunssfdi, "__fixunssfdi") +DEF(TOK___fixunsdfdi, "__fixunsdfdi") +DEF(TOK___fixunsxfdi, "__fixunsxfdi") +DEF(TOK___bound_ptr_add, "__bound_ptr_add") +DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1") +DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2") +DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4") +DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8") +DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12") +DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")