added runtime library - fixed more relocations

This commit is contained in:
bellard
2002-07-22 23:37:39 +00:00
parent 3d902af1a9
commit 6cdecbe4e6
4 changed files with 678 additions and 132 deletions

174
tcc.c
View File

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