mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-28 04:00:06 +08:00
added runtime library - fixed more relocations
This commit is contained in:
parent
3d902af1a9
commit
6cdecbe4e6
41
i386-gen.c
41
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
|
||||
|
||||
|
556
libtcc1.c
Normal file
556
libtcc1.c
Normal file
@ -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;
|
||||
}
|
||||
|
172
tcc.c
172
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,6 +6118,7 @@ static int tcc_compile(TCCState *s)
|
||||
{
|
||||
Sym *define_start;
|
||||
char buf[512];
|
||||
int p;
|
||||
|
||||
funcname = "";
|
||||
include_stack_ptr = include_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 */
|
||||
|
39
tcctok.h
Normal file
39
tcctok.h
Normal file
@ -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")
|
Loading…
Reference in New Issue
Block a user