aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--i386-gen.c41
-rw-r--r--libtcc1.c556
-rw-r--r--tcc.c174
-rw-r--r--tcctok.h39
4 files changed, 678 insertions, 132 deletions
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);
@@ -681,77 +672,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
non standard math libs */
@@ -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")