added runtime library - fixed more relocations
This commit is contained in:
174
tcc.c
174
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 */
|
||||
|
||||
Reference in New Issue
Block a user