1
0
Fork 0

Revert "Move almost all global variables to TCCState, actually all tests pass on Ubuntu 18.04 x86_64"

This reverts commit af686a796b.
This commit is contained in:
mingodad 2021-10-22 07:39:54 +02:00
parent 2ce2dbcb09
commit 1645616843
30 changed files with 10723 additions and 11190 deletions

1112
arm-asm.c

File diff suppressed because it is too large Load Diff

1135
arm-gen.c

File diff suppressed because it is too large Load Diff

View File

@ -107,9 +107,9 @@ int gotplt_entry_type (int reloc_type)
}
#ifndef TCC_TARGET_PE
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = S->plt;
Section *plt = s1->plt;
uint8_t *p;
unsigned plt_offset;
@ -119,7 +119,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* empty PLT: create PLT0 entry that push address of call site and
jump to ld.so resolution routine (GOT + 8) */
if (plt->data_offset == 0) {
p = section_ptr_add(S, plt, 20);
p = section_ptr_add(plt, 20);
write32le(p, 0xe52de004); /* push {lr} */
write32le(p+4, 0xe59fe004); /* ldr lr, [pc, #4] */
write32le(p+8, 0xe08fe00e); /* add lr, pc, lr */
@ -129,11 +129,11 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
plt_offset = plt->data_offset;
if (attr->plt_thumb_stub) {
p = section_ptr_add(S, plt, 4);
p = section_ptr_add(plt, 4);
write32le(p, 0x4778); /* bx pc */
write32le(p+2, 0x46c0); /* nop */
}
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
/* save GOT offset for relocate_plt */
write32le(p + 4, got_offset);
return plt_offset;
@ -141,22 +141,22 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
int x = S->got->sh_addr - S->plt->sh_addr - 12;
write32le(S->plt->data + 16, x - 4);
int x = s1->got->sh_addr - s1->plt->sh_addr - 12;
write32le(s1->plt->data + 16, x - 4);
p += 20;
while (p < p_end) {
unsigned off = x + read32le(p + 4) + (S->plt->data - p) + 4;
unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4;
if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */
p += 4;
write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000
@ -167,17 +167,17 @@ ST_FUNC void relocate_plt(TCCState *S)
}
}
if (S->plt->reloc) {
if (s1->plt->reloc) {
ElfW_Rel *rel;
p = S->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
write32le(p + rel->r_offset, S->plt->sh_addr);
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write32le(p + rel->r_offset, s1->plt->sh_addr);
}
}
}
#endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
ElfW(Sym) *sym;
int sym_index, esym_index;
@ -212,7 +212,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
h = x & 2;
th_ko = (x & 3) && (!blx_avail || !is_call);
if (th_ko || x >= 0x2000000 || x < -0x2000000)
tcc_error(S, "can't relocate value at %x,%d",addr, type);
tcc_error("can't relocate value at %x,%d",addr, type);
x >>= 2;
x &= 0xffffff;
/* Only reached if blx is avail and it is a call */
@ -255,7 +255,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
/* Relocation infos */
to_thumb = val & 1;
plt = S->plt;
plt = s1->plt;
to_plt = (val >= plt->sh_addr) &&
(val < plt->sh_addr + plt->data_offset);
is_call = (type == R_ARM_THM_PC22);
@ -267,10 +267,10 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
Section *text;
name = (char *) symtab_section->link->data + sym->st_name;
text = S->sections[sym->st_shndx];
text = s1->sections[sym->st_shndx];
/* Modify reloc to target a thumb stub to switch to ARM */
snprintf(buf, sizeof(buf), "%s_from_thumb", name);
index = put_elf_sym(S, symtab_section,
index = put_elf_sym(symtab_section,
text->data_offset + 1,
sym->st_size, sym->st_info, 0,
sym->st_shndx, buf);
@ -281,7 +281,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
put_elf_reloc(symtab_section, text,
text->data_offset + 4, R_ARM_JUMP24,
sym_index);
p = section_ptr_add(S, text, 8);
p = section_ptr_add(text, 8);
write32le(p, 0x4778); /* bx pc */
write32le(p+2, 0x46c0); /* nop */
write32le(p+4, 0xeafffffe); /* b $sym */
@ -301,7 +301,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
- instruction must be a call (bl) or a jump to PLT */
if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
if (to_thumb || (val & 2) || (!is_call && !to_plt))
tcc_error(S, "can't relocate value at %x,%d",addr, type);
tcc_error("can't relocate value at %x,%d",addr, type);
/* Compute and store final offset */
s = (x >> 24) & 1;
@ -372,14 +372,14 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
x = (x * 2) / 2;
x += val - addr;
if((x^(x>>1))&0x40000000)
tcc_error(S, "can't relocate value at %x,%d",addr, type);
tcc_error("can't relocate value at %x,%d",addr, type);
(*(int *)ptr) |= x & 0x7fffffff;
}
return;
case R_ARM_ABS32:
case R_ARM_TARGET1:
if (S->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_ARM_ABS32);
@ -396,19 +396,19 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
*(int *)ptr += val - addr;
return;
case R_ARM_GOTPC:
*(int *)ptr += S->got->sh_addr - addr;
*(int *)ptr += s1->got->sh_addr - addr;
return;
case R_ARM_GOTOFF:
*(int *)ptr += val - S->got->sh_addr;
*(int *)ptr += val - s1->got->sh_addr;
return;
case R_ARM_GOT32:
/* we load the got offset */
*(int *)ptr += get_sym_attr(S, sym_index, 0)->got_offset;
*(int *)ptr += get_sym_attr(s1, sym_index, 0)->got_offset;
return;
case R_ARM_GOT_PREL:
/* we load the pc relative got offset */
*(int *)ptr += S->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset -
*(int *)ptr += s1->got->sh_addr +
get_sym_attr(s1, sym_index, 0)->got_offset -
addr;
return;
case R_ARM_COPY:
@ -428,7 +428,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return;
case R_ARM_RELATIVE:
#ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase);
add32le(ptr, val - s1->pe_imagebase);
#endif
/* do nothing */
return;

View File

@ -9,9 +9,9 @@
#define CONFIG_TCC_ASM
#define NB_ASM_REGS 16
ST_FUNC void g(TCCState* S, int c);
ST_FUNC void gen_le16(TCCState* S, int c);
ST_FUNC void gen_le32(TCCState* S, int c);
ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c);
/*************************************************************/
#else
@ -25,7 +25,7 @@ static void asm_error(void)
}
/* XXX: make it faster ? */
ST_FUNC void g(TCCState* S, int c)
ST_FUNC void g(int c)
{
int ind1;
if (nocode_wanted)
@ -37,24 +37,24 @@ ST_FUNC void g(TCCState* S, int c)
ind = ind1;
}
ST_FUNC void gen_le16 (TCCState* S, int i)
ST_FUNC void gen_le16 (int i)
{
g(S, i);
g(S, i>>8);
g(i);
g(i>>8);
}
ST_FUNC void gen_le32 (TCCState* S, int i)
ST_FUNC void gen_le32 (int i)
{
gen_le16(S, i);
gen_le16(S, i>>16);
gen_le16(i);
gen_le16(i>>16);
}
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
ST_FUNC void gen_expr32(ExprValue *pe)
{
gen_le32(S, pe->v);
gen_le32(pe->v);
}
ST_FUNC void asm_opcode(TCCState *S, int opcode)
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
{
asm_error();
}

File diff suppressed because it is too large Load Diff

View File

@ -90,18 +90,18 @@ int gotplt_entry_type (int reloc_type)
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = S->plt;
Section *plt = s1->plt;
uint8_t *p;
unsigned plt_offset;
if (plt->data_offset == 0) {
section_ptr_add(S, plt, 32);
section_ptr_add(plt, 32);
}
plt_offset = plt->data_offset;
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
write32le(p, got_offset);
write32le(p + 4, (uint64_t) got_offset >> 32);
return plt_offset;
@ -109,22 +109,22 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
uint64_t plt = S->plt->sh_addr;
uint64_t got = S->got->sh_addr + 16;
uint64_t plt = s1->plt->sh_addr;
uint64_t got = s1->got->sh_addr + 16;
uint64_t off = (got >> 12) - (plt >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0xa9bf7bf0); // stp x16,x30,[sp,#-16]!
write32le(p + 4, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
@ -137,13 +137,13 @@ ST_FUNC void relocate_plt(TCCState *S)
write32le(p + 24, 0xd503201f); // nop
write32le(p + 28, 0xd503201f); // nop
p += 32;
got = S->got->sh_addr;
got = s1->got->sh_addr;
while (p < p_end) {
uint64_t pc = plt + (p - S->plt->data);
uint64_t pc = plt + (p - s1->plt->data);
uint64_t addr = got + read64le(p);
uint64_t off = (addr >> 12) - (pc >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, (0x90000010 | // adrp x16,...
(off & 0x1ffffc) << 3 | (off & 3) << 29));
write32le(p + 4, (0xf9400211 | // ldr x17,[x16,#...]
@ -155,16 +155,16 @@ ST_FUNC void relocate_plt(TCCState *S)
}
}
if (S->plt->reloc) {
if (s1->plt->reloc) {
ElfW_Rel *rel;
p = S->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, S->plt->sh_addr);
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, s1->plt->sh_addr);
}
}
}
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
int sym_index = ELFW(R_SYM)(rel->r_info), esym_index;
#ifdef DEBUG_RELOC
@ -173,8 +173,8 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch(type) {
case R_AARCH64_ABS64:
if (S->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_ABS64);
@ -190,7 +190,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add64le(ptr, val);
return;
case R_AARCH64_ABS32:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
@ -202,9 +202,9 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add32le(ptr, val);
return;
case R_AARCH64_PREL32:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_AARCH64_PREL32);
@ -235,7 +235,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
case R_AARCH64_ADR_PREL_PG_HI21: {
uint64_t off = (val >> 12) - (addr >> 12);
if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error(S, "R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
tcc_error("R_AARCH64_ADR_PREL_PG_HI21 relocation failed");
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29));
return;
@ -268,7 +268,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
(char *) symtab_section->link->data + sym->st_name);
#endif
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
tcc_error(S, "R_AARCH64_(JUMP|CALL)26 relocation failed"
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
write32le(ptr, (0x14000000 |
(uint32_t)(type == R_AARCH64_CALL26) << 31 |
@ -276,10 +276,10 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return;
case R_AARCH64_ADR_GOT_PAGE: {
uint64_t off =
(((S->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
(((s1->got->sh_addr +
get_sym_attr(s1, sym_index, 0)->got_offset) >> 12) - (addr >> 12));
if ((off + ((uint64_t)1 << 20)) >> 21)
tcc_error(S, "R_AARCH64_ADR_GOT_PAGE relocation failed");
tcc_error("R_AARCH64_ADR_GOT_PAGE relocation failed");
write32le(ptr, ((read32le(ptr) & 0x9f00001f) |
(off & 0x1ffffc) << 3 | (off & 3) << 29));
return;
@ -287,8 +287,8 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
case R_AARCH64_LD64_GOT_LO12_NC:
write32le(ptr,
((read32le(ptr) & 0xfff803ff) |
((S->got->sh_addr +
get_sym_attr(S, sym_index, 0)->got_offset) & 0xff8) << 7));
((s1->got->sh_addr +
get_sym_attr(s1, sym_index, 0)->got_offset) & 0xff8) << 7));
return;
case R_AARCH64_COPY:
return;
@ -304,7 +304,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
return;
case R_AARCH64_RELATIVE:
#ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase);
add32le(ptr, val - s1->pe_imagebase);
#endif
/* do nothing */
return;

1516
c67-gen.c

File diff suppressed because it is too large Load Diff

View File

@ -65,23 +65,23 @@ int gotplt_entry_type (int reloc_type)
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
tcc_error(S, "C67 got not implemented");
tcc_error("C67 got not implemented");
return 0;
}
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
/* XXX: TODO */
@ -91,7 +91,7 @@ ST_FUNC void relocate_plt(TCCState *S)
}
}
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
switch(type) {
case R_C60_32:

View File

@ -253,10 +253,10 @@ static const uint16_t op0_codes[] = {
#endif
};
static inline int get_reg_shift(TCCState *S)
static inline int get_reg_shift(TCCState *s1)
{
int shift, v;
v = asm_int_expr(S);
v = asm_int_expr(s1);
switch(v) {
case 1:
shift = 0;
@ -271,7 +271,7 @@ static inline int get_reg_shift(TCCState *S)
shift = 3;
break;
default:
expect(S, "1, 2, 4 or 8 constant");
expect("1, 2, 4 or 8 constant");
shift = 0;
break;
}
@ -279,11 +279,11 @@ static inline int get_reg_shift(TCCState *S)
}
#ifdef TCC_TARGET_X86_64
static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type)
static int asm_parse_numeric_reg(int t, unsigned int *type)
{
int reg = -1;
if (t >= TOK_IDENT && t < S->tccpp_tok_ident) {
const char *s = S->tccpp_table_ident[t - TOK_IDENT]->str;
if (t >= TOK_IDENT && t < tok_ident) {
const char *s = table_ident[t - TOK_IDENT]->str;
char c;
*type = OP_REG64;
if (*s == 'c') {
@ -318,51 +318,51 @@ static int asm_parse_numeric_reg(TCCState *S, int t, unsigned int *type)
}
#endif
static int asm_parse_reg(TCCState* S, unsigned int *type)
static int asm_parse_reg(unsigned int *type)
{
int reg = 0;
*type = 0;
if (S->tccpp_tok != '%')
if (tok != '%')
goto error_32;
next(S);
if (S->tccpp_tok >= TOK_ASM_eax && S->tccpp_tok <= TOK_ASM_edi) {
reg = S->tccpp_tok - TOK_ASM_eax;
next();
if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
reg = tok - TOK_ASM_eax;
*type = OP_REG32;
#ifdef TCC_TARGET_X86_64
} else if (S->tccpp_tok >= TOK_ASM_rax && S->tccpp_tok <= TOK_ASM_rdi) {
reg = S->tccpp_tok - TOK_ASM_rax;
} else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
reg = tok - TOK_ASM_rax;
*type = OP_REG64;
} else if (S->tccpp_tok == TOK_ASM_rip) {
} else if (tok == TOK_ASM_rip) {
reg = -2; /* Probably should use different escape code. */
*type = OP_REG64;
} else if ((reg = asm_parse_numeric_reg(S, S->tccpp_tok, type)) >= 0
} else if ((reg = asm_parse_numeric_reg(tok, type)) >= 0
&& (*type == OP_REG32 || *type == OP_REG64)) {
;
#endif
} else {
error_32:
expect(S, "register");
expect("register");
}
next(S);
next();
return reg;
}
static void parse_operand(TCCState *S, Operand *op)
static void parse_operand(TCCState *s1, Operand *op)
{
ExprValue e;
int reg, indir;
const char *p;
indir = 0;
if (S->tccpp_tok == '*') {
next(S);
if (tok == '*') {
next();
indir = OP_INDIR;
}
if (S->tccpp_tok == '%') {
next(S);
if (S->tccpp_tok >= TOK_ASM_al && S->tccpp_tok <= TOK_ASM_db7) {
reg = S->tccpp_tok - TOK_ASM_al;
if (tok == '%') {
next();
if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
reg = tok - TOK_ASM_al;
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
op->reg = reg & 7;
if ((op->type & OP_REG) && op->reg == TREG_XAX)
@ -371,48 +371,48 @@ static void parse_operand(TCCState *S, Operand *op)
op->type |= OP_CL;
else if (op->type == OP_REG16 && op->reg == TREG_XDX)
op->type |= OP_DX;
} else if (S->tccpp_tok >= TOK_ASM_dr0 && S->tccpp_tok <= TOK_ASM_dr7) {
} else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
op->type = OP_DB;
op->reg = S->tccpp_tok - TOK_ASM_dr0;
} else if (S->tccpp_tok >= TOK_ASM_es && S->tccpp_tok <= TOK_ASM_gs) {
op->reg = tok - TOK_ASM_dr0;
} else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
op->type = OP_SEG;
op->reg = S->tccpp_tok - TOK_ASM_es;
} else if (S->tccpp_tok == TOK_ASM_st) {
op->reg = tok - TOK_ASM_es;
} else if (tok == TOK_ASM_st) {
op->type = OP_ST;
op->reg = 0;
next(S);
if (S->tccpp_tok == '(') {
next(S);
if (S->tccpp_tok != TOK_PPNUM)
next();
if (tok == '(') {
next();
if (tok != TOK_PPNUM)
goto reg_error;
p = S->tccpp_tokc.str.data;
p = tokc.str.data;
reg = p[0] - '0';
if ((unsigned)reg >= 8 || p[1] != '\0')
goto reg_error;
op->reg = reg;
next(S);
skip(S, ')');
next();
skip(')');
}
if (op->reg == 0)
op->type |= OP_ST0;
goto no_skip;
#ifdef TCC_TARGET_X86_64
} else if (S->tccpp_tok >= TOK_ASM_spl && S->tccpp_tok <= TOK_ASM_dil) {
} else if (tok >= TOK_ASM_spl && tok <= TOK_ASM_dil) {
op->type = OP_REG8 | OP_REG8_LOW;
op->reg = 4 + S->tccpp_tok - TOK_ASM_spl;
} else if ((op->reg = asm_parse_numeric_reg(S, S->tccpp_tok, &op->type)) >= 0) {
op->reg = 4 + tok - TOK_ASM_spl;
} else if ((op->reg = asm_parse_numeric_reg(tok, &op->type)) >= 0) {
;
#endif
} else {
reg_error:
tcc_error(S, "unknown register %%%s", get_tok_str(S, S->tccpp_tok, &S->tccpp_tokc));
tcc_error("unknown register %%%s", get_tok_str(tok, &tokc));
}
next(S);
next();
no_skip: ;
} else if (S->tccpp_tok == '$') {
} else if (tok == '$') {
/* constant value */
next(S);
asm_expr(S, &e);
next();
asm_expr(s1, &e);
op->type = OP_IM32;
op->e = e;
if (!op->e.sym) {
@ -433,45 +433,45 @@ static void parse_operand(TCCState *S, Operand *op)
op->reg = -1;
op->reg2 = -1;
op->shift = 0;
if (S->tccpp_tok != '(') {
asm_expr(S, &e);
if (tok != '(') {
asm_expr(s1, &e);
op->e = e;
} else {
next(S);
if (S->tccpp_tok == '%') {
unget_tok(S, '(');
next();
if (tok == '%') {
unget_tok('(');
op->e.v = 0;
op->e.sym = NULL;
} else {
/* bracketed offset expression */
asm_expr(S, &e);
if (S->tccpp_tok != ')')
expect(S, ")");
next(S);
asm_expr(s1, &e);
if (tok != ')')
expect(")");
next();
op->e.v = e.v;
op->e.sym = e.sym;
}
op->e.pcrel = 0;
}
if (S->tccpp_tok == '(') {
if (tok == '(') {
unsigned int type = 0;
next(S);
if (S->tccpp_tok != ',') {
op->reg = asm_parse_reg(S, &type);
next();
if (tok != ',') {
op->reg = asm_parse_reg(&type);
}
if (S->tccpp_tok == ',') {
next(S);
if (S->tccpp_tok != ',') {
op->reg2 = asm_parse_reg(S, &type);
if (tok == ',') {
next();
if (tok != ',') {
op->reg2 = asm_parse_reg(&type);
}
if (S->tccpp_tok == ',') {
next(S);
op->shift = get_reg_shift(S);
if (tok == ',') {
next();
op->shift = get_reg_shift(s1);
}
}
if (type & OP_REG32)
op->type |= OP_EA32;
skip(S, ')');
skip(')');
}
if (op->reg == -1 && op->reg2 == -1)
op->type |= OP_ADDR;
@ -480,65 +480,65 @@ static void parse_operand(TCCState *S, Operand *op)
}
/* XXX: unify with C code output ? */
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
ST_FUNC void gen_expr32(ExprValue *pe)
{
if (pe->pcrel)
/* If PC-relative, always set VT_SYM, even without symbol,
so as to force a relocation to be emitted. */
gen_addrpc32(S, VT_SYM, pe->sym, pe->v);
gen_addrpc32(VT_SYM, pe->sym, pe->v);
else
gen_addr32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
}
#ifdef TCC_TARGET_X86_64
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe)
ST_FUNC void gen_expr64(ExprValue *pe)
{
gen_addr64(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
}
#endif
/* XXX: unify with C code output ? */
static void gen_disp32(TCCState* S, ExprValue *pe)
static void gen_disp32(ExprValue *pe)
{
Sym *sym = pe->sym;
ElfSym *esym = elfsym(S, sym);
ElfSym *esym = elfsym(sym);
if (esym && esym->st_shndx == cur_text_section->sh_num) {
/* same section: we can output an absolute value. Note
that the TCC compiler behaves differently here because
it always outputs a relocation to ease (future) code
elimination in the linker */
gen_le32(S, pe->v + esym->st_value - S->tccgen_ind - 4);
gen_le32(pe->v + esym->st_value - ind - 4);
} else {
if (sym && sym->type.t == VT_VOID) {
sym->type.t = VT_FUNC;
sym->type.ref = NULL;
}
gen_addrpc32(S, VT_SYM, sym, pe->v);
gen_addrpc32(VT_SYM, sym, pe->v);
}
}
/* generate the modrm operand */
static inline int asm_modrm(TCCState* S, int reg, Operand *op)
static inline int asm_modrm(int reg, Operand *op)
{
int mod, reg1, reg2, sib_reg1;
if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
g(S, 0xc0 + (reg << 3) + op->reg);
g(0xc0 + (reg << 3) + op->reg);
} else if (op->reg == -1 && op->reg2 == -1) {
/* displacement only */
#ifdef TCC_TARGET_X86_64
g(S, 0x04 + (reg << 3));
g(S, 0x25);
g(0x04 + (reg << 3));
g(0x25);
#else
g(S, 0x05 + (reg << 3));
g(0x05 + (reg << 3));
#endif
gen_expr32(S, &op->e);
gen_expr32(&op->e);
#ifdef TCC_TARGET_X86_64
} else if (op->reg == -2) {
ExprValue *pe = &op->e;
g(S, 0x05 + (reg << 3));
gen_addrpc32(S, pe->sym ? VT_SYM : 0, pe->sym, pe->v);
return S->tccgen_ind;
g(0x05 + (reg << 3));
gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
return ind;
#endif
} else {
sib_reg1 = op->reg;
@ -557,19 +557,19 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
reg1 = op->reg;
if (op->reg2 != -1)
reg1 = 4;
g(S, mod + (reg << 3) + reg1);
g(mod + (reg << 3) + reg1);
if (reg1 == 4) {
/* add sib byte */
reg2 = op->reg2;
if (reg2 == -1)
reg2 = 4; /* indicate no index */
g(S, (op->shift << 6) + (reg2 << 3) + sib_reg1);
g((op->shift << 6) + (reg2 << 3) + sib_reg1);
}
/* add offset */
if (mod == 0x40) {
g(S, op->e.v);
g(op->e.v);
} else if (mod == 0x80 || op->reg == -1) {
gen_expr32(S, &op->e);
gen_expr32(&op->e);
}
}
return 0;
@ -581,7 +581,7 @@ static inline int asm_modrm(TCCState* S, int reg, Operand *op)
#define REX_X 0x42
#define REX_B 0x41
static void asm_rex(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_type,
static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
int regi, int rmi)
{
unsigned char rex = width64 ? 0x48 : 0;
@ -631,9 +631,9 @@ static void asm_rex(TCCState* S, int width64, Operand *ops, int nb_ops, int *op_
}
if (rex) {
if (saw_high_8bit)
tcc_error(S, "can't encode register %%%ch when REX prefix is required",
tcc_error("can't encode register %%%ch when REX prefix is required",
"acdb"[saw_high_8bit-4]);
g(S, rex);
g(rex);
}
}
#endif
@ -679,7 +679,7 @@ static void maybe_print_stats (void)
}
}
ST_FUNC void asm_opcode(TCCState *S, int opcode)
ST_FUNC void asm_opcode(TCCState *s1, int opcode)
{
const ASMInstr *pa;
int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc;
@ -697,7 +697,7 @@ ST_FUNC void asm_opcode(TCCState *S, int opcode)
/* force synthetic ';' after prefix instruction, so we can handle */
/* one-line things like "rep stosb" instead of only "rep\nstosb" */
if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz)
unget_tok(S, ';');
unget_tok(';');
/* get operands */
pop = ops;
@ -705,27 +705,27 @@ ST_FUNC void asm_opcode(TCCState *S, int opcode)
seg_prefix = 0;
alltypes = 0;
for(;;) {
if (S->tccpp_tok == ';' || S->tccpp_tok == TOK_LINEFEED)
if (tok == ';' || tok == TOK_LINEFEED)
break;
if (nb_ops >= MAX_OPERANDS) {
tcc_error(S, "incorrect number of operands");
tcc_error("incorrect number of operands");
}
parse_operand(S, pop);
if (S->tccpp_tok == ':') {
parse_operand(s1, pop);
if (tok == ':') {
if (pop->type != OP_SEG || seg_prefix)
tcc_error(S, "incorrect prefix");
tcc_error("incorrect prefix");
seg_prefix = segment_prefixes[pop->reg];
next(S);
parse_operand(S, pop);
next();
parse_operand(s1, pop);
if (!(pop->type & OP_EA)) {
tcc_error(S, "segment prefix must be followed by memory reference");
tcc_error("segment prefix must be followed by memory reference");
}
}
pop++;
nb_ops++;
if (S->tccpp_tok != ',')
if (tok != ',')
break;
next(S);
next();
}
s = 0; /* avoid warning */
@ -842,23 +842,23 @@ again:
int b;
b = op0_codes[opcode - TOK_ASM_first];
if (b & 0xff00)
g(S, b >> 8);
g(S, b);
g(b >> 8);
g(b);
return;
} else if (opcode <= TOK_ASM_alllast) {
tcc_error(S, "bad operand with opcode '%s'",
get_tok_str(S, opcode, NULL));
tcc_error("bad operand with opcode '%s'",
get_tok_str(opcode, NULL));
} else {
/* Special case for cmovcc, we accept size suffixes but ignore
them, but we don't want them to blow up our tables. */
TokenSym *ts = S->tccpp_table_ident[opcode - TOK_IDENT];
TokenSym *ts = table_ident[opcode - TOK_IDENT];
if (ts->len >= 6
&& strchr("wlq", ts->str[ts->len-1])
&& !memcmp(ts->str, "cmov", 4)) {
opcode = tok_alloc(S, ts->str, ts->len-1)->tok;
opcode = tok_alloc(ts->str, ts->len-1)->tok;
goto again;
}
tcc_error(S, "unknown opcode '%s'", ts->str);
tcc_error("unknown opcode '%s'", ts->str);
}
}
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
@ -886,7 +886,7 @@ again:
(ops[0].type & OP_EA))
s = NBWLX - 2;
else
tcc_error(S, "cannot infer opcode suffix");
tcc_error("cannot infer opcode suffix");
}
}
@ -894,7 +894,7 @@ again:
/* Generate addr32 prefix if needed */
for(i = 0; i < nb_ops; i++) {
if (ops[i].type & OP_EA32) {
g(S, 0x67);
g(0x67);
break;
}
}
@ -913,7 +913,7 @@ again:
p66 = 1;
}
if (p66)
g(S, 0x66);
g(0x66);
#ifdef TCC_TARGET_X86_64
rex64 = 0;
if (pa->instr_type & OPC_48)
@ -943,9 +943,9 @@ again:
/* now generates the operation */
if (OPCT_IS(pa->instr_type, OPC_FWAIT))
g(S, 0x9b);
g(0x9b);
if (seg_prefix)
g(S, seg_prefix);
g(seg_prefix);
v = pa->opcode;
if (pa->instr_type & OPC_0F)
@ -998,7 +998,7 @@ again:
goto modrm_found;
}
#ifdef ASM_DEBUG
tcc_error(S, "bad op table");
tcc_error("bad op table");
#endif
modrm_found:
modrm_index = i;
@ -1014,7 +1014,7 @@ again:
}
}
#ifdef TCC_TARGET_X86_64
asm_rex (S, rex64, ops, nb_ops, op_type, modreg_index, modrm_index);
asm_rex (rex64, ops, nb_ops, op_type, modreg_index, modrm_index);
#endif
if (pa->instr_type & OPC_REG) {
@ -1035,10 +1035,10 @@ again:
int jmp_disp;
/* see if we can really generate the jump with a byte offset */
esym = elfsym(S, ops[0].e.sym);
esym = elfsym(ops[0].e.sym);
if (!esym || esym->st_shndx != cur_text_section->sh_num)
goto no_short_jump;
jmp_disp = ops[0].e.v + esym->st_value - S->tccgen_ind - 2 - (v >= 0xff);
jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
if (jmp_disp == (int8_t)jmp_disp) {
/* OK to generate jump */
ops[0].e.sym = 0;
@ -1053,18 +1053,18 @@ again:
else if (v == 0x70) /* jcc */
v += 0x0f10;
else
tcc_error(S, "invalid displacement");
tcc_error("invalid displacement");
}
}
if (OPCT_IS(pa->instr_type, OPC_TEST))
v += test_bits[opcode - pa->sym];
op1 = v >> 16;
if (op1)
g(S, op1);
g(op1);
op1 = (v >> 8) & 0xff;
if (op1)
g(S, op1);
g(S, v);
g(op1);
g(v);
if (OPCT_IS(pa->instr_type, OPC_SHIFT)) {
reg = (opcode - pa->sym) / NBWLX;
@ -1084,7 +1084,7 @@ again:
used instead of group */
if (modreg_index >= 0)
reg = ops[modreg_index].reg;
pc = asm_modrm(S, reg, &ops[modrm_index]);
pc = asm_modrm(reg, &ops[modrm_index]);
}
/* emit constants */
@ -1092,10 +1092,10 @@ again:
if (!(pa->instr_type & OPC_0F)
&& (pa->opcode == 0x9a || pa->opcode == 0xea)) {
/* ljmp or lcall kludge */
gen_expr32(S, &ops[1].e);
gen_expr32(&ops[1].e);
if (ops[0].e.sym)
tcc_error(S, "cannot relocate");
gen_le16(S, ops[0].e.v);
tcc_error("cannot relocate");
gen_le16(ops[0].e.v);
return;
}
#endif
@ -1116,32 +1116,32 @@ again:
}
if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym)
tcc_error(S, "cannot relocate");
tcc_error("cannot relocate");
if (v & (OP_IM8 | OP_IM8S)) {
g(S, ops[i].e.v);
g(ops[i].e.v);
} else if (v & OP_IM16) {
gen_le16(S, ops[i].e.v);
gen_le16(ops[i].e.v);
#ifdef TCC_TARGET_X86_64
} else if (v & OP_IM64) {
gen_expr64(S, &ops[i].e);
gen_expr64(&ops[i].e);
#endif
} else if (pa->op_type[i] == OPT_DISP || pa->op_type[i] == OPT_DISP8) {
gen_disp32(S, &ops[i].e);
gen_disp32(&ops[i].e);
} else {
gen_expr32(S, &ops[i].e);
gen_expr32(&ops[i].e);
}
}
}
/* after immediate operands, adjust pc-relative address */
if (pc)
add32le(cur_text_section->data + pc - 4, pc - S->tccgen_ind);
add32le(cur_text_section->data + pc - 4, pc - ind);
}
/* return the constraint priority (we allocate first the lowest
numbered constraints) */
static inline int constraint_priority(TCCState* S, const char *str)
static inline int constraint_priority(const char *str)
{
int priority, c, pr;
@ -1182,7 +1182,7 @@ static inline int constraint_priority(TCCState* S, const char *str)
pr = 4;
break;
default:
tcc_error(S, "unknown constraint '%c'", c);
tcc_error("unknown constraint '%c'", c);
pr = 0;
}
if (pr > priority)
@ -1200,19 +1200,19 @@ static const char *skip_constraint_modifiers(const char *p)
/* If T (a token) is of the form "%reg" returns the register
number and type, otherwise return -1. */
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
ST_FUNC int asm_parse_regvar (int t)
{
const char *s;
Operand op;
if (t < TOK_IDENT || (t & SYM_FIELD))
return -1;
s = S->tccpp_table_ident[t - TOK_IDENT]->str;
s = table_ident[t - TOK_IDENT]->str;
if (s[0] != '%')
return -1;
t = tok_alloc_const(S, s + 1);
unget_tok(S, t);
unget_tok(S, '%');
parse_operand(S, &op);
t = tok_alloc_const(s + 1);
unget_tok(t);
unget_tok('%');
parse_operand(tcc_state, &op);
/* Accept only integer regs for now. */
if (op.type & OP_REG)
return op.reg;
@ -1225,7 +1225,7 @@ ST_FUNC int asm_parse_regvar (TCCState* S, int t)
#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
int nb_operands, int nb_outputs,
const uint8_t *clobber_regs,
int *pout_reg)
@ -1253,13 +1253,13 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
str = skip_constraint_modifiers(str);
if (isnum(*str) || *str == '[') {
/* this is a reference to another constraint */
k = find_constraint(S, operands, nb_operands, str, NULL);
k = find_constraint(operands, nb_operands, str, NULL);
if ((unsigned)k >= i || i < nb_outputs)
tcc_error(S, "invalid reference in constraint %d ('%s')",
tcc_error("invalid reference in constraint %d ('%s')",
i, str);
op->ref_index = k;
if (operands[k].input_index >= 0)
tcc_error(S, "cannot reference twice the same operand");
tcc_error("cannot reference twice the same operand");
operands[k].input_index = i;
op->priority = 5;
} else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
@ -1268,7 +1268,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
op->priority = 1;
op->reg = reg;
} else {
op->priority = constraint_priority(S, str);
op->priority = constraint_priority(str);
}
}
@ -1316,7 +1316,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
}
if (op->reg >= 0) {
if (is_reg_allocated(op->reg))
tcc_error(S, "asm regvar requests register that's taken already");
tcc_error("asm regvar requests register that's taken already");
reg = op->reg;
goto reg_found;
}
@ -1330,7 +1330,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
/* FALL THRU */
case '&':
if (j >= nb_outputs)
tcc_error(S, "'%c' modifier can only be applied to outputs", c);
tcc_error("'%c' modifier can only be applied to outputs", c);
reg_mask = REG_IN_MASK | REG_OUT_MASK;
goto try_next;
case 'A':
@ -1424,7 +1424,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
}
break;
default:
tcc_error(S, "asm constraint %d ('%s') could not be satisfied",
tcc_error("asm constraint %d ('%s') could not be satisfied",
j, op->constraint);
break;
}
@ -1447,7 +1447,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
if (!(regs_allocated[reg] & REG_OUT_MASK))
goto reg_found2;
}
tcc_error(S, "could not find free output register for reloading");
tcc_error("could not find free output register for reloading");
reg_found2:
*pout_reg = reg;
break;
@ -1461,7 +1461,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
op = &operands[j];
printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
j,
op->id ? get_tok_str(S, op->id, NULL) : "",
op->id ? get_tok_str(op->id, NULL) : "",
op->constraint,
op->vt->r,
op->reg);
@ -1471,7 +1471,7 @@ ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands,
#endif
}
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
ST_FUNC void subst_asm_operand(CString *add_str,
SValue *sv, int modifier)
{
int r, reg, size, val;
@ -1481,33 +1481,33 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
if ((r & VT_VALMASK) == VT_CONST) {
if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' &&
modifier != 'P')
cstr_ccat(S, add_str, '$');
cstr_ccat(add_str, '$');
if (r & VT_SYM) {
const char *name = get_tok_str(S, sv->sym->v, NULL);
const char *name = get_tok_str(sv->sym->v, NULL);
if (sv->sym->v >= SYM_FIRST_ANOM) {
/* In case of anonymous symbols ("L.42", used
for static data labels) we can't find them
in the C symbol table when later looking up
this name. So enter them now into the asm label
list when we still know the symbol. */
get_asm_sym(S, tok_alloc_const(S, name), sv->sym);
get_asm_sym(tok_alloc_const(name), sv->sym);
}
if (S->leading_underscore)
cstr_ccat(S, add_str, '_');
cstr_cat(S, add_str, name, -1);
if (tcc_state->leading_underscore)
cstr_ccat(add_str, '_');
cstr_cat(add_str, name, -1);
if ((uint32_t)sv->c.i == 0)
goto no_offset;
cstr_ccat(S, add_str, '+');
cstr_ccat(add_str, '+');
}
val = sv->c.i;
if (modifier == 'n')
val = -val;
snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
cstr_cat(S, add_str, buf, -1);
cstr_cat(add_str, buf, -1);
no_offset:;
#ifdef TCC_TARGET_X86_64
if (r & VT_LVAL)
cstr_cat(S, add_str, "(%rip)", -1);
cstr_cat(add_str, "(%rip)", -1);
#endif
} else if ((r & VT_VALMASK) == VT_LOCAL) {
#ifdef TCC_TARGET_X86_64
@ -1515,24 +1515,24 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
#else
snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
#endif
cstr_cat(S, add_str, buf, -1);
cstr_cat(add_str, buf, -1);
} else if (r & VT_LVAL) {
reg = r & VT_VALMASK;
if (reg >= VT_CONST)
tcc_internal_error(S, "");
tcc_internal_error("");
snprintf(buf, sizeof(buf), "(%%%s)",
#ifdef TCC_TARGET_X86_64
get_tok_str(S, TOK_ASM_rax + reg, NULL)
get_tok_str(TOK_ASM_rax + reg, NULL)
#else
get_tok_str(S, TOK_ASM_eax + reg, NULL)
get_tok_str(TOK_ASM_eax + reg, NULL)
#endif
);
cstr_cat(S, add_str, buf, -1);
cstr_cat(add_str, buf, -1);
} else {
/* register case */
reg = r & VT_VALMASK;
if (reg >= VT_CONST)
tcc_internal_error(S, "");
tcc_internal_error("");
/* choose register operand size */
if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
@ -1552,11 +1552,11 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
if (modifier == 'b') {
if (reg >= 4)
tcc_error(S, "cannot use byte register");
tcc_error("cannot use byte register");
size = 1;
} else if (modifier == 'h') {
if (reg >= 4)
tcc_error(S, "cannot use byte register");
tcc_error("cannot use byte register");
size = -1;
} else if (modifier == 'w') {
size = 2;
@ -1587,13 +1587,13 @@ ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str,
break;
#endif
}
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(S, reg, NULL));
cstr_cat(S, add_str, buf, -1);
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
cstr_cat(add_str, buf, -1);
}
}
/* generate prolog and epilog code for asm statement */
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
int nb_outputs, int is_output,
uint8_t *clobber_regs,
int out_reg)
@ -1627,8 +1627,8 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
reg = reg_saved[i];
if (regs_allocated[reg]) {
if (reg >= 8)
g(S, 0x41), reg-=8;
g(S, 0x50 + reg);
g(0x41), reg-=8;
g(0x50 + reg);
}
}
@ -1644,15 +1644,15 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
sv = *op->vt;
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
sv.type.t = VT_PTR;
load(S, op->reg, &sv);
load(op->reg, &sv);
} else if (i >= nb_outputs || op->is_rw) {
/* load value in register */
load(S, op->reg, op->vt);
load(op->reg, op->vt);
if (op->is_llong) {
SValue sv;
sv = *op->vt;
sv.c.i += 4;
load(S, TREG_XDX, &sv);
load(TREG_XDX, &sv);
}
}
}
@ -1668,19 +1668,19 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
sv = *op->vt;
sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
sv.type.t = VT_PTR;
load(S, out_reg, &sv);
load(out_reg, &sv);
sv = *op->vt;
sv.r = (sv.r & ~VT_VALMASK) | out_reg;
store(S, op->reg, &sv);
store(op->reg, &sv);
}
} else {
store(S, op->reg, op->vt);
store(op->reg, op->vt);
if (op->is_llong) {
SValue sv;
sv = *op->vt;
sv.c.i += 4;
store(S, TREG_XDX, &sv);
store(TREG_XDX, &sv);
}
}
}
@ -1690,14 +1690,14 @@ ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands,
reg = reg_saved[i];
if (regs_allocated[reg]) {
if (reg >= 8)
g(S, 0x41), reg-=8;
g(S, 0x58 + reg);
g(0x41), reg-=8;
g(0x58 + reg);
}
}
}
}
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
{
int reg;
#ifdef TCC_TARGET_X86_64
@ -1708,7 +1708,7 @@ ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
!strcmp(str, "cc") ||
!strcmp(str, "flags"))
return;
reg = tok_alloc_const(S, str);
reg = tok_alloc_const(str);
if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
reg -= TOK_ASM_eax;
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
@ -1716,11 +1716,11 @@ ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str)
#ifdef TCC_TARGET_X86_64
} else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) {
reg -= TOK_ASM_rax;
} else if ((reg = asm_parse_numeric_reg(S, reg, &type)) >= 0) {
} else if ((reg = asm_parse_numeric_reg(reg, &type)) >= 0) {
;
#endif
} else {
tcc_error(S, "invalid clobber register '%s'", str);
tcc_error("invalid clobber register '%s'", str);
}
clobber_regs[reg] = 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -91,15 +91,15 @@ int gotplt_entry_type (int reloc_type)
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = S->plt;
Section *plt = s1->plt;
uint8_t *p;
int modrm;
unsigned plt_offset, relofs;
/* on i386 if we build a DLL, we add a %ebx offset */
if (S->output_type == TCC_OUTPUT_DLL)
if (s1->output_type == TCC_OUTPUT_DLL)
modrm = 0xa3;
else
modrm = 0x25;
@ -108,7 +108,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
(GOT + 2 * PTR_SIZE) */
if (plt->data_offset == 0) {
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* pushl got + PTR_SIZE */
p[1] = modrm + 0x10;
write32le(p + 2, PTR_SIZE);
@ -121,10 +121,10 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* The PLT slot refers to the relocation entry it needs via offset.
The reloc entry is created below, so its offset is the current
data_offset */
relofs = S->plt->reloc ? S->plt->reloc->data_offset : 0;
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */
p[1] = modrm;
write32le(p + 2, got_offset);
@ -137,31 +137,31 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (S->output_type != TCC_OUTPUT_DLL && p < p_end) {
add32le(p + 2, S->got->sh_addr);
add32le(p + 8, S->got->sh_addr);
if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) {
add32le(p + 2, s1->got->sh_addr);
add32le(p + 8, s1->got->sh_addr);
p += 16;
while (p < p_end) {
add32le(p + 2, S->got->sh_addr);
add32le(p + 2, s1->got->sh_addr);
p += 16;
}
}
if (S->plt->reloc) {
if (s1->plt->reloc) {
ElfW_Rel *rel;
int x = S->plt->sh_addr + 16 + 6;
p = S->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
int x = s1->plt->sh_addr + 16 + 6;
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write32le(p + rel->r_offset, x);
x += 16;
}
@ -169,7 +169,7 @@ ST_FUNC void relocate_plt(TCCState *S)
}
#endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
int sym_index, esym_index;
@ -177,8 +177,8 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch (type) {
case R_386_32:
if (S->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
@ -192,9 +192,9 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
add32le(ptr, val);
return;
case R_386_PC32:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
@ -212,31 +212,31 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
write32le(ptr, val);
return;
case R_386_GOTPC:
add32le(ptr, S->got->sh_addr - addr);
add32le(ptr, s1->got->sh_addr - addr);
return;
case R_386_GOTOFF:
add32le(ptr, val - S->got->sh_addr);
add32le(ptr, val - s1->got->sh_addr);
return;
case R_386_GOT32:
case R_386_GOT32X:
/* we load the got offset */
add32le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
return;
case R_386_16:
if (S->output_format != TCC_OUTPUT_FORMAT_BINARY) {
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
output_file:
tcc_error(S, "can only produce 16-bit binary files");
tcc_error("can only produce 16-bit binary files");
}
write16le(ptr, read16le(ptr) + val);
return;
case R_386_PC16:
if (S->output_format != TCC_OUTPUT_FORMAT_BINARY)
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
goto output_file;
write16le(ptr, read16le(ptr) + val - addr);
return;
case R_386_RELATIVE:
#ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase);
add32le(ptr, val - s1->pe_imagebase);
#endif
/* do nothing */
return;
@ -267,12 +267,12 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
memcpy(ptr-3, replace, sizeof(replace));
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx];
sec = s1->sections[sym->st_shndx];
x = sym->st_value - sec->sh_addr - sec->data_offset;
add32le(ptr + 5, -x);
}
else
tcc_error(S, "unexpected R_386_TLS_GD pattern");
tcc_error("unexpected R_386_TLS_GD pattern");
}
return;
case R_386_TLS_LDM:
@ -295,7 +295,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
}
else
tcc_error(S, "unexpected R_386_TLS_LDM pattern");
tcc_error("unexpected R_386_TLS_LDM pattern");
}
return;
case R_386_TLS_LDO_32:
@ -306,7 +306,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
int32_t x;
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx];
sec = s1->sections[sym->st_shndx];
x = val - sec->sh_addr - sec->data_offset;
add32le(ptr, x);
}

861
libtcc.c

File diff suppressed because it is too large Load Diff

View File

@ -15,95 +15,56 @@ typedef struct TCCState TCCState;
typedef void (*TCCErrorFunc)(void *opaque, const char *msg);
#ifndef _OFF_T_DEFINED
#define _OFF_T_DEFINED
#ifndef _OFF_T_
#define _OFF_T_
typedef long _off_t;
#ifndef _SIZE_T_
#define _SIZE_T_
typedef unsigned long size_t;
#endif
#if !defined(NO_OLDNAMES) || defined(_POSIX)
typedef long off_t;
#endif
#endif
#endif
struct vio_module_t;
typedef struct vio_fd {
int fd;
void *vio_udata;
struct vio_module_t *vio_module;
} vio_fd;
#define CALL_VIO_OPEN_FIRST 0x01
#define CALL_VIO_OPEN_LAST 0x02
typedef struct vio_module_t {
void *user_data;
struct TCCState *S;
int call_vio_open_flags; /*CALL_VIO_OPEN_FIRST, CALL_VIO_OPEN_LAST, one or both */
int (*vio_open)(vio_fd *fd, const char *fn, int oflag) ;
off_t (*vio_lseek)(vio_fd fd, off_t offset, int whence);
size_t (*vio_read)(vio_fd fd, void *buf, size_t bytes);
int (*vio_close)(vio_fd *fd);
} vio_module_t;
/* create a new TCC compilation context */
LIBTCCAPI TCCState *tcc_new(void);
/* free a TCC compilation context */
LIBTCCAPI void tcc_delete(TCCState *S);
LIBTCCAPI void tcc_delete(TCCState *s);
/* set CONFIG_TCCDIR at runtime */
LIBTCCAPI void tcc_set_lib_path(TCCState *S, const char *path);
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
/* set error/warning display callback */
LIBTCCAPI void tcc_set_error_func(TCCState *S, void *error_opaque, TCCErrorFunc error_func);
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func);
/* return error/warning callback */
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *S);
LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
/* return error/warning callback opaque pointer */
LIBTCCAPI void *tcc_get_error_opaque(TCCState *S);
LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
/* set options as from command line (multiple supported) */
LIBTCCAPI void tcc_set_options(TCCState *S, const char *str);
/* set virtual io module */
LIBTCCAPI void tcc_set_vio_module(TCCState *S, vio_module_t *vio_module);
LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
/*****************************/
/* preprocessor */
/* add include path */
LIBTCCAPI int tcc_add_include_path(TCCState *S, const char *pathname);
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
/* add in system include path */
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *S, const char *pathname);
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
LIBTCCAPI void tcc_define_symbol(TCCState *S, const char *sym, const char *value);
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
/* undefine preprocess symbol 'sym' */
LIBTCCAPI void tcc_undefine_symbol(TCCState *S, const char *sym);
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
/*****************************/
/* compiling */
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
LIBTCCAPI int tcc_add_file(TCCState *S, const char *filename);
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
/* compile a string containing a C source. Return -1 if error. */
LIBTCCAPI int tcc_compile_string(TCCState *S, const char *buf);
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
/*****************************/
/* linking commands */
/* set output type. MUST BE CALLED before any compilation */
LIBTCCAPI int tcc_set_output_type(TCCState *S, int output_type);
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
#define TCC_OUTPUT_EXE 2 /* executable file */
#define TCC_OUTPUT_DLL 3 /* dynamic library */
@ -111,24 +72,24 @@ LIBTCCAPI int tcc_set_output_type(TCCState *S, int output_type);
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *S, const char *pathname);
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
/* the library name is the same as the argument of the '-l' option */
LIBTCCAPI int tcc_add_library(TCCState *S, const char *libraryname);
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
/* add a symbol to the compiled program */
LIBTCCAPI int tcc_add_symbol(TCCState *S, const char *name, const void *val);
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
/* output an executable, library or object file. DO NOT call
tcc_relocate() before. */
LIBTCCAPI int tcc_output_file(TCCState *S, const char *filename);
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
/* link and run main() function and return its value. DO NOT call
tcc_relocate() before. */
LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv);
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
/* do all relocations (needed before using tcc_get_symbol()) */
LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr);
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
/* possible values for 'ptr':
- TCC_RELOCATE_AUTO : Allocate and manage memory internally
- NULL : return required memory size for the step below
@ -137,24 +98,12 @@ LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr);
#define TCC_RELOCATE_AUTO (void*)1
/* return symbol value or NULL if not found */
LIBTCCAPI void *tcc_get_symbol(TCCState *S, const char *name);
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
/* return symbol value or NULL if not found */
LIBTCCAPI void tcc_list_symbols(TCCState *S, void *ctx,
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val));
typedef int (*tcc_cmpfun)(const void *, const void *, void *);
LIBTCCAPI void tcc_qsort_s(void *base, size_t nel, size_t width, tcc_cmpfun cmp, void *ctx);
enum { /*need better names for some of then*/
TCC_OPTION_d_BI = 1,
TCC_OPTION_d_D = 3,
TCC_OPTION_d_4 = 4,
TCC_OPTION_d_M = 7,
TCC_OPTION_d_t = 16,
TCC_OPTION_d_32 = 32,
};
#ifdef __cplusplus
}
#endif

View File

@ -9,9 +9,9 @@
#define CONFIG_TCC_ASM
#define NB_ASM_REGS 32
ST_FUNC void g(TCCState* S, int c);
ST_FUNC void gen_le16(TCCState* S, int c);
ST_FUNC void gen_le32(TCCState* S, int c);
ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c);
/*************************************************************/
#else
@ -20,85 +20,85 @@ ST_FUNC void gen_le32(TCCState* S, int c);
#include "tcc.h"
/* XXX: make it faster ? */
ST_FUNC void g(TCCState* S, int c)
ST_FUNC void g(int c)
{
int ind1;
if (S->tccgen_nocode_wanted)
if (nocode_wanted)
return;
ind1 = S->tccgen_ind + 1;
ind1 = ind + 1;
if (ind1 > cur_text_section->data_allocated)
section_realloc(S, cur_text_section, ind1);
cur_text_section->data[S->tccgen_ind] = c;
S->tccgen_ind = ind1;
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind] = c;
ind = ind1;
}
ST_FUNC void gen_le16 (TCCState* S, int i)
ST_FUNC void gen_le16 (int i)
{
g(S, i);
g(S, i>>8);
g(i);
g(i>>8);
}
ST_FUNC void gen_le32 (TCCState* S, int i)
ST_FUNC void gen_le32 (int i)
{
int ind1;
if (S->tccgen_nocode_wanted)
if (nocode_wanted)
return;
ind1 = S->tccgen_ind + 4;
ind1 = ind + 4;
if (ind1 > cur_text_section->data_allocated)
section_realloc(S, cur_text_section, ind1);
cur_text_section->data[S->tccgen_ind++] = i & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 8) & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 16) & 0xFF;
cur_text_section->data[S->tccgen_ind++] = (i >> 24) & 0xFF;
section_realloc(cur_text_section, ind1);
cur_text_section->data[ind++] = i & 0xFF;
cur_text_section->data[ind++] = (i >> 8) & 0xFF;
cur_text_section->data[ind++] = (i >> 16) & 0xFF;
cur_text_section->data[ind++] = (i >> 24) & 0xFF;
}
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe)
ST_FUNC void gen_expr32(ExprValue *pe)
{
gen_le32(S, pe->v);
gen_le32(pe->v);
}
static void asm_emit_opcode(TCCState* S, uint32_t opcode) {
gen_le32(S, opcode);
static void asm_emit_opcode(uint32_t opcode) {
gen_le32(opcode);
}
static void asm_nullary_opcode(TCCState *S, int token)
static void asm_nullary_opcode(TCCState *s1, int token)
{
switch (token) {
// Sync instructions
case TOK_ASM_fence: // I
asm_emit_opcode(S, (0x3 << 2) | 3 | (0 << 12));
asm_emit_opcode((0x3 << 2) | 3 | (0 << 12));
return;
case TOK_ASM_fence_i: // I
asm_emit_opcode(S, (0x3 << 2) | 3| (1 << 12));
asm_emit_opcode((0x3 << 2) | 3| (1 << 12));
return;
// System calls
case TOK_ASM_scall: // I (pseudo)
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 12));
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12));
return;
case TOK_ASM_sbreak: // I (pseudo)
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 12) | (1 << 20));
asm_emit_opcode((0x1C << 2) | 3 | (0 << 12) | (1 << 20));
return;
// Privileged Instructions
case TOK_ASM_ecall:
asm_emit_opcode(S, (0x1C << 2) | 3 | (0 << 20));
asm_emit_opcode((0x1C << 2) | 3 | (0 << 20));
return;
case TOK_ASM_ebreak:
asm_emit_opcode(S, (0x1C << 2) | 3 | (1 << 20));
asm_emit_opcode((0x1C << 2) | 3 | (1 << 20));
return;
// Other
case TOK_ASM_wfi:
asm_emit_opcode(S, (0x1C << 2) | 3 | (0x105 << 20));
asm_emit_opcode((0x1C << 2) | 3 | (0x105 << 20));
return;
default:
expect(S, "nullary instruction");
expect("nullary instruction");
}
}
@ -121,30 +121,30 @@ typedef struct Operand {
} Operand;
/* Parse a text containing operand and store the result in OP */
static void parse_operand(TCCState *S, Operand *op)
static void parse_operand(TCCState *s1, Operand *op)
{
ExprValue e;
int8_t reg;
op->type = 0;
if ((reg = asm_parse_regvar(S, S->tccpp_tok)) != -1) {
next(S); // skip register name
if ((reg = asm_parse_regvar(tok)) != -1) {
next(); // skip register name
op->type = OP_REG;
op->reg = (uint8_t) reg;
return;
} else if (S->tccpp_tok == '$') {
} else if (tok == '$') {
/* constant value */
next(S); // skip '#' or '$'
next(); // skip '#' or '$'
}
asm_expr(S, &e);
asm_expr(s1, &e);
op->type = OP_IM32;
op->e = e;
if (!op->e.sym) {
if ((int) op->e.v >= -2048 && (int) op->e.v < 2048)
op->type = OP_IM12S;
} else
expect(S, "operand");
expect("operand");
}
#define ENCODE_RS1(register_index) ((register_index) << 15)
@ -152,96 +152,96 @@ static void parse_operand(TCCState *S, Operand *op)
#define ENCODE_RD(register_index) ((register_index) << 7)
// Note: Those all map to CSR--so they are pseudo-instructions.
static void asm_unary_opcode(TCCState *S, int token)
static void asm_unary_opcode(TCCState *s1, int token)
{
uint32_t opcode = (0x1C << 2) | 3 | (2 << 12);
Operand op;
parse_operand(S, &op);
parse_operand(s1, &op);
if (op.type != OP_REG) {
expect(S, "register");
expect("register");
return;
}
opcode |= ENCODE_RD(op.reg);
switch (token) {
case TOK_ASM_rdcycle:
asm_emit_opcode(S, opcode | (0xC00 << 20));
asm_emit_opcode(opcode | (0xC00 << 20));
return;
case TOK_ASM_rdcycleh:
asm_emit_opcode(S, opcode | (0xC80 << 20));
asm_emit_opcode(opcode | (0xC80 << 20));
return;
case TOK_ASM_rdtime:
asm_emit_opcode(S, opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
asm_emit_opcode(opcode | (0xC01 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdtimeh:
asm_emit_opcode(S, opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
asm_emit_opcode(opcode | (0xC81 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdinstret:
asm_emit_opcode(S, opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
asm_emit_opcode(opcode | (0xC02 << 20) | ENCODE_RD(op.reg));
return;
case TOK_ASM_rdinstreth:
asm_emit_opcode(S, opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
asm_emit_opcode(opcode | (0xC82 << 20) | ENCODE_RD(op.reg));
return;
default:
expect(S, "unary instruction");
expect("unary instruction");
}
}
static void asm_emit_u(TCCState *S, int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
static void asm_emit_u(int token, uint32_t opcode, const Operand* rd, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_IM12S && rs2->type != OP_IM32) {
tcc_error(S, "'%s': Expected second source operand that is an immediate value", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected second source operand that is an immediate value", get_tok_str(token, NULL));
return;
} else if (rs2->e.v >= 0x100000) {
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 0xfffff", get_tok_str(token, NULL));
return;
}
/* U-type instruction:
31...12 imm[31:12]
11...7 rd
6...0 opcode */
gen_le32(S, opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
gen_le32(opcode | ENCODE_RD(rd->reg) | (rs2->e.v << 12));
}
static void asm_binary_opcode(TCCState* S, int token)
static void asm_binary_opcode(TCCState* s1, int token)
{
Operand ops[2];
parse_operand(S, &ops[0]);
if (S->tccpp_tok == ',')
next(S);
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[1]);
expect("','");
parse_operand(s1, &ops[1]);
switch (token) {
case TOK_ASM_lui:
asm_emit_u(S, token, (0xD << 2) | 3, &ops[0], &ops[1]);
asm_emit_u(token, (0xD << 2) | 3, &ops[0], &ops[1]);
return;
case TOK_ASM_auipc:
asm_emit_u(S, token, (0x05 << 2) | 3, &ops[0], &ops[1]);
asm_emit_u(token, (0x05 << 2) | 3, &ops[0], &ops[1]);
return;
default:
expect(S, "binary instruction");
expect("binary instruction");
}
}
/* caller: Add funct3, funct7 into opcode */
static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
static void asm_emit_r(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs1->type != OP_REG) {
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_REG) {
tcc_error(S, "'%s': Expected second source operand that is a register or immediate", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected second source operand that is a register or immediate", get_tok_str(token, NULL));
return;
}
/* R-type instruction:
@ -251,22 +251,22 @@ static void asm_emit_r(TCCState* S, int token, uint32_t opcode, const Operand* r
14...12 funct3
11...7 rd
6...0 opcode */
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg));
}
/* caller: Add funct3 into opcode */
static void asm_emit_i(TCCState* S, int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
static void asm_emit_i(int token, uint32_t opcode, const Operand* rd, const Operand* rs1, const Operand* rs2)
{
if (rd->type != OP_REG) {
tcc_error(S, "'%s': Expected destination operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected destination operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs1->type != OP_REG) {
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_IM12S) {
tcc_error(S, "'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected second source operand that is an immediate value between 0 and 4095", get_tok_str(token, NULL));
return;
}
/* I-type instruction:
@ -276,156 +276,156 @@ static void asm_emit_i(TCCState* S, int token, uint32_t opcode, const Operand* r
11...7 rd
6...0 opcode */
gen_le32(S, opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
gen_le32(opcode | ENCODE_RD(rd->reg) | ENCODE_RS1(rs1->reg) | (rs2->e.v << 20));
}
static void asm_shift_opcode(TCCState *S, int token)
static void asm_shift_opcode(TCCState *s1, int token)
{
Operand ops[3];
parse_operand(S, &ops[0]);
if (S->tccpp_tok == ',')
next(S);
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[1]);
if (S->tccpp_tok == ',')
next(S);
expect("','");
parse_operand(s1, &ops[1]);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[2]);
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
case TOK_ASM_sll:
asm_emit_r(S, token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slli:
asm_emit_i(S, token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (4 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srl:
asm_emit_r(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srli:
asm_emit_i(S, token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sra:
asm_emit_r(S, token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (5 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srai:
asm_emit_i(S, token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (5 << 12) | (16 << 26), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sllw:
asm_emit_r(S, token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xE << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slliw:
asm_emit_i(S, token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (6 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srlw:
asm_emit_r(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_srliw:
asm_emit_i(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sraw:
asm_emit_r(S, token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xE << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sraiw:
asm_emit_i(S, token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x6 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect(S, "shift instruction");
expect("shift instruction");
}
}
static void asm_data_processing_opcode(TCCState* S, int token)
static void asm_data_processing_opcode(TCCState* s1, int token)
{
Operand ops[3];
parse_operand(S, &ops[0]);
if (S->tccpp_tok == ',')
next(S);
parse_operand(s1, &ops[0]);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[1]);
if (S->tccpp_tok == ',')
next(S);
expect("','");
parse_operand(s1, &ops[1]);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[2]);
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
// Arithmetic (RD,RS1,(RS2|IMM)); R-format, I-format or U-format
case TOK_ASM_add:
asm_emit_r(S, token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addi:
asm_emit_i(S, token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (4 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sub:
asm_emit_r(S, token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addw:
asm_emit_r(S, token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_addiw: // 64 bit
asm_emit_i(S, token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x6 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_subw:
asm_emit_r(S, token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xE << 2) | 3 | (0 << 12) | (32 << 25), &ops[0], &ops[1], &ops[2]);
return;
// Logical (RD,RS1,(RS2|IMM)); R-format or I-format
case TOK_ASM_xor:
asm_emit_r(S, token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_xori:
asm_emit_i(S, token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_or:
asm_emit_r(S, token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_ori:
asm_emit_i(S, token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_and:
asm_emit_r(S, token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_andi:
asm_emit_i(S, token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (7 << 12), &ops[0], &ops[1], &ops[2]);
return;
// Compare (RD,RS1,(RS2|IMM)); R-format or I-format
case TOK_ASM_slt:
asm_emit_r(S, token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_slti:
asm_emit_i(S, token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sltu:
asm_emit_r(S, token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_r(token, (0xC << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sltiu:
asm_emit_i(S, token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x4 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect(S, "known data processing instruction");
expect("known data processing instruction");
}
}
/* caller: Add funct3 to opcode */
static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
static void asm_emit_s(int token, uint32_t opcode, const Operand* rs1, const Operand* rs2, const Operand* imm)
{
if (rs1->type != OP_REG) {
tcc_error(S, "'%s': Expected first source operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected first source operand that is a register", get_tok_str(token, NULL));
return;
}
if (rs2->type != OP_REG) {
tcc_error(S, "'%s': Expected second source operand that is a register", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected second source operand that is a register", get_tok_str(token, NULL));
return;
}
if (imm->type != OP_IM12S) {
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return;
}
{
@ -438,112 +438,112 @@ static void asm_emit_s(TCCState* S, int token, uint32_t opcode, const Operand* r
11...7 imm[4:0]
6...0 opcode
opcode always fixed pos. */
gen_le32(S, opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
gen_le32(opcode | ENCODE_RS1(rs1->reg) | ENCODE_RS2(rs2->reg) | ((v & 0x1F) << 7) | ((v >> 5) << 25));
}
}
static void asm_data_transfer_opcode(TCCState* S, int token)
static void asm_data_transfer_opcode(TCCState* s1, int token)
{
Operand ops[3];
parse_operand(S, &ops[0]);
parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) {
expect(S, "register");
expect("register");
return;
}
if (S->tccpp_tok == ',')
next(S);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[1]);
expect("','");
parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) {
expect(S, "register");
expect("register");
return;
}
if (S->tccpp_tok == ',')
next(S);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[2]);
expect("','");
parse_operand(s1, &ops[2]);
switch (token) {
// Loads (RD,RS1,I); I-format
case TOK_ASM_lb:
asm_emit_i(S, token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3, &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lh:
asm_emit_i(S, token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lw:
asm_emit_i(S, token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lbu:
asm_emit_i(S, token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (4 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lhu:
asm_emit_i(S, token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (5 << 12), &ops[0], &ops[1], &ops[2]);
return;
// 64 bit
case TOK_ASM_ld:
asm_emit_i(S, token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_lwu:
asm_emit_i(S, token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_i(token, (0x0 << 2) | 3 | (6 << 12), &ops[0], &ops[1], &ops[2]);
return;
// Stores (RS1,RS2,I); S-format
case TOK_ASM_sb:
asm_emit_s(S, token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_s(token, (0x8 << 2) | 3 | (0 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sh:
asm_emit_s(S, token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_s(token, (0x8 << 2) | 3 | (1 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sw:
asm_emit_s(S, token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_s(token, (0x8 << 2) | 3 | (2 << 12), &ops[0], &ops[1], &ops[2]);
return;
case TOK_ASM_sd:
asm_emit_s(S, token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
asm_emit_s(token, (0x8 << 2) | 3 | (3 << 12), &ops[0], &ops[1], &ops[2]);
return;
default:
expect(S, "known data transfer instruction");
expect("known data transfer instruction");
}
}
static void asm_branch_opcode(TCCState* S, int token)
static void asm_branch_opcode(TCCState* s1, int token)
{
// Branch (RS1,RS2,IMM); SB-format
uint32_t opcode = (0x18 << 2) | 3;
uint32_t offset = 0;
Operand ops[3];
parse_operand(S, &ops[0]);
parse_operand(s1, &ops[0]);
if (ops[0].type != OP_REG) {
expect(S, "register");
expect("register");
return;
}
if (S->tccpp_tok == ',')
next(S);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[1]);
expect("','");
parse_operand(s1, &ops[1]);
if (ops[1].type != OP_REG) {
expect(S, "register");
expect("register");
return;
}
if (S->tccpp_tok == ',')
next(S);
if (tok == ',')
next();
else
expect(S, "','");
parse_operand(S, &ops[2]);
expect("','");
parse_operand(s1, &ops[2]);
if (ops[2].type != OP_IM12S) {
tcc_error(S, "'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected third operand that is an immediate value between 0 and 0xfff", get_tok_str(token, NULL));
return;
}
offset = ops[2].e.v;
if (offset & 1) {
tcc_error(S, "'%s': Expected third operand that is an even immediate value", get_tok_str(S, token, NULL));
tcc_error("'%s': Expected third operand that is an even immediate value", get_tok_str(token, NULL));
return;
}
@ -567,12 +567,12 @@ static void asm_branch_opcode(TCCState* S, int token)
opcode |= 7 << 12;
break;
default:
expect(S, "known branch instruction");
expect("known branch instruction");
}
asm_emit_opcode(S, opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31));
asm_emit_opcode(opcode | ENCODE_RS1(ops[0].reg) | ENCODE_RS2(ops[1].reg) | (((offset >> 1) & 0xF) << 8) | (((offset >> 5) & 0x1f) << 25) | (((offset >> 11) & 1) << 7) | (((offset >> 12) & 1) << 31));
}
ST_FUNC void asm_opcode(TCCState *S, int token)
ST_FUNC void asm_opcode(TCCState *s1, int token)
{
switch (token) {
case TOK_ASM_fence:
@ -585,7 +585,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_mrth:
case TOK_ASM_hrts:
case TOK_ASM_wfi:
asm_nullary_opcode(S, token);
asm_nullary_opcode(s1, token);
return;
case TOK_ASM_rdcycle:
@ -594,12 +594,12 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_rdtimeh:
case TOK_ASM_rdinstret:
case TOK_ASM_rdinstreth:
asm_unary_opcode(S, token);
asm_unary_opcode(s1, token);
return;
case TOK_ASM_lui:
case TOK_ASM_auipc:
asm_binary_opcode(S, token);
asm_binary_opcode(s1, token);
return;
case TOK_ASM_sll:
@ -620,7 +620,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_srad:
case TOK_ASM_sraiw:
case TOK_ASM_sraid:
asm_shift_opcode(S, token);
asm_shift_opcode(s1, token);
return;
case TOK_ASM_add:
@ -642,7 +642,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_slti:
case TOK_ASM_sltu:
case TOK_ASM_sltiu:
asm_data_processing_opcode(S, token);
asm_data_processing_opcode(s1, token);
case TOK_ASM_lb:
case TOK_ASM_lh:
@ -655,7 +655,7 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_sh:
case TOK_ASM_sw:
case TOK_ASM_sd:
asm_data_transfer_opcode(S, token);
asm_data_transfer_opcode(s1, token);
return;
case TOK_ASM_beq:
@ -664,35 +664,35 @@ ST_FUNC void asm_opcode(TCCState *S, int token)
case TOK_ASM_bge:
case TOK_ASM_bltu:
case TOK_ASM_bgeu:
asm_branch_opcode(S, token);
asm_branch_opcode(s1, token);
return;
default:
expect(S, "known instruction");
expect("known instruction");
}
}
ST_FUNC void subst_asm_operand(TCCState *S, CString *add_str, SValue *sv, int modifier)
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier)
{
tcc_error(S, "RISCV64 asm not implemented.");
tcc_error("RISCV64 asm not implemented.");
}
/* generate prolog and epilog code for asm statement */
ST_FUNC void asm_gen_code(TCCState *S, ASMOperand *operands, int nb_operands,
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
int nb_outputs, int is_output,
uint8_t *clobber_regs,
int out_reg)
{
}
ST_FUNC void asm_compute_constraints(TCCState *S, ASMOperand *operands,
ST_FUNC void asm_compute_constraints(ASMOperand *operands,
int nb_operands, int nb_outputs,
const uint8_t *clobber_regs,
int *pout_reg)
{
}
ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
{
int reg;
TokenSym *ts;
@ -701,15 +701,15 @@ ST_FUNC void asm_clobber(TCCState *S, uint8_t *clobber_regs, const char *str)
!strcmp(str, "cc") ||
!strcmp(str, "flags"))
return;
ts = tok_alloc(S, str, strlen(str));
reg = asm_parse_regvar(S, ts->tok);
ts = tok_alloc(str, strlen(str));
reg = asm_parse_regvar(ts->tok);
if (reg == -1) {
tcc_error(S, "invalid clobber register '%s'", str);
tcc_error("invalid clobber register '%s'", str);
}
clobber_regs[reg] = 1;
}
ST_FUNC int asm_parse_regvar (TCCState* S, int t)
ST_FUNC int asm_parse_regvar (int t)
{
if (t >= TOK_ASM_x0 && t <= TOK_ASM_pc) { /* register name */
switch (t) {

File diff suppressed because it is too large Load Diff

View File

@ -95,39 +95,39 @@ int gotplt_entry_type (int reloc_type)
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = S->plt;
Section *plt = s1->plt;
uint8_t *p;
unsigned plt_offset;
if (plt->data_offset == 0)
section_ptr_add(S, plt, 32);
section_ptr_add(plt, 32);
plt_offset = plt->data_offset;
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
write64le(p, got_offset);
return plt_offset;
}
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
uint64_t plt = S->plt->sh_addr;
uint64_t got = S->got->sh_addr;
uint64_t plt = s1->plt->sh_addr;
uint64_t got = s1->got->sh_addr;
uint64_t off = (got - plt + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error(S, "Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt);
write32le(p, 0x397 | (off << 12)); // auipc t2, %pcrel_hi(got)
write32le(p + 4, 0x41c30333); // sub t1, t1, t3
write32le(p + 8, 0x0003be03 // ld t3, %pcrel_lo(got)(t2)
@ -140,11 +140,11 @@ ST_FUNC void relocate_plt(TCCState *S)
write32le(p + 28, 0x000e0067); // jr t3
p += 32;
while (p < p_end) {
uint64_t pc = plt + (p - S->plt->data);
uint64_t pc = plt + (p - s1->plt->data);
uint64_t addr = got + read64le(p);
uint64_t off = (addr - pc + 0x800) >> 12;
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error(S, "Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", (long)off, (long)addr, (long)pc);
write32le(p, 0xe17 | (off << 12)); // auipc t3, %pcrel_hi(func@got)
write32le(p + 4, 0x000e3e03 // ld t3, %pcrel_lo(func@got)(t3)
| (((addr - pc) & 0xfff) << 20));
@ -154,16 +154,16 @@ ST_FUNC void relocate_plt(TCCState *S)
}
}
if (S->plt->reloc) {
if (s1->plt->reloc) {
ElfW_Rel *rel;
p = S->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, S->plt->sh_addr);
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, s1->plt->sh_addr);
}
}
}
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
addr_t addr, addr_t val)
{
uint64_t off64;
@ -179,7 +179,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_BRANCH:
off64 = val - addr;
if ((off64 + (1 << 12)) & ~(uint64_t)0x1ffe)
tcc_error(S, "R_RISCV_BRANCH relocation failed"
tcc_error("R_RISCV_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64 >> 1;
write32le(ptr, (read32le(ptr) & ~0xfe000f80)
@ -191,7 +191,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_JAL:
off64 = val - addr;
if ((off64 + (1 << 21)) & ~(((uint64_t)1 << 22) - 2))
tcc_error(S, "R_RISCV_JAL relocation failed"
tcc_error("R_RISCV_JAL relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write32le(ptr, (read32le(ptr) & 0xfff)
@ -213,7 +213,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
#endif
off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error(S, "R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
(long)off64, (long)((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
symtab_section->link->data + sym->st_name);
write32le(ptr, (read32le(ptr) & 0xfff)
@ -222,10 +222,10 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
last_hi.val = val;
return;
case R_RISCV_GOT_HI20:
val = S->got->sh_addr + get_sym_attr(S, sym_index, 0)->got_offset;
val = s1->got->sh_addr + get_sym_attr(s1, sym_index, 0)->got_offset;
off64 = (int64_t)(val - addr + 0x800) >> 12;
if ((off64 + ((uint64_t)1 << 20)) >> 21)
tcc_error(S, "R_RISCV_GOT_HI20 relocation failed");
tcc_error("R_RISCV_GOT_HI20 relocation failed");
last_hi.addr = addr;
last_hi.val = val;
write32le(ptr, (read32le(ptr) & 0xfff)
@ -236,7 +236,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
printf("PCREL_LO12_I: val=%lx addr=%lx\n", (long)val, (long)addr);
#endif
if (val != last_hi.addr)
tcc_error(S, "unsupported hi/lo pcrel reloc scheme");
tcc_error("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val;
addr = last_hi.addr;
write32le(ptr, (read32le(ptr) & 0xfffff)
@ -244,7 +244,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
return;
case R_RISCV_PCREL_LO12_S:
if (val != last_hi.addr)
tcc_error(S, "unsupported hi/lo pcrel reloc scheme");
tcc_error("unsupported hi/lo pcrel reloc scheme");
val = last_hi.val;
addr = last_hi.addr;
off32 = val - addr;
@ -256,7 +256,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_RVC_BRANCH:
off64 = (val - addr);
if ((off64 + (1 << 8)) & ~(uint64_t)0x1fe)
tcc_error(S, "R_RISCV_RVC_BRANCH relocation failed"
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe383)
@ -269,7 +269,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
case R_RISCV_RVC_JUMP:
off64 = (val - addr);
if ((off64 + (1 << 11)) & ~(uint64_t)0xffe)
tcc_error(S, "R_RISCV_RVC_BRANCH relocation failed"
tcc_error("R_RISCV_RVC_BRANCH relocation failed"
" (val=%lx, addr=%lx)", (long)val, (long)addr);
off32 = off64;
write16le(ptr, (read16le(ptr) & 0xe003)
@ -284,7 +284,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
return;
case R_RISCV_32:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
@ -296,8 +296,8 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr,
add32le(ptr, val);
return;
case R_RISCV_64:
if (S->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_RISCV_64);

238
tcc.c
View File

@ -199,40 +199,40 @@ static void print_dirs(const char *msg, char **paths, int nb_paths)
printf(" %s\n", paths[i]);
}
static void print_search_dirs(TCCState *S)
static void print_search_dirs(TCCState *s)
{
printf("install: %s\n", S->tcc_lib_path);
printf("install: %s\n", s->tcc_lib_path);
/* print_dirs("programs", NULL, 0); */
print_dirs("include", S->sysinclude_paths, S->nb_sysinclude_paths);
print_dirs("libraries", S->library_paths, S->nb_library_paths);
print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
print_dirs("libraries", s->library_paths, s->nb_library_paths);
#ifdef TCC_TARGET_PE
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", S->tcc_lib_path);
printf("libtcc1:\n %s/lib/"TCC_LIBTCC1"\n", s->tcc_lib_path);
#else
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", S->tcc_lib_path);
print_dirs("crt", S->crt_paths, S->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(S));
printf("libtcc1:\n %s/"TCC_LIBTCC1"\n", s->tcc_lib_path);
print_dirs("crt", s->crt_paths, s->nb_crt_paths);
printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
#endif
}
static void set_environment(TCCState *S)
static void set_environment(TCCState *s)
{
char * path;
path = getenv("C_INCLUDE_PATH");
if(path != NULL) {
tcc_add_sysinclude_path(S, path);
tcc_add_sysinclude_path(s, path);
}
path = getenv("CPATH");
if(path != NULL) {
tcc_add_include_path(S, path);
tcc_add_include_path(s, path);
}
path = getenv("LIBRARY_PATH");
if(path != NULL) {
tcc_add_library_path(S, path);
tcc_add_library_path(s, path);
}
}
static char *default_outputfile(TCCState *S, const char *first_file)
static char *default_outputfile(TCCState *s, const char *first_file)
{
char buf[1024];
char *ext;
@ -243,18 +243,18 @@ static char *default_outputfile(TCCState *S, const char *first_file)
snprintf(buf, sizeof(buf), "%s", name);
ext = tcc_fileextension(buf);
#ifdef TCC_TARGET_PE
if (S->output_type == TCC_OUTPUT_DLL)
if (s->output_type == TCC_OUTPUT_DLL)
strcpy(ext, ".dll");
else
if (S->output_type == TCC_OUTPUT_EXE)
if (s->output_type == TCC_OUTPUT_EXE)
strcpy(ext, ".exe");
else
#endif
if ((S->just_deps || S->output_type == TCC_OUTPUT_OBJ) && !S->option_r && *ext)
if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
strcpy(ext, ".o");
else
strcpy(buf, "a.out");
return tcc_strdup(S, buf);
return tcc_strdup(buf);
}
static unsigned getclock_ms(void)
@ -268,101 +268,9 @@ static unsigned getclock_ms(void)
#endif
}
#ifdef WITH_ATTACHMENTS
#include "tcc_attachments.h"
#define ATTACH_PREFIX "/_attach_"
static vio_module_t vio_module;
typedef struct vio_memfile_t {
off_t size;
off_t pos;
const unsigned char *mem;
} vio_memfile_t;
static int vio_mem_open(vio_fd *fd, const char *fn, int oflag) {
//printf("%d:%s\n", fd->fd, fn);
if(fd->vio_module && strncmp(ATTACH_PREFIX, fn, sizeof(ATTACH_PREFIX)-1) == 0){
int i, count = sizeof(bin2c_filesAttached)/sizeof(bin2c_filesAttached_st);
for(i=0; i < count; ++i) {
//printf("%s:%s\n", fn, bin2c_filesAttached[i].file_name);
if(strcmp(fn, bin2c_filesAttached[i].file_name) == 0) {
vio_memfile_t *mf = (vio_memfile_t*)tcc_malloc(S, fd->vio_module->tcc_state);
mf->mem = bin2c_filesAttached[i].sym_name;
mf->size = bin2c_filesAttached[i].size;
mf->pos = 0;
fd->fd = 1;
fd->vio_udata = mf;
//printf("%d:%s\n", fd->fd, fn);
return fd->fd;
}
}
}
return -1;
}
static off_t vio_mem_lseek(vio_fd fd, off_t offset, int whence) {
if(fd.vio_udata) {
off_t loffset = 0;
vio_memfile_t *mf = (vio_memfile_t*)fd.vio_udata;
if (whence == SEEK_CUR)
loffset = mf->pos + offset;
else if (whence == SEEK_SET)
loffset = offset;
else if (whence == SEEK_END)
loffset = ((off_t)mf->size) + offset;
if (loffset < 0 && loffset > mf->size)
return -1;
mf->pos = loffset;
return mf->pos;
}
return lseek(fd.fd, offset, whence);
}
static size_t vio_mem_read(vio_fd fd, void *buf, size_t bytes) {
if(fd.vio_udata) {
vio_memfile_t *mf = (vio_memfile_t*)fd.vio_udata;
if( (mf->pos + bytes) > mf->size) {
long bc = mf->size - mf->pos;
if(bc > 0) {
memcpy(buf, mf->mem + mf->pos, bc);
mf->pos = mf->size;
return bc;
}
return 0;
}
memcpy(buf, mf->mem + mf->pos, bytes);
mf->pos += bytes;
return bytes;
}
return 0;
}
static int vio_mem_close(vio_fd *fd) {
if(fd->vio_udata){
tcc_free(S, fd->vio_udata);
}
return 0;
}
void set_vio_module(TCCState *S){
vio_module.user_data = NULL;
vio_module.call_vio_open_flags = CALL_VIO_OPEN_FIRST;
vio_module.vio_open = &vio_mem_open;
vio_module.vio_lseek = &vio_mem_lseek;
vio_module.vio_read = &vio_mem_read;
vio_module.vio_close = &vio_mem_close;
tcc_set_vio_module(s, &vio_module);
}
#endif
int main(int argc0, char **argv0)
{
TCCState *S, *s1;
TCCState *s, *s1;
int ret, opt, n = 0, t = 0, done;
unsigned start_time = 0, end_time = 0;
const char *first_file;
@ -371,19 +279,13 @@ int main(int argc0, char **argv0)
redo:
argc = argc0, argv = argv0;
S = s1 = tcc_new();
opt = tcc_parse_args(S, &argc, &argv, 1);
#ifdef WITH_ATTACHMENTS
tcc_set_lib_path(S, ATTACH_PREFIX);
tcc_add_include_path(S, ATTACH_PREFIX);
set_vio_module(S);
#endif
s = s1 = tcc_new();
opt = tcc_parse_args(s, &argc, &argv, 1);
if (n == 0) {
if (opt == OPT_HELP) {
fputs(help, stdout);
if (!S->verbose)
if (!s->verbose)
return 0;
++opt;
}
@ -392,57 +294,57 @@ redo:
return 0;
}
if (opt == OPT_M32 || opt == OPT_M64)
tcc_tool_cross(S, argv, opt); /* never returns */
if (S->verbose)
tcc_tool_cross(s, argv, opt); /* never returns */
if (s->verbose)
printf(version);
if (opt == OPT_AR)
return tcc_tool_ar(S, argc, argv);
return tcc_tool_ar(s, argc, argv);
#ifdef TCC_TARGET_PE
if (opt == OPT_IMPDEF)
return tcc_tool_impdef(S, argc, argv);
return tcc_tool_impdef(s, argc, argv);
#endif
if (opt == OPT_V)
return 0;
if (opt == OPT_PRINT_DIRS) {
/* initialize search dirs */
set_environment(S);
tcc_set_output_type(S, TCC_OUTPUT_MEMORY);
print_search_dirs(S);
set_environment(s);
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
print_search_dirs(s);
return 0;
}
if (S->nb_files == 0)
tcc_error(S, "no input files");
if (s->nb_files == 0)
tcc_error("no input files");
if (S->output_type == TCC_OUTPUT_PREPROCESS) {
if (S->outfile && 0!=strcmp("-",S->outfile)) {
ppfp = fopen(S->outfile, "w");
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
if (s->outfile && 0!=strcmp("-",s->outfile)) {
ppfp = fopen(s->outfile, "w");
if (!ppfp)
tcc_error(S, "could not write '%s'", S->outfile);
tcc_error("could not write '%s'", s->outfile);
}
} else if (S->output_type == TCC_OUTPUT_OBJ && !S->option_r) {
if (S->nb_libraries)
tcc_error(S, "cannot specify libraries with -c");
if (S->nb_files > 1 && S->outfile)
tcc_error(S, "cannot specify output file with -c many files");
} else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
if (s->nb_libraries)
tcc_error("cannot specify libraries with -c");
if (s->nb_files > 1 && s->outfile)
tcc_error("cannot specify output file with -c many files");
}
if (S->do_bench)
if (s->do_bench)
start_time = getclock_ms();
}
set_environment(S);
if (S->output_type == 0)
S->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(S, S->output_type);
S->ppfp = ppfp;
set_environment(s);
if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE;
tcc_set_output_type(s, s->output_type);
s->ppfp = ppfp;
if ((S->output_type == TCC_OUTPUT_MEMORY
|| S->output_type == TCC_OUTPUT_PREPROCESS)
&& (S->dflag & TCC_OPTION_d_t)) { /* -dt option */
if ((s->output_type == TCC_OUTPUT_MEMORY
|| s->output_type == TCC_OUTPUT_PREPROCESS)
&& (s->dflag & 16)) { /* -dt option */
if (t)
S->dflag |= TCC_OPTION_d_32;
S->run_test = ++t;
s->dflag |= 32;
s->run_test = ++t;
if (n)
--n;
}
@ -450,48 +352,48 @@ redo:
/* compile or add each files or library */
first_file = NULL, ret = 0;
do {
struct filespec *f = S->files[n];
S->filetype = f->type;
struct filespec *f = s->files[n];
s->filetype = f->type;
if (f->type & AFF_TYPE_LIB) {
if (tcc_add_library_err(S, f->name) < 0)
if (tcc_add_library_err(s, f->name) < 0)
ret = 1;
} else {
if (1 == S->verbose)
if (1 == s->verbose)
printf("-> %s\n", f->name);
if (!first_file)
first_file = f->name;
if (tcc_add_file(S, f->name) < 0)
if (tcc_add_file(s, f->name) < 0)
ret = 1;
}
done = ret || ++n >= S->nb_files;
} while (!done && (S->output_type != TCC_OUTPUT_OBJ || S->option_r));
done = ret || ++n >= s->nb_files;
} while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
if (S->do_bench)
if (s->do_bench)
end_time = getclock_ms();
if (S->run_test) {
if (s->run_test) {
t = 0;
} else if (S->output_type == TCC_OUTPUT_PREPROCESS) {
} else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
;
} else if (0 == ret) {
if (S->output_type == TCC_OUTPUT_MEMORY) {
if (s->output_type == TCC_OUTPUT_MEMORY) {
#ifdef TCC_IS_NATIVE
ret = tcc_run(S, argc, argv);
ret = tcc_run(s, argc, argv);
#endif
} else {
if (!S->outfile)
S->outfile = default_outputfile(S, first_file);
if (!S->just_deps && tcc_output_file(S, S->outfile))
if (!s->outfile)
s->outfile = default_outputfile(s, first_file);
if (!s->just_deps && tcc_output_file(s, s->outfile))
ret = 1;
else if (S->gen_deps)
gen_makedeps(S, S->outfile, S->deps_outfile);
else if (s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile);
}
}
if (done && 0 == t && 0 == ret && S->do_bench)
tcc_print_stats(S, end_time - start_time);
if (done && 0 == t && 0 == ret && s->do_bench)
tcc_print_stats(s, end_time - start_time);
tcc_delete(S);
tcc_delete(s);
if (!done)
goto redo; /* compile more files with -c */
if (t)

745
tcc.h
View File

@ -585,7 +585,7 @@ typedef struct Section {
unsigned long data_offset; /* current data offset */
unsigned char *data; /* section data */
unsigned long data_allocated; /* used for realloc() handling */
TCCState *S;
TCCState *s1;
int sh_name; /* elf section name (only used during output) */
int sh_num; /* elf section number */
int sh_type; /* elf section type */
@ -743,78 +743,6 @@ struct sym_attr {
#endif
};
/*From tccpp.c*/
typedef struct TinyAlloc {
unsigned limit;
unsigned size;
uint8_t *buffer;
uint8_t *p;
unsigned nb_allocs;
struct TinyAlloc *next, *top;
#ifdef TAL_INFO
unsigned nb_peak;
unsigned nb_total;
unsigned nb_missed;
uint8_t *peak_p;
#endif
} TinyAlloc;
/*From tccgen.c*/
typedef struct scope_t {
struct scope_t *prev;
struct { int loc, locorig, num; } vla;
struct { Sym *s; int n; } cl;
int *bsym, *csym;
Sym *lstk, *llstk;
} scope_t;
typedef struct switch_t {
struct case_t {
int64_t v1, v2;
int sym;
} **p; int n; /* list of case ranges */
int def_sym; /* default symbol */
int *bsym;
scope_t *scope;
struct switch_t *prev;
SValue sv;
} switch_t;
#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
/*list of temporary local variables on the stack in current function. */
typedef struct temp_local_variable_t {
int location; //offset on stack. Svalue.c.i
short size;
short align;
} temp_local_variable_t;
typedef struct {
unsigned long offset;
unsigned long last_file_name;
unsigned long last_func_name;
int ind;
int line;
} tcov_data_t;
typedef struct {
int debug_type;
Sym *type;
} debug_hash_t;
typedef struct debug_info_t {
int start;
int end;
int n_sym;
struct debug_sym {
int type;
unsigned long value;
char *str;
Section *sec;
int sym_index;
} *sym;
struct debug_info_t *child, *next, *last, *parent;
} debug_info_t;
struct TCCState {
unsigned char verbose; /* if true, display some information during compilation */
unsigned char nostdinc; /* if true, no standard headers are added */
@ -999,11 +927,11 @@ struct TCCState {
int nb_sym_attrs;
/* ptr to next reloc entry reused */
ElfW_Rel *qrel;
#define qrel S->qrel
#define qrel s1->qrel
#ifdef TCC_TARGET_RISCV64
struct pcrel_hi { addr_t addr, val; } last_hi;
#define last_hi S->last_hi
#define last_hi s1->last_hi
#endif
#ifdef TCC_TARGET_PE
@ -1034,10 +962,6 @@ struct TCCState {
const char *runtime_main;
void **runtime_mem;
int nb_runtime_mem;
# ifdef HAVE_SELINUX
void *write_mem;
unsigned long mem_size;
# endif
#endif
#ifdef CONFIG_TCC_BACKTRACE
@ -1067,117 +991,6 @@ struct TCCState {
char *deps_outfile; /* option -MF */
int argc;
char **argv;
/* Entries needed to make it reentrant */
vio_module_t *vio_module;
/* ------------ tccpp.c ------------ */
struct BufferedFile *tccpp_file;
int tccpp_ch, tccpp_tok;
CValue tccpp_tokc;
const int *tccpp_macro_ptr;
int tccpp_parse_flags;
int tccpp_tok_flags;
CString tccpp_tokcstr; /* current parsed string, if any */
CString tccpp_cstr_buf;
CString tccpp_macro_equal_buf;
TokenString tccpp_tokstr_buf;
TokenString *tccpp_macro_stack;
/* display benchmark infos */
int tccpp_total_lines;
int tccpp_total_bytes;
int tccpp_tok_ident;
TokenSym **tccpp_table_ident;
int *tccpp_macro_ptr_allocated;
const int *tccpp_unget_saved_macro_ptr;
int tccpp_unget_saved_buffer[TOK_MAX_SIZE + 1];
int tccpp_unget_buffer_enabled;
TokenSym *tccpp_hash_ident[TOK_HASH_SIZE];
char tccpp_token_buf[STRING_MAX_SIZE + 1];
/* true if isid(c) || isnum(c) */
unsigned char tccpp_isidnum_table[256-CH_EOF];
int tccpp_pp_debug_tok, tccpp_pp_debug_symv;
int tccpp_pp_once;
int tccpp_pp_expr;
int tccpp_pp_counter;
TinyAlloc *tccpp_toksym_alloc;
TinyAlloc *tccpp_tokstr_alloc;
/*----------- tccasm.c --------*/
Section *tccasm_last_text_section; /* to handle .previous asm directive */
/* ------------ tccgen.c ------------ */
Sym *tccgen_global_stack;
Sym *tccgen_local_stack;
Sym *tccgen_local_label_stack;
Sym *tccgen_global_label_stack;
Sym *tccgen_define_stack;
CType tccgen_int_type, tccgen_func_old_type, tccgen_char_type, tccgen_char_pointer_type;
SValue *tccgen_vtop;
SValue tccgen__vstack[1 + VSTACK_SIZE];
int tccgen_rsym, tccgen_anon_sym, tccgen_ind, tccgen_loc;
char tccgen_debug_modes;
int tccgen_const_wanted; /* true if constant wanted */
int tccgen_nocode_wanted; /* true if no code generation wanted for an expression */
int tccgen_global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
CType tccgen_func_vt; /* current function return type (used by return instruction) */
int tccgen_func_var; /* true if current function is variadic */
int tccgen_func_vc;
const char *tccgen_funcname;
Sym *tccgen_sym_free_first;
void **tccgen_sym_pools;
int tccgen_nb_sym_pools;
Sym *tccgen_all_cleanups, *tccgen_pending_gotos;
int tccgen_local_scope;
int tccgen_in_sizeof;
int tccgen_in_generic;
int tccgen_section_sym;
int tccgen_last_line_num, tccgen_new_file, tccgen_func_ind; /* debug info control */
CString tccgen_initstr;
switch_t *tccgen_cur_switch; /* current switch */
temp_local_variable_t tccgen_arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
int tccgen_nb_temp_local_vars;
scope_t *tccgen_cur_scope, *tccgen_loop_scope, *tccgen_root_scope;
tcov_data_t tccgen_tcov_data;
int tccgen_debug_next_type;
debug_hash_t *tccgen_debug_hash;
int tccgen_n_debug_hash;
debug_info_t *tccgen_debug_info, *tccgen_debug_info_root;
unsigned char tccgen_prec[256];
/*--------armg-gen.c-----------*/
/*#if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)*/
CType armgen_float_type, armgen_double_type, armgen_func_float_type, armgen_func_double_type;
/*#endif*/
/*------- tccrun.c ------------*/
/*--------x86_64-gen.c --------*/
unsigned long x86_64_gen_func_sub_sp_offset;
int x86_64_gen_func_ret_sub;
#if defined(CONFIG_TCC_BCHECK)
addr_t func_bound_offset;
unsigned long func_bound_ind;
int func_bound_add_epilog;
#endif
#ifdef TCC_TARGET_PE
int x86_64_gen_func_scratch, x86_64_gen_func_alloca;
#endif
};
struct filespec {
@ -1361,7 +1174,7 @@ enum tcc_token {
/* ------------ libtcc.c ------------ */
//ST_DATA struct TCCState *S;
ST_DATA struct TCCState *tcc_state;
/* public functions currently used by the tcc main function */
ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
@ -1370,56 +1183,53 @@ ST_FUNC char *pstrncpy(char *out, const char *in, size_t num);
PUB_FUNC char *tcc_basename(const char *name);
PUB_FUNC char *tcc_fileextension (const char *name);
PUB_FUNC void tcc_free_base(void *ptr);
PUB_FUNC void *tcc_malloc_base(unsigned long size);
PUB_FUNC void *tcc_mallocz_base(unsigned long size);
#ifndef MEM_DEBUG
PUB_FUNC void tcc_free(TCCState* S, void *ptr);
PUB_FUNC void *tcc_malloc(TCCState* S, unsigned long size);
PUB_FUNC void *tcc_mallocz(TCCState* S, unsigned long size);
PUB_FUNC void *tcc_realloc(TCCState* S, void *ptr, unsigned long size);
PUB_FUNC char *tcc_strdup(TCCState* S, const char *str);
PUB_FUNC void tcc_free(void *ptr);
PUB_FUNC void *tcc_malloc(unsigned long size);
PUB_FUNC void *tcc_mallocz(unsigned long size);
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
PUB_FUNC char *tcc_strdup(const char *str);
#else
#define tcc_free(s, ptr) tcc_free_debug(s, ptr)
#define tcc_malloc(s, size) tcc_malloc_debug(s, size, __FILE__, __LINE__)
#define tcc_mallocz(s, size) tcc_mallocz_debug(s, size, __FILE__, __LINE__)
#define tcc_realloc(s, ptr, size) tcc_realloc_debug(s, ptr, size, __FILE__, __LINE__)
#define tcc_strdup(s, str) tcc_strdup_debug(s, str, __FILE__, __LINE__)
PUB_FUNC void tcc_free_debug(TCCState* S, void *ptr);
PUB_FUNC void *tcc_malloc_debug(TCCState* S, unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_mallocz_debug(TCCState* S, unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_realloc_debug(TCCState* S, void *ptr, unsigned long size, const char *file, int line);
PUB_FUNC char *tcc_strdup_debug(TCCState* S, const char *str, const char *file, int line);
#define tcc_free(ptr) tcc_free_debug(ptr)
#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
PUB_FUNC void tcc_free_debug(void *ptr);
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#endif
#define free(p) use_tcc_free(S, p)
#define malloc(s) use_tcc_malloc(S, s)
#define realloc(p, s) use_tcc_realloc(S, p, s)
#define free(p) use_tcc_free(p)
#define malloc(s) use_tcc_malloc(s)
#define realloc(p, s) use_tcc_realloc(p, s)
#undef strdup
#define strdup(s) use_tcc_strdup(S, s)
PUB_FUNC void _tcc_error_noabort(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
PUB_FUNC NORETURN void _tcc_error(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
PUB_FUNC void _tcc_warning(TCCState* S, const char *fmt, ...) PRINTF_LIKE(2,3);
#define tcc_internal_error(S, msg) tcc_error(S, "internal compiler error\n"\
#define strdup(s) use_tcc_strdup(s)
PUB_FUNC void _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
"%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
/* other utilities */
ST_FUNC void dynarray_add(TCCState* S, void *ptab, int *nb_ptr, void *data);
ST_FUNC void dynarray_reset(TCCState* S, void *pp, int *n);
ST_INLN void cstr_ccat(TCCState* S, CString *cstr, int ch);
ST_FUNC void cstr_cat(TCCState* S, CString *cstr, const char *str, int len);
ST_FUNC void cstr_wccat(TCCState* S, CString *cstr, int ch);
ST_FUNC void cstr_new(TCCState* S, CString *cstr);
ST_FUNC void cstr_free(TCCState* S, CString *cstr);
ST_FUNC int cstr_printf(TCCState* S, CString *cs, const char *fmt, ...) PRINTF_LIKE(3,4);
ST_FUNC int cstr_vprintf(TCCState* S, CString *cstr, const char *fmt, va_list ap);
ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
ST_FUNC void dynarray_reset(void *pp, int *n);
ST_INLN void cstr_ccat(CString *cstr, int ch);
ST_FUNC void cstr_cat(CString *cstr, const char *str, int len);
ST_FUNC void cstr_wccat(CString *cstr, int ch);
ST_FUNC void cstr_new(CString *cstr);
ST_FUNC void cstr_free(CString *cstr);
ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
ST_FUNC void cstr_reset(CString *cstr);
ST_FUNC void tcc_open_bf(TCCState *S, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *S, const char *filename);
ST_FUNC void tcc_close(TCCState *S);
ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
ST_FUNC int tcc_open(TCCState *s1, const char *filename);
ST_FUNC void tcc_close(void);
ST_FUNC int tcc_add_file_internal(TCCState *S, const char *filename, int flags);
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
/* flags: */
#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
@ -1439,26 +1249,26 @@ ST_FUNC int tcc_add_file_internal(TCCState *S, const char *filename, int flags);
#define AFF_BINTYPE_C67 4
#ifndef ELF_OBJ_ONLY
ST_FUNC int tcc_add_crt(TCCState *S, const char *filename);
ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
#endif
#ifndef TCC_TARGET_MACHO
ST_FUNC int tcc_add_dll(TCCState *S, const char *filename, int flags);
ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
#endif
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tcc_add_bcheck(TCCState *S);
ST_FUNC void tcc_add_bcheck(TCCState *s1);
#endif
#ifdef CONFIG_TCC_BACKTRACE
ST_FUNC void tcc_add_btstub(TCCState *S);
ST_FUNC void tcc_add_btstub(TCCState *s1);
#endif
ST_FUNC void tcc_add_pragma_libs(TCCState *S);
PUB_FUNC int tcc_add_library_err(TCCState *S, const char *f);
PUB_FUNC void tcc_print_stats(TCCState *S, unsigned total_time);
PUB_FUNC int tcc_parse_args(TCCState *S, int *argc, char ***argv, int optind);
ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
#ifdef _WIN32
ST_FUNC char *normalize_slashes(char *path);
#endif
ST_FUNC DLLReference *tcc_add_dllref(TCCState *S, const char *dllname);
ST_FUNC char *tcc_load_text(TCCState *S, int fd);
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname);
ST_FUNC char *tcc_load_text(int fd);
/* tcc_parse_args return codes: */
#define OPT_HELP 1
@ -1472,6 +1282,18 @@ ST_FUNC char *tcc_load_text(TCCState *S, int fd);
/* ------------ tccpp.c ------------ */
ST_DATA struct BufferedFile *file;
ST_DATA int ch, tok;
ST_DATA CValue tokc;
ST_DATA const int *macro_ptr;
ST_DATA int parse_flags;
ST_DATA int tok_flags;
ST_DATA CString tokcstr; /* current parsed string, if any */
/* display benchmark infos */
ST_DATA int tok_ident;
ST_DATA TokenSym **table_ident;
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
@ -1499,36 +1321,36 @@ enum line_macro_output_format {
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
};
ST_FUNC TokenSym *tok_alloc(TCCState* S, const char *str, int len);
ST_FUNC int tok_alloc_const(TCCState* S, const char *str);
ST_FUNC const char *get_tok_str(TCCState* S, int v, CValue *cv);
ST_FUNC void begin_macro(TCCState* S, TokenString *str, int alloc);
ST_FUNC void end_macro(TCCState* S);
ST_FUNC int set_idnum(TCCState* S, int c, int val);
ST_FUNC TokenSym *tok_alloc(const char *str, int len);
ST_FUNC int tok_alloc_const(const char *str);
ST_FUNC const char *get_tok_str(int v, CValue *cv);
ST_FUNC void begin_macro(TokenString *str, int alloc);
ST_FUNC void end_macro(void);
ST_FUNC int set_idnum(int c, int val);
ST_INLN void tok_str_new(TokenString *s);
ST_FUNC TokenString *tok_str_alloc(TCCState* S);
ST_FUNC void tok_str_free(TCCState* S, TokenString *s);
ST_FUNC void tok_str_free_str(TCCState* S, int *str);
ST_FUNC void tok_str_add(TCCState* S, TokenString *s, int t);
ST_FUNC void tok_str_add_tok(TCCState* S, TokenString *s);
ST_INLN void define_push(TCCState* S, int v, int macro_type, int *str, Sym *first_arg);
ST_FUNC void define_undef(TCCState* S, Sym *s);
ST_INLN Sym *define_find(TCCState* S, int v);
ST_FUNC void free_defines(TCCState* S, Sym *b);
ST_FUNC Sym *label_find(TCCState* S, int v);
ST_FUNC Sym *label_push(TCCState* S, Sym **ptop, int v, int flags);
ST_FUNC void label_pop(TCCState* S, Sym **ptop, Sym *slast, int keep);
ST_FUNC void parse_define(TCCState* S);
ST_FUNC void preprocess(TCCState* S, int is_bof);
ST_FUNC void next(TCCState* S);
ST_INLN void unget_tok(TCCState* S, int last_tok);
ST_FUNC void preprocess_start(TCCState *S, int filetype);
ST_FUNC void preprocess_end(TCCState *S);
ST_FUNC void tccpp_new(TCCState *S);
ST_FUNC void tccpp_delete(TCCState *S);
ST_FUNC int tcc_preprocess(TCCState *S);
ST_FUNC void skip(TCCState* S, int c);
ST_FUNC NORETURN void expect(TCCState* S, const char *msg);
ST_FUNC TokenString *tok_str_alloc(void);
ST_FUNC void tok_str_free(TokenString *s);
ST_FUNC void tok_str_free_str(int *str);
ST_FUNC void tok_str_add(TokenString *s, int t);
ST_FUNC void tok_str_add_tok(TokenString *s);
ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg);
ST_FUNC void define_undef(Sym *s);
ST_INLN Sym *define_find(int v);
ST_FUNC void free_defines(Sym *b);
ST_FUNC Sym *label_find(int v);
ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep);
ST_FUNC void parse_define(void);
ST_FUNC void preprocess(int is_bof);
ST_FUNC void next(void);
ST_INLN void unget_tok(int last_tok);
ST_FUNC void preprocess_start(TCCState *s1, int filetype);
ST_FUNC void preprocess_end(TCCState *s1);
ST_FUNC void tccpp_new(TCCState *s);
ST_FUNC void tccpp_delete(TCCState *s);
ST_FUNC int tcc_preprocess(TCCState *s1);
ST_FUNC void skip(int c);
ST_FUNC NORETURN void expect(const char *msg);
/* space excluding newline */
static inline int is_space(int ch) {
@ -1550,85 +1372,104 @@ static inline int toup(int c) {
/* ------------ tccgen.c ------------ */
#define SYM_POOL_NB (8192 / sizeof(Sym))
ST_FUNC void tcc_debug_start(TCCState *S);
ST_FUNC void tcc_debug_end(TCCState *S);
ST_FUNC void tcc_debug_bincl(TCCState *S);
ST_FUNC void tcc_debug_eincl(TCCState *S);
ST_FUNC void tcc_debug_putfile(TCCState *S, const char *filename);
ST_FUNC void tccgen_init(TCCState *S);
ST_FUNC int tccgen_compile(TCCState *S);
ST_FUNC void tccgen_finish(TCCState *S);
ST_FUNC void check_vstack(TCCState* S);
ST_DATA Sym *global_stack;
ST_DATA Sym *local_stack;
ST_DATA Sym *local_label_stack;
ST_DATA Sym *global_label_stack;
ST_DATA Sym *define_stack;
ST_DATA CType int_type, func_old_type, char_pointer_type;
ST_DATA SValue *vtop;
ST_DATA int rsym, anon_sym, ind, loc;
ST_DATA char debug_modes;
ST_DATA int const_wanted; /* true if constant wanted */
ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
ST_DATA CType func_vt; /* current function return type (used by return instruction) */
ST_DATA int func_var; /* true if current function is variadic */
ST_DATA int func_vc;
ST_DATA const char *funcname;
ST_FUNC void tcc_debug_start(TCCState *s1);
ST_FUNC void tcc_debug_end(TCCState *s1);
ST_FUNC void tcc_debug_bincl(TCCState *s1);
ST_FUNC void tcc_debug_eincl(TCCState *s1);
ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename);
ST_FUNC void tccgen_init(TCCState *s1);
ST_FUNC int tccgen_compile(TCCState *s1);
ST_FUNC void tccgen_finish(TCCState *s1);
ST_FUNC void check_vstack(void);
ST_INLN int is_float(int t);
ST_FUNC int ieee_finite(double d);
ST_FUNC int exact_log2p1(int i);
ST_FUNC void test_lvalue(TCCState* S);
ST_FUNC void test_lvalue(void);
ST_FUNC ElfSym *elfsym(TCCState* S, Sym *);
ST_FUNC void update_storage(TCCState* S, Sym *sym);
ST_FUNC void put_extern_sym2(TCCState* S, Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
ST_FUNC void put_extern_sym(TCCState* S, Sym *sym, Section *section, addr_t value, unsigned long size);
ST_FUNC ElfSym *elfsym(Sym *);
ST_FUNC void update_storage(Sym *sym);
ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
#if PTR_SIZE == 4
ST_FUNC void greloc(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type);
ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
#endif
ST_FUNC void greloca(TCCState* S, Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
ST_INLN void sym_free(TCCState* S, Sym *sym);
ST_FUNC Sym *sym_push(TCCState* S, int v, CType *type, int r, int c);
ST_FUNC void sym_pop(TCCState* S, Sym **ptop, Sym *b, int keep);
ST_FUNC Sym *sym_push2(TCCState* S, Sym **ps, int v, int t, int c);
ST_INLN void sym_free(Sym *sym);
ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
ST_FUNC Sym *sym_find2(Sym *s, int v);
ST_INLN Sym *sym_find(TCCState* S, int v);
ST_INLN Sym *struct_find(TCCState* S, int v);
ST_INLN Sym *sym_find(int v);
ST_INLN Sym *struct_find(int v);
ST_FUNC Sym *global_identifier_push(TCCState* S, int v, int t, int c);
ST_FUNC Sym *external_global_sym(TCCState* S, int v, CType *type);
ST_FUNC Sym *external_helper_sym(TCCState* S, int v);
ST_FUNC void vpush_helper_func(TCCState* S, int v);
ST_FUNC void vset(TCCState* S, CType *type, int r, int v);
ST_FUNC void vset_VT_CMP(TCCState* S, int op);
ST_FUNC void vpushi(TCCState* S, int v);
ST_FUNC void vpushv(TCCState* S, SValue *v);
ST_FUNC void vpushsym(TCCState* S, CType *type, Sym *sym);
ST_FUNC void vswap(TCCState* S);
ST_FUNC void vrote(TCCState* S, SValue *e, int n);
ST_FUNC void vrott(TCCState* S, int n);
ST_FUNC void vrotb(TCCState* S, int n);
ST_FUNC void vpop(TCCState* S);
ST_FUNC Sym *global_identifier_push(int v, int t, int c);
ST_FUNC Sym *external_global_sym(int v, CType *type);
ST_FUNC Sym *external_helper_sym(int v);
ST_FUNC void vpush_helper_func(int v);
ST_FUNC void vset(CType *type, int r, int v);
ST_FUNC void vset_VT_CMP(int op);
ST_FUNC void vpushi(int v);
ST_FUNC void vpushv(SValue *v);
ST_FUNC void vpushsym(CType *type, Sym *sym);
ST_FUNC void vswap(void);
ST_FUNC void vrote(SValue *e, int n);
ST_FUNC void vrott(int n);
ST_FUNC void vrotb(int n);
ST_FUNC void vpop(void);
#if PTR_SIZE == 4
ST_FUNC void lexpand(TCCState* S);
ST_FUNC void lexpand(void);
#endif
#ifdef TCC_TARGET_ARM
ST_FUNC int get_reg_ex(TCCState* S, int rc, int rc2);
ST_FUNC int get_reg_ex(int rc, int rc2);
#endif
ST_FUNC void save_reg(TCCState* S, int r);
ST_FUNC void save_reg_upstack(TCCState* S, int r, int n);
ST_FUNC int get_reg(TCCState* S, int rc);
ST_FUNC void save_regs(TCCState* S, int n);
ST_FUNC void gaddrof(TCCState* S);
ST_FUNC int gv(TCCState* S, int rc);
ST_FUNC void gv2(TCCState* S, int rc1, int rc2);
ST_FUNC void gen_op(TCCState* S, int op);
ST_FUNC void save_reg(int r);
ST_FUNC void save_reg_upstack(int r, int n);
ST_FUNC int get_reg(int rc);
ST_FUNC void save_regs(int n);
ST_FUNC void gaddrof(void);
ST_FUNC int gv(int rc);
ST_FUNC void gv2(int rc1, int rc2);
ST_FUNC void gen_op(int op);
ST_FUNC int type_size(CType *type, int *a);
ST_FUNC void mk_pointer(TCCState* S, CType *type);
ST_FUNC void vstore(TCCState* S);
ST_FUNC void inc(TCCState* S, int post, int c);
ST_FUNC void parse_mult_str (TCCState* S, CString *astr, const char *msg);
ST_FUNC void parse_asm_str(TCCState* S, CString *astr);
ST_FUNC void indir(TCCState* S);
ST_FUNC void unary(TCCState* S);
ST_FUNC void gexpr(TCCState* S);
ST_FUNC int expr_const(TCCState* S);
ST_FUNC void mk_pointer(CType *type);
ST_FUNC void vstore(void);
ST_FUNC void inc(int post, int c);
ST_FUNC void parse_mult_str (CString *astr, const char *msg);
ST_FUNC void parse_asm_str(CString *astr);
ST_FUNC void indir(void);
ST_FUNC void unary(void);
ST_FUNC void gexpr(void);
ST_FUNC int expr_const(void);
#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
ST_FUNC Sym *get_sym_ref(TCCState* S, CType *type, Section *sec, unsigned long offset, unsigned long size);
ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
#endif
#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
ST_FUNC int classify_x86_64_va_arg(CType *ty);
#endif
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void gbound_args(TCCState* S, int nb_args);
ST_FUNC void gbound_args(int nb_args);
ST_DATA int func_bound_add_epilog;
#endif
@ -1648,51 +1489,51 @@ typedef struct {
unsigned int n_value; /* value of symbol */
} Stab_Sym;
ST_FUNC void tccelf_new(TCCState *S);
ST_FUNC void tccelf_delete(TCCState *S);
ST_FUNC void tccelf_stab_new(TCCState *S);
ST_FUNC void tccelf_begin_file(TCCState *S);
ST_FUNC void tccelf_end_file(TCCState *S);
ST_FUNC void tccelf_new(TCCState *s);
ST_FUNC void tccelf_delete(TCCState *s);
ST_FUNC void tccelf_stab_new(TCCState *s);
ST_FUNC void tccelf_begin_file(TCCState *s1);
ST_FUNC void tccelf_end_file(TCCState *s1);
#ifdef CONFIG_TCC_BCHECK
ST_FUNC void tccelf_bounds_new(TCCState *S);
ST_FUNC void tccelf_bounds_new(TCCState *s);
#endif
ST_FUNC Section *new_section(TCCState *S, const char *name, int sh_type, int sh_flags);
ST_FUNC void section_realloc(TCCState* S, Section *sec, unsigned long new_size);
ST_FUNC size_t section_add(TCCState* S, Section *sec, addr_t size, int align);
ST_FUNC void *section_ptr_add(TCCState* S, Section *sec, addr_t size);
ST_FUNC Section *find_section(TCCState *S, const char *name);
ST_FUNC Section *new_symtab(TCCState *S, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
ST_FUNC Section *find_section(TCCState *s1, const char *name);
ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
ST_FUNC int put_elf_str(TCCState* S, Section *s, const char *sym);
ST_FUNC int put_elf_sym(TCCState* S, Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int set_elf_sym(Section *S, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int find_elf_sym(Section *S, const char *name);
ST_FUNC int put_elf_str(Section *s, const char *sym);
ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
ST_FUNC int find_elf_sym(Section *s, const char *name);
ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
ST_FUNC void put_stabs(TCCState *S, const char *str, int type, int other, int desc, unsigned long value);
ST_FUNC void put_stabs_r(TCCState *S, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
ST_FUNC void put_stabn(TCCState *S, int type, int other, int desc, int value);
ST_FUNC void put_stabs(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value);
ST_FUNC void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc, unsigned long value, Section *sec, int sym_index);
ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value);
ST_FUNC void resolve_common_syms(TCCState *S);
ST_FUNC void relocate_syms(TCCState *S, Section *symtab, int do_resolve);
ST_FUNC void relocate_sections(TCCState *S);
ST_FUNC void resolve_common_syms(TCCState *s1);
ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
ST_FUNC void relocate_sections(TCCState *s1);
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
ST_FUNC void *load_data(TCCState* S, int fd, unsigned long file_offset, unsigned long size);
ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size);
ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
ST_FUNC int tcc_load_object_file(TCCState *S, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *S, int fd, int alacarte);
ST_FUNC void add_array(TCCState *S, const char *sec, int c);
ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
ST_FUNC void add_array(TCCState *s1, const char *sec, int c);
#if !defined(ELF_OBJ_ONLY) || (defined(TCC_TARGET_MACHO) && defined TCC_IS_NATIVE)
ST_FUNC void build_got_entries(TCCState *S);
ST_FUNC void build_got_entries(TCCState *s1);
#endif
ST_FUNC struct sym_attr *get_sym_attr(TCCState *S, int index, int alloc);
ST_FUNC addr_t get_sym_addr(TCCState *S, const char *name, int err, int forc);
ST_FUNC void list_elf_symbols(TCCState *S, void *ctx,
ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
void (*symbol_cb)(void *ctx, const char *name, const void *val));
ST_FUNC int set_global_sym(TCCState *S, const char *name, Section *sec, addr_t offs);
ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
using variable <elem> */
@ -1701,11 +1542,11 @@ ST_FUNC int set_global_sym(TCCState *S, const char *name, Section *sec, addr_t o
elem < (type *) (sec->data + sec->data_offset); elem++)
#ifndef ELF_OBJ_ONLY
ST_FUNC int tcc_load_dll(TCCState *S, int fd, const char *filename, int level);
ST_FUNC int tcc_load_ldscript(TCCState *S, int fd);
ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
#endif
#ifndef TCC_TARGET_PE
ST_FUNC void tcc_add_runtime(TCCState *S);
ST_FUNC void tcc_add_runtime(TCCState *s1);
#endif
/* ------------ xxx-link.c ------------ */
@ -1723,41 +1564,41 @@ enum gotplt_entry {
ST_FUNC int code_reloc (int reloc_type);
ST_FUNC int gotplt_entry_type (int reloc_type);
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr);
ST_FUNC void relocate_plt(TCCState *S);
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
ST_FUNC void relocate_plt(TCCState *s1);
#endif
#endif
ST_FUNC void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
/* ------------ xxx-gen.c ------------ */
ST_DATA const char * const target_machine_defs;
ST_DATA const int reg_classes[NB_REGS];
ST_FUNC void gsym_addr(TCCState* S, int t, int a);
ST_FUNC void gsym(TCCState* S, int t);
ST_FUNC void load(TCCState *S, int r, SValue *sv);
ST_FUNC void store(TCCState *S, int r, SValue *v);
ST_FUNC void gsym_addr(int t, int a);
ST_FUNC void gsym(int t);
ST_FUNC void load(int r, SValue *sv);
ST_FUNC void store(int r, SValue *v);
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
ST_FUNC void gfunc_call(TCCState *S, int nb_args);
ST_FUNC void gfunc_prolog(TCCState *S, Sym *func_sym);
ST_FUNC void gfunc_epilog(TCCState *S);
ST_FUNC void gen_fill_nops(TCCState* S, int);
ST_FUNC int gjmp(TCCState* S, int t);
ST_FUNC void gjmp_addr(TCCState* S, int a);
ST_FUNC int gjmp_cond(TCCState* S, int op, int t);
ST_FUNC int gjmp_append(TCCState *S, int n, int t);
ST_FUNC void gen_opi(TCCState* S, int op);
ST_FUNC void gen_opf(TCCState* S, int op);
ST_FUNC void gen_cvt_ftoi(TCCState *S, int t);
ST_FUNC void gen_cvt_itof(TCCState *S, int t);
ST_FUNC void gen_cvt_ftof(TCCState *S, int t);
ST_FUNC void ggoto(TCCState *S);
ST_FUNC void gfunc_call(int nb_args);
ST_FUNC void gfunc_prolog(Sym *func_sym);
ST_FUNC void gfunc_epilog(void);
ST_FUNC void gen_fill_nops(int);
ST_FUNC int gjmp(int t);
ST_FUNC void gjmp_addr(int a);
ST_FUNC int gjmp_cond(int op, int t);
ST_FUNC int gjmp_append(int n, int t);
ST_FUNC void gen_opi(int op);
ST_FUNC void gen_opf(int op);
ST_FUNC void gen_cvt_ftoi(int t);
ST_FUNC void gen_cvt_itof(int t);
ST_FUNC void gen_cvt_ftof(int t);
ST_FUNC void ggoto(void);
#ifndef TCC_TARGET_C67
ST_FUNC void o(TCCState* S, unsigned int c);
ST_FUNC void o(unsigned int c);
#endif
ST_FUNC void gen_vla_sp_save(TCCState* S, int addr);
ST_FUNC void gen_vla_sp_restore(TCCState* S, int addr);
ST_FUNC void gen_vla_alloc(TCCState* S, CType *type, int align);
ST_FUNC void gen_vla_sp_save(int addr);
ST_FUNC void gen_vla_sp_restore(int addr);
ST_FUNC void gen_vla_alloc(CType *type, int align);
static inline uint16_t read16le(unsigned char *p) {
return p[0] | (uint16_t)p[1] << 8;
@ -1786,57 +1627,57 @@ static inline void add64le(unsigned char *p, int64_t x) {
/* ------------ i386-gen.c ------------ */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
ST_FUNC void g(TCCState* S, int c);
ST_FUNC void gen_le16(TCCState* S, int c);
ST_FUNC void gen_le32(TCCState* S, int c);
ST_FUNC void g(int c);
ST_FUNC void gen_le16(int c);
ST_FUNC void gen_le32(int c);
#endif
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC void gen_addr32(TCCState* S, int r, Sym *sym, int c);
ST_FUNC void gen_addrpc32(TCCState* S, int r, Sym *sym, int c);
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
ST_FUNC void gen_addr32(int r, Sym *sym, int c);
ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
ST_FUNC void gen_cvt_csti(int t);
ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
/* ------------ x86_64-gen.c ------------ */
#ifdef TCC_TARGET_X86_64
ST_FUNC void gen_addr64(TCCState* S, int r, Sym *sym, int64_t c);
ST_FUNC void gen_opl(TCCState* S, int op);
ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
ST_FUNC void gen_opl(int op);
#ifdef TCC_TARGET_PE
ST_FUNC void gen_vla_result(TCCState* S, int addr);
ST_FUNC void gen_vla_result(int addr);
#endif
ST_FUNC void gen_cvt_sxtw(TCCState *S);
ST_FUNC void gen_cvt_csti(TCCState* S, int t);
ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_cvt_csti(int t);
#endif
/* ------------ arm-gen.c ------------ */
#ifdef TCC_TARGET_ARM
#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
PUB_FUNC const char *default_elfinterp(TCCState *S);
PUB_FUNC const char *default_elfinterp(struct TCCState *s);
#endif
ST_FUNC void arm_init(TCCState *S);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
ST_FUNC void arm_init(struct TCCState *s);
ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
/* ------------ arm64-gen.c ------------ */
#ifdef TCC_TARGET_ARM64
ST_FUNC void gen_opl(TCCState* S, int op);
ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
ST_FUNC void gen_va_start(TCCState *S);
ST_FUNC void gen_va_arg(TCCState *S, CType *t);
ST_FUNC void gen_clear_cache(TCCState *S);
ST_FUNC void gen_cvt_sxtw(TCCState *S);
ST_FUNC void gen_cvt_csti(TCCState *S, int t);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
ST_FUNC void gen_opl(int op);
ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(void);
ST_FUNC void gen_va_arg(CType *t);
ST_FUNC void gen_clear_cache(void);
ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_cvt_csti(int t);
ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
/* ------------ riscv64-gen.c ------------ */
#ifdef TCC_TARGET_RISCV64
ST_FUNC void gen_opl(TCCState* S, int op);
//ST_FUNC void gfunc_return(TCCState *S, CType *func_type);
ST_FUNC void gen_va_start(TCCState *S);
ST_FUNC void arch_transfer_ret_regs(TCCState* S, int);
ST_FUNC void gen_cvt_sxtw(TCCState *S);
ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
ST_FUNC void gen_opl(int op);
//ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(void);
ST_FUNC void arch_transfer_ret_regs(int);
ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_increment_tcov (SValue *sv);
#endif
/* ------------ c67-gen.c ------------ */
@ -1846,44 +1687,44 @@ ST_FUNC void gen_increment_tcov (TCCState* S, SValue *sv);
/* ------------ tcccoff.c ------------ */
#ifdef TCC_TARGET_COFF
ST_FUNC int tcc_output_coff(TCCState *S, FILE *f);
ST_FUNC int tcc_load_coff(TCCState *S, int fd);
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f);
ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
#endif
/* ------------ tccasm.c ------------ */
ST_FUNC void asm_instr(TCCState* S);
ST_FUNC void asm_global_instr(TCCState* S);
ST_FUNC int tcc_assemble(TCCState *S, int do_preprocess);
ST_FUNC void asm_instr(void);
ST_FUNC void asm_global_instr(void);
ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
#ifdef CONFIG_TCC_ASM
ST_FUNC int find_constraint(TCCState* S, ASMOperand *operands, int nb_operands, const char *name, const char **pp);
ST_FUNC Sym* get_asm_sym(TCCState* S, int name, Sym *csym);
ST_FUNC void asm_expr(TCCState *S, ExprValue *pe);
ST_FUNC int asm_int_expr(TCCState *S);
ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
ST_FUNC int asm_int_expr(TCCState *s1);
/* ------------ i386-asm.c ------------ */
ST_FUNC void gen_expr32(TCCState* S, ExprValue *pe);
ST_FUNC void gen_expr32(ExprValue *pe);
#ifdef TCC_TARGET_X86_64
ST_FUNC void gen_expr64(TCCState* S, ExprValue *pe);
ST_FUNC void gen_expr64(ExprValue *pe);
#endif
ST_FUNC void asm_opcode(TCCState *S, int opcode);
ST_FUNC int asm_parse_regvar(TCCState* S, int t);
ST_FUNC void asm_compute_constraints(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
ST_FUNC void subst_asm_operand(TCCState* S, CString *add_str, SValue *sv, int modifier);
ST_FUNC void asm_gen_code(TCCState* S, ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
ST_FUNC void asm_clobber(TCCState* S, uint8_t *clobber_regs, const char *str);
ST_FUNC void asm_opcode(TCCState *s1, int opcode);
ST_FUNC int asm_parse_regvar(int t);
ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
#endif
/* ------------ tccpe.c -------------- */
#ifdef TCC_TARGET_PE
ST_FUNC int pe_load_file(struct TCCState *S, int fd, const char *filename);
ST_FUNC int pe_output_file(TCCState * S, const char *filename);
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value);
ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename);
ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC SValue *pe_getimport(TCCState * S, SValue *sv, SValue *v2);
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
#endif
#ifdef TCC_TARGET_X86_64
ST_FUNC void pe_add_unwind_data(TCCState* S, unsigned start, unsigned end, unsigned stack);
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
#endif
PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp);
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
/* symbol properties stored in Elf32_Sym->st_other */
# define ST_PE_EXPORT 0x10
# define ST_PE_IMPORT 0x20
@ -1893,11 +1734,11 @@ PUB_FUNC int tcc_get_dllexports(TCCState* S, const char *filename, char **pp);
/* ------------ tccmacho.c ----------------- */
#ifdef TCC_TARGET_MACHO
ST_FUNC int macho_output_file(TCCState * S, const char *filename);
ST_FUNC int macho_load_dll(TCCState *S, int fd, const char *filename, int lev);
ST_FUNC int macho_load_tbd(TCCState *S, int fd, const char *filename, int lev);
ST_FUNC int macho_output_file(TCCState * s1, const char *filename);
ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev);
ST_FUNC int macho_load_tbd(TCCState *s1, int fd, const char *filename, int lev);
#ifdef TCC_IS_NATIVE
ST_FUNC void tcc_add_macos_sdkpath(TCCState* S);
ST_FUNC void tcc_add_macos_sdkpath(TCCState* s);
ST_FUNC const char* macho_tbd_soname(const char* filename);
#endif
#endif
@ -1914,17 +1755,17 @@ ST_FUNC void dlclose(void *p);
ST_FUNC const char *dlerror(void);
ST_FUNC void *dlsym(void *handle, const char *symbol);
#endif
ST_FUNC void tcc_run_free(TCCState *S);
ST_FUNC void tcc_run_free(TCCState *s1);
#endif
/* ------------ tcctools.c ----------------- */
#if 0 /* included in tcc.c */
ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv);
ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
#ifdef TCC_TARGET_PE
ST_FUNC int tcc_tool_impdef(TCCState *S, int argc, char **argv);
ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
#endif
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int option);
ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename);
ST_FUNC void tcc_tool_cross(TCCState *s, char **argv, int option);
ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename);
#endif
/********************************************************/
@ -1979,12 +1820,12 @@ ST_FUNC void post_sem(TCCSem *p);
#define total_lines TCC_STATE_VAR(total_lines)
#define total_bytes TCC_STATE_VAR(total_bytes)
PUB_FUNC void tcc_enter_state(TCCState *S);
PUB_FUNC void tcc_exit_state(TCCState *S);
PUB_FUNC void tcc_enter_state(TCCState *s1);
PUB_FUNC void tcc_exit_state(TCCState *s1);
/* conditional warning depending on switch */
#define tcc_warning_c(sw) TCC_SET_STATE((\
S->warn_num = offsetof(TCCState, sw) \
tcc_state->warn_num = offsetof(TCCState, sw) \
- offsetof(TCCState, warn_none), _tcc_warning))
/********************************************************/
@ -1994,10 +1835,10 @@ PUB_FUNC void tcc_exit_state(TCCState *S);
#undef TCC_SET_STATE
#ifdef USING_GLOBALS
# define TCC_STATE_VAR(sym) S->sym
# define TCC_STATE_VAR(sym) tcc_state->sym
# define TCC_SET_STATE(fn) fn
# undef USING_GLOBALS
#else
# define TCC_STATE_VAR(sym) S->sym
# define TCC_SET_STATE(fn) (tcc_enter_state(S),fn)
# define TCC_STATE_VAR(sym) s1->sym
# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
#endif

834
tccasm.c

File diff suppressed because it is too large Load Diff

116
tcccoff.c
View File

@ -40,12 +40,12 @@ int FuncEntries[MAX_FUNCS];
int OutputTheSection(Section * sect);
short int GetCoffFlags(const char *s);
void SortSymbolTable(TCCState *S);
Section *FindSection(TCCState * S, const char *sname);
void SortSymbolTable(TCCState *s1);
Section *FindSection(TCCState * s1, const char *sname);
int C67_main_entry_point;
int FindCoffSymbolIndex(TCCState * S, const char *func_name);
int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
int nb_syms;
typedef struct {
@ -74,7 +74,7 @@ typedef struct {
unsigned short dummy4;
} AUXEF;
ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
{
Section *tcc_sect;
SCNHDR *coff_sec;
@ -87,12 +87,12 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
Coff_str_table = pCoff_str_table = NULL;
stext = FindSection(S, ".text");
sdata = FindSection(S, ".data");
sbss = FindSection(S, ".bss");
stext = FindSection(s1, ".text");
sdata = FindSection(s1, ".data");
sbss = FindSection(s1, ".bss");
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
coff_nb_syms = FindCoffSymbolIndex(S, "XXXXXXXXXX1");
coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
file_hdr.f_timdat = 0; /* time & date stamp */
@ -116,9 +116,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
CoffTextSectionNo = -1;
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
NSectionsToOutput++;
@ -149,9 +149,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// for the raw data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put raw data
@ -163,9 +163,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// now loop through and determine file pointer locations
// for the relocation data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
@ -179,14 +179,14 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// now loop through and determine file pointer locations
// for the line number data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
coff_sec->s_nlnno = 0;
coff_sec->s_lnnoptr = 0;
if (S->do_debug && tcc_sect == stext) {
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
// also find association between source file name and function
@ -314,7 +314,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
if (S->do_debug)
if (s1->do_debug)
file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
else
file_hdr.f_nsyms = 0;
@ -328,9 +328,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
// write section headers
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(coff_sec, sizeof(SCNHDR), 1, f);
@ -338,9 +338,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
}
// write raw data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
@ -348,9 +348,9 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
}
// write relocation data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (OutputTheSection(tcc_sect)) {
// put relocations data
@ -365,16 +365,16 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
if (S->do_debug)
SortSymbolTable(S);
if (s1->do_debug)
SortSymbolTable(s1);
// write line no data
for (i = 1; i < S->nb_sections; i++) {
for (i = 1; i < s1->nb_sections; i++) {
coff_sec = &section_header[i];
tcc_sect = S->sections[i];
tcc_sect = s1->sections[i];
if (S->do_debug && tcc_sect == stext) {
if (s1->do_debug && tcc_sect == stext) {
// count how many line nos data
@ -437,7 +437,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// output a function begin
CoffLineNo.l_addr.l_symndx =
FindCoffSymbolIndex(S, func_name);
FindCoffSymbolIndex(s1, func_name);
CoffLineNo.l_lnno = 0;
fwrite(&CoffLineNo, 6, 1, f);
@ -502,7 +502,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
}
// write symbol table
if (S->do_debug) {
if (s1->do_debug) {
int k;
struct syment csym;
AUXFUNC auxfunc;
@ -514,7 +514,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
int nstr;
int n = 0;
Coff_str_table = (char *) tcc_malloc(S, MAX_STR_TABLE);
Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
pCoff_str_table = Coff_str_table;
nstr = 0;
@ -533,7 +533,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
} else {
if (pCoff_str_table - Coff_str_table + strlen(name) >
MAX_STR_TABLE - 1)
tcc_error(S, "String table too large");
tcc_error("String table too large");
csym._n._n_n._n_zeroes = 0;
csym._n._n_n._n_offset =
@ -563,7 +563,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
}
if (k >= nFuncs) {
tcc_error(S, "debug info can't find function: %s", name);
tcc_error("debug info can't find function: %s", name);
}
// put a Function Name
@ -669,7 +669,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
}
}
if (S->do_debug) {
if (s1->do_debug) {
// write string table
// first write the size
@ -679,7 +679,7 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// then write the strings
fwrite(Coff_str_table, i, 1, f);
tcc_free(S, Coff_str_table);
tcc_free(Coff_str_table);
}
return 0;
@ -690,13 +690,13 @@ ST_FUNC int tcc_output_coff(TCCState *S, FILE *f)
// group the symbols in order of filename, func1, func2, etc
// finally global symbols
void SortSymbolTable(TCCState *S)
void SortSymbolTable(TCCState *s1)
{
int i, j, k, n = 0;
Elf32_Sym *p, *p2, *NewTable;
char *name, *name2;
NewTable = (Elf32_Sym *) tcc_malloc(S, nb_syms * sizeof(Elf32_Sym));
NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
p = (Elf32_Sym *) symtab_section->data;
@ -730,7 +730,7 @@ void SortSymbolTable(TCCState *S)
}
if (k >= nFuncs) {
tcc_error(S, "debug (sort) info can't find function: %s", name2);
tcc_error("debug (sort) info can't find function: %s", name2);
}
if (strcmp(AssociatedFile[k], name) == 0) {
@ -757,7 +757,7 @@ void SortSymbolTable(TCCState *S)
}
if (n != nb_syms)
tcc_error(S, "Internal Compiler error, debug info");
tcc_error("Internal Compiler error, debug info");
// copy it all back
@ -766,11 +766,11 @@ void SortSymbolTable(TCCState *S)
*p++ = NewTable[i];
}
tcc_free(S, NewTable);
tcc_free(NewTable);
}
int FindCoffSymbolIndex(TCCState *S, const char *func_name)
int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
{
int i, n = 0;
Elf32_Sym *p;
@ -842,23 +842,23 @@ short int GetCoffFlags(const char *s)
return 0;
}
Section *FindSection(TCCState * S, const char *sname)
Section *FindSection(TCCState * s1, const char *sname)
{
Section *s;
int i;
for (i = 1; i < S->nb_sections; i++) {
s = S->sections[i];
for (i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (!strcmp(sname, s->name))
return s;
}
tcc_error(S, "could not find section %s", sname);
tcc_error("could not find section %s", sname);
return 0;
}
ST_FUNC int tcc_load_coff(TCCState * S, int fd)
ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
{
// tktk TokenSym *ts;
@ -872,39 +872,39 @@ ST_FUNC int tcc_load_coff(TCCState * S, int fd)
f = fdopen(fd, "rb");
if (!f) {
tcc_error(S, "Unable to open .out file for input");
tcc_error("Unable to open .out file for input");
}
if (fread(&file_hdr, FILHSZ, 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
// first read the string table
if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
if (fread(&str_size, sizeof(int), 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
Coff_str_table = (char *) tcc_malloc(S, str_size);
Coff_str_table = (char *) tcc_malloc(str_size);
if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
// read/process all the symbols
// seek back to symbols
if (fseek(f, file_hdr.f_symptr, SEEK_SET))
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
for (i = 0; i < file_hdr.f_nsyms; i++) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
if (csym._n._n_n._n_zeroes == 0) {
name = Coff_str_table + csym._n._n_n._n_offset - 4;
@ -933,13 +933,13 @@ ST_FUNC int tcc_load_coff(TCCState * S, int fd)
if (name[0] == '_' && strcmp(name, "_main") != 0)
name++;
tcc_add_symbol(S, name, (void*)(uintptr_t)csym.n_value);
tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
}
// skip any aux records
if (csym.n_numaux == 1) {
if (fread(&csym, SYMESZ, 1, f) != 1)
tcc_error(S, "error reading .out file for input");
tcc_error("error reading .out file for input");
i++;
}
}

1345
tccelf.c

File diff suppressed because it is too large Load Diff

5334
tccgen.c

File diff suppressed because it is too large Load Diff

View File

@ -249,19 +249,19 @@ struct macho {
#define SHT_LINKEDIT (SHT_LOOS + 42)
#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */
static void * add_lc(TCCState* S, struct macho *mo, uint32_t cmd, uint32_t cmdsize)
static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize)
{
struct load_command *lc = tcc_mallocz(S, cmdsize);
struct load_command *lc = tcc_mallocz(cmdsize);
lc->cmd = cmd;
lc->cmdsize = cmdsize;
mo->lc = tcc_realloc(S, mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1));
mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1));
mo->lc[mo->nlc++] = lc;
return lc;
}
static struct segment_command_64 * add_segment(TCCState* S, struct macho *mo, const char *name)
static struct segment_command_64 * add_segment(struct macho *mo, const char *name)
{
struct segment_command_64 *sc = add_lc(S, mo, LC_SEGMENT_64, sizeof(*sc));
struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc));
strncpy(sc->segname, name, 16);
mo->seg2lc[mo->nseg++] = mo->nlc - 1;
return sc;
@ -272,14 +272,14 @@ static struct segment_command_64 * get_segment(struct macho *mo, int i)
return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]);
}
static int add_section(TCCState* S, struct macho *mo, struct segment_command_64 **_seg, const char *name)
static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name)
{
struct segment_command_64 *seg = *_seg;
int ret = seg->nsects;
struct section_64 *sec;
seg->nsects++;
seg->cmdsize += sizeof(*sec);
seg = tcc_realloc(S, seg, sizeof(*seg) + seg->nsects * sizeof(*sec));
seg = tcc_realloc(seg, sizeof(*seg) + seg->nsects * sizeof(*sec));
sec = (struct section_64*)((char*)seg + sizeof(*seg)) + ret;
memset(sec, 0, sizeof(*sec));
strncpy(sec->sectname, name, 16);
@ -293,11 +293,11 @@ static struct section_64 *get_section(struct segment_command_64 *seg, int i)
return (struct section_64*)((char*)seg + sizeof(*seg)) + i;
}
static void * add_dylib(TCCState* S, struct macho *mo, char *name)
static void * add_dylib(struct macho *mo, char *name)
{
struct dylib_command *lc;
int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8;
lc = add_lc(S, mo, LC_LOAD_DYLIB, sz);
lc = add_lc(mo, LC_LOAD_DYLIB, sz);
lc->name = sizeof(*lc);
strcpy((char*)lc + lc->name, name);
lc->timestamp = 2;
@ -306,7 +306,7 @@ static void * add_dylib(TCCState* S, struct macho *mo, char *name)
return lc;
}
static void check_relocs(TCCState *S, struct macho *mo)
static void check_relocs(TCCState *s1, struct macho *mo)
{
Section *s;
ElfW_Rel *rel;
@ -314,10 +314,10 @@ static void check_relocs(TCCState *S, struct macho *mo)
int i, type, gotplt_entry, sym_index, for_code;
struct sym_attr *attr;
S->got = new_section(S, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
mo->indirsyms = new_section(S, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
for (i = 1; i < S->nb_sections; i++) {
s = S->sections[i];
s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
for (i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
if (s->sh_type != SHT_RELX)
continue;
for_each_elem(s, 0, rel, ElfW_Rel) {
@ -331,21 +331,21 @@ static void check_relocs(TCCState *S, struct macho *mo)
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (sym->st_shndx == SHN_UNDEF
|| gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
attr = get_sym_attr(S, sym_index, 1);
attr = get_sym_attr(s1, sym_index, 1);
if (!attr->dyn_index) {
uint32_t *pi = section_ptr_add(S, mo->indirsyms, sizeof(*pi));
attr->got_offset = S->got->data_offset;
uint32_t *pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
attr->got_offset = s1->got->data_offset;
attr->plt_offset = -1;
attr->dyn_index = 1; /* used as flag */
section_ptr_add(S, S->got, PTR_SIZE);
section_ptr_add(s1->got, PTR_SIZE);
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
if (sym->st_shndx == SHN_UNDEF)
tcc_error(S, "undefined local symbol???");
tcc_error("undefined local symbol???");
*pi = INDIRECT_SYMBOL_LOCAL;
/* The pointer slot we generated must point to the
symbol, whose address is only known after layout,
so register a simple relocation for that. */
put_elf_reloc(S->symtab, S->got, attr->got_offset,
put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
R_DATA_PTR, sym_index);
} else
*pi = mo->e2msym[sym_index];
@ -354,10 +354,10 @@ static void check_relocs(TCCState *S, struct macho *mo)
if (attr->plt_offset == -1) {
uint8_t *jmp;
attr->plt_offset = mo->stubs->data_offset;
jmp = section_ptr_add(S, mo->stubs, 6);
jmp = section_ptr_add(mo->stubs, 6);
jmp[0] = 0xff; /* jmpq *ofs(%rip) */
jmp[1] = 0x25;
put_elf_reloc(S->symtab, mo->stubs,
put_elf_reloc(s1->symtab, mo->stubs,
attr->plt_offset + 2,
R_X86_64_GOTPCREL, sym_index);
}
@ -369,7 +369,7 @@ static void check_relocs(TCCState *S, struct macho *mo)
}
}
static int check_symbols(TCCState *S, struct macho *mo)
static int check_symbols(TCCState *s1, struct macho *mo)
{
int sym_index, sym_end;
int ret = 0;
@ -391,17 +391,17 @@ static int check_symbols(TCCState *S, struct macho *mo)
if (mo->ilocal == -1)
mo->ilocal = sym_index - 1;
if (mo->iextdef != -1 || mo->iundef != -1)
tcc_error(S, "local syms after global ones");
tcc_error("local syms after global ones");
} else if (sym->st_shndx != SHN_UNDEF) {
if (mo->iextdef == -1)
mo->iextdef = sym_index - 1;
if (mo->iundef != -1)
tcc_error(S, "external defined symbol after undefined");
tcc_error("external defined symbol after undefined");
} else if (sym->st_shndx == SHN_UNDEF) {
if (mo->iundef == -1)
mo->iundef = sym_index - 1;
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
|| find_elf_sym(S->dynsymtab_section, name)) {
|| find_elf_sym(s1->dynsymtab_section, name)) {
/* Mark the symbol as coming from a dylib so that
relocate_syms doesn't complain. Normally bind_exe_dynsyms
would do this check, and place the symbol into dynsym
@ -410,14 +410,14 @@ static int check_symbols(TCCState *S, struct macho *mo)
sym->st_shndx = SHN_FROMDLL;
continue;
}
tcc_error_noabort(S, "undefined symbol '%s'", name);
tcc_error_noabort("undefined symbol '%s'", name);
ret = -1;
}
}
return ret;
}
static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn)
static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn)
{
struct nlist_64 n = *pn;
ElfSym *sym = (ElfW(Sym) *)symtab_section->data + pn->n_value;
@ -433,19 +433,19 @@ static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn)
n.n_type = N_ABS;
break;
default:
tcc_error(S, "unhandled ELF symbol type %d %s",
tcc_error("unhandled ELF symbol type %d %s",
ELFW(ST_TYPE)(sym->st_info), name);
}
if (sym->st_shndx == SHN_UNDEF)
tcc_error(S, "should have been rewritten to SHN_FROMDLL: %s", name);
tcc_error("should have been rewritten to SHN_FROMDLL: %s", name);
else if (sym->st_shndx == SHN_FROMDLL)
n.n_type = N_UNDF, n.n_sect = 0;
else if (sym->st_shndx == SHN_ABS)
n.n_type = N_ABS, n.n_sect = 0;
else if (sym->st_shndx >= SHN_LORESERVE)
tcc_error(S, "unhandled ELF symbol section %d %s", sym->st_shndx, name);
tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name);
else if (!mo->elfsectomacho[sym->st_shndx])
tcc_error(S, "ELF section %d not mapped into Mach-O for symbol %s",
tcc_error("ELF section %d not mapped into Mach-O for symbol %s",
sym->st_shndx, name);
else
n.n_sect = mo->elfsectomacho[sym->st_shndx];
@ -458,15 +458,16 @@ static void convert_symbol(TCCState *S, struct macho *mo, struct nlist_64 *pn)
*pn = n;
}
static void convert_symbols(TCCState *S, struct macho *mo)
static void convert_symbols(TCCState *s1, struct macho *mo)
{
struct nlist_64 *pn;
for_each_elem(mo->symtab, 0, pn, struct nlist_64)
convert_symbol(S, mo, pn);
convert_symbol(s1, mo, pn);
}
static int machosymcmp(const void *_a, const void *_b, TCCState *S)
static int machosymcmp(const void *_a, const void *_b)
{
TCCState *s1 = tcc_state;
int ea = ((struct nlist_64 *)_a)->n_value;
int eb = ((struct nlist_64 *)_b)->n_value;
ElfSym *sa = (ElfSym *)symtab_section->data + ea;
@ -491,33 +492,33 @@ static int machosymcmp(const void *_a, const void *_b, TCCState *S)
return ea - eb;
}
static void create_symtab(TCCState *S, struct macho *mo)
static void create_symtab(TCCState *s1, struct macho *mo)
{
int sym_index, sym_end;
struct nlist_64 *pn;
/* Stub creation belongs to check_relocs, but we need to create
the symbol now, so its included in the sorting. */
mo->stubs = new_section(S, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
mo->stubsym = put_elf_sym(S, S->symtab, 0, 0,
mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
mo->stubsym = put_elf_sym(s1->symtab, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
mo->stubs->sh_num, ".__stubs");
mo->symtab = new_section(S, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
mo->strtab = new_section(S, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
put_elf_str(S, mo->strtab, " "); /* Mach-O starts strtab with a space */
mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
pn = section_ptr_add(S, mo->symtab, sizeof(*pn) * (sym_end - 1));
pn = section_ptr_add(mo->symtab, sizeof(*pn) * (sym_end - 1));
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
const char *name = (char*)symtab_section->link->data + sym->st_name;
pn[sym_index - 1].n_strx = put_elf_str(S, mo->strtab, name);
pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
pn[sym_index - 1].n_value = sym_index;
}
tcc_enter_state(S); /* qsort needs global state */
tcc_qsort_s(pn, sym_end - 1, sizeof(*pn), (tcc_cmpfun)machosymcmp, S);
tcc_exit_state(S);
mo->e2msym = tcc_malloc(S, sym_end * sizeof(*mo->e2msym));
tcc_enter_state(s1); /* qsort needs global state */
qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp);
tcc_exit_state(s1);
mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym));
mo->e2msym[0] = -1;
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
mo->e2msym[pn[sym_index - 1].n_value] = sym_index - 1;
@ -545,7 +546,7 @@ const struct {
/*[sk_linkedit] =*/ { 3, S_REGULAR, NULL },
};
static void collect_sections(TCCState *S, struct macho *mo)
static void collect_sections(TCCState *s1, struct macho *mo)
{
int i, sk, numsec;
uint64_t curaddr, fileofs;
@ -556,49 +557,49 @@ static void collect_sections(TCCState *S, struct macho *mo)
struct dysymtab_command *dysymlc;
char *str;
seg = add_segment(S, mo, "__PAGEZERO");
seg = add_segment(mo, "__PAGEZERO");
seg->vmsize = (uint64_t)1 << 32;
seg = add_segment(S, mo, "__TEXT");
seg = add_segment(mo, "__TEXT");
seg->vmaddr = (uint64_t)1 << 32;
seg->maxprot = 7; // rwx
seg->initprot = 5; // r-x
seg = add_segment(S, mo, "__DATA");
seg = add_segment(mo, "__DATA");
seg->vmaddr = -1;
seg->maxprot = 7; // rwx
seg->initprot = 3; // rw-
seg = add_segment(S, mo, "__LINKEDIT");
seg = add_segment(mo, "__LINKEDIT");
seg->vmaddr = -1;
seg->maxprot = 7; // rwx
seg->initprot = 1; // r--
mo->ep = add_lc(S, mo, LC_MAIN, sizeof(*mo->ep));
mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
mo->ep->entryoff = 4096;
i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
dyldlc = add_lc(S, mo, LC_LOAD_DYLINKER, i);
dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i);
dyldlc->name = sizeof(*dyldlc);
str = (char*)dyldlc + dyldlc->name;
strcpy(str, "/usr/lib/dyld");
symlc = add_lc(S, mo, LC_SYMTAB, sizeof(*symlc));
dysymlc = add_lc(S, mo, LC_DYSYMTAB, sizeof(*dysymlc));
symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
for(i = 0; i < S->nb_loaded_dlls; i++) {
DLLReference *dllref = S->loaded_dlls[i];
for(i = 0; i < s1->nb_loaded_dlls; i++) {
DLLReference *dllref = s1->loaded_dlls[i];
if (dllref->level == 0)
add_dylib(S, mo, dllref->name);
add_dylib(mo, dllref->name);
}
/* dyld requires a writable segment with classic Mach-O, but it ignores
zero-sized segments for this, so force to have some data. */
section_ptr_add(S, data_section, 1);
section_ptr_add(data_section, 1);
memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect));
for (i = S->nb_sections; i-- > 1;) {
for (i = s1->nb_sections; i-- > 1;) {
int type, flags;
s = S->sections[i];
s = s1->sections[i];
type = s->sh_type;
flags = s->sh_flags;
sk = sk_unknown;
@ -613,7 +614,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
case SHT_RELX: sk = sk_discard; break;
case SHT_LINKEDIT: sk = sk_linkedit; break;
case SHT_PROGBITS:
if (s == S->got)
if (s == s1->got)
sk = sk_nl_ptr;
else if (flags & SHF_EXECINSTR)
sk = sk_text;
@ -633,7 +634,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
curaddr += 4096;
seg = NULL;
numsec = 0;
mo->elfsectomacho = tcc_mallocz(S, sizeof(*mo->elfsectomacho) * S->nb_sections);
mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
for (sk = sk_unknown; sk < sk_last; sk++) {
struct section_64 *sec = NULL;
if (seg) {
@ -645,7 +646,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
int si;
seg = get_segment(mo, skinfo[sk].seg);
if (skinfo[sk].name) {
si = add_section(S, mo, &seg, skinfo[sk].name);
si = add_section(mo, &seg, skinfo[sk].name);
numsec++;
mo->lc[mo->seg2lc[skinfo[sk].seg]] = (struct load_command*)seg;
mo->sk_to_sect[sk].machosect = si;
@ -669,7 +670,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
sec->align = al;
al = 1ULL << al;
if (al > 4096)
tcc_warning(S, "alignment > 4096"), sec->align = 12, al = 4096;
tcc_warning("alignment > 4096"), sec->align = 12, al = 4096;
curaddr = (curaddr + al - 1) & -al;
fileofs = (fileofs + al - 1) & -al;
if (sec) {
@ -738,7 +739,7 @@ static void collect_sections(TCCState *S, struct macho *mo)
dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);
}
static void macho_write(TCCState *S, struct macho *mo, FILE *fp)
static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
{
int i, sk;
uint64_t fileofs = 0;
@ -778,7 +779,7 @@ static void macho_write(TCCState *S, struct macho *mo, FILE *fp)
}
}
ST_FUNC int macho_output_file(TCCState *S, const char *filename)
ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
{
int fd, mode, file_type;
FILE *fp;
@ -787,7 +788,7 @@ ST_FUNC int macho_output_file(TCCState *S, const char *filename)
(void)memset(&mo, 0, sizeof(mo));
file_type = S->output_type;
file_type = s1->output_type;
if (file_type == TCC_OUTPUT_OBJ)
mode = 0666;
else
@ -795,36 +796,36 @@ ST_FUNC int macho_output_file(TCCState *S, const char *filename)
unlink(filename);
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
if (fd < 0) {
tcc_error_noabort(S, "could not write '%s: %s'", filename, strerror(errno));
tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
return -1;
}
fp = fdopen(fd, "wb");
if (S->verbose)
if (s1->verbose)
printf("<- %s\n", filename);
tcc_add_runtime(S);
resolve_common_syms(S);
create_symtab(S, &mo);
check_relocs(S, &mo);
ret = check_symbols(S, &mo);
tcc_add_runtime(s1);
resolve_common_syms(s1);
create_symtab(s1, &mo);
check_relocs(s1, &mo);
ret = check_symbols(s1, &mo);
if (!ret) {
collect_sections(S, &mo);
relocate_syms(S, S->symtab, 0);
mo.ep->entryoff = get_sym_addr(S, "main", 1, 1)
collect_sections(s1, &mo);
relocate_syms(s1, s1->symtab, 0);
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
- get_segment(&mo, 1)->vmaddr;
if (S->nb_errors)
if (s1->nb_errors)
goto do_ret;
relocate_sections(S);
convert_symbols(S, &mo);
macho_write(S, &mo, fp);
relocate_sections(s1);
convert_symbols(s1, &mo);
macho_write(s1, &mo, fp);
}
do_ret:
for (i = 0; i < mo.nlc; i++)
tcc_free(S, mo.lc[i]);
tcc_free(S, mo.lc);
tcc_free(S, mo.elfsectomacho);
tcc_free(S, mo.e2msym);
tcc_free(mo.lc[i]);
tcc_free(mo.lc);
tcc_free(mo.elfsectomacho);
tcc_free(mo.e2msym);
fclose(fp);
return ret;
@ -836,13 +837,13 @@ static uint32_t macho_swap32(uint32_t x)
}
#define SWAP(x) (swap ? macho_swap32(x) : (x))
ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
ST_FUNC int macho_add_dllref(TCCState* s1, int lev, const char* soname)
{
/* if the dll is already loaded, do not load it */
DLLReference *dllref;
int i;
for(i = 0; i < S->nb_loaded_dlls; i++) {
dllref = S->loaded_dlls[i];
for(i = 0; i < s1->nb_loaded_dlls; i++) {
dllref = s1->loaded_dlls[i];
if (!strcmp(soname, dllref->name)) {
/* but update level if needed */
if (lev < dllref->level)
@ -850,7 +851,7 @@ ST_FUNC int macho_add_dllref(TCCState* S, int lev, const char* soname)
return -1;
}
}
tcc_add_dllref(S, soname)->level = lev;
tcc_add_dllref(s1, soname)->level = lev;
return 0;
}
@ -912,12 +913,12 @@ the_end:
}
#endif /* TCC_IS_NATIVE */
ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev)
ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
{
char *soname, *data, *pos;
int ret = -1;
pos = data = tcc_load_text(S, fd);
pos = data = tcc_load_text(fd);
if (!tbd_parse_movepast("install-name: ")) goto the_end;
tbd_parse_skipws;
tbd_parse_tramplequote;
@ -925,7 +926,7 @@ ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev)
if (!tbd_parse_movetoany("\n \"'")) goto the_end;
tbd_parse_trample;
ret = 0;
if (macho_add_dllref(S, lev, soname) != 0) goto the_end;
if (macho_add_dllref(s1, lev, soname) != 0) goto the_end;
while(pos) {
char* sym = NULL;
int cont = 1;
@ -941,17 +942,17 @@ ST_FUNC int macho_load_tbd(TCCState* S, int fd, const char* filename, int lev)
tbd_parse_skipws;
if (*pos==0||*pos==']') cont=0;
tbd_parse_trample;
set_elf_sym(S->dynsymtab_section, 0, 0,
set_elf_sym(s1->dynsymtab_section, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
}
}
the_end:
tcc_free(S, data);
tcc_free(data);
return ret;
}
ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
{
unsigned char buf[sizeof(struct mach_header_64)];
void *buf2;
@ -973,7 +974,7 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
return -1;
memcpy(&fh, buf, sizeof(fh));
if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) {
struct fat_arch *fa = load_data(S, fd, sizeof(fh),
struct fat_arch *fa = load_data(fd, sizeof(fh),
fh.nfat_arch * sizeof(*fa));
swap = fh.magic == FAT_CIGAM;
for (i = 0; i < SWAP(fh.nfat_arch); i++)
@ -981,15 +982,15 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
&& SWAP(fa[i].cpusubtype) == 3) /* CPU_SUBTYPE_X86_ALL */
break;
if (i == SWAP(fh.nfat_arch)) {
tcc_free(S, fa);
tcc_free(fa);
return -1;
}
machofs = SWAP(fa[i].offset);
tcc_free(S, fa);
tcc_free(fa);
lseek(fd, machofs, SEEK_SET);
goto again;
} else if (fh.magic == FAT_MAGIC_64 || fh.magic == FAT_CIGAM_64) {
tcc_warning(S, "%s: Mach-O fat 64bit files of type 0x%x not handled",
tcc_warning("%s: Mach-O fat 64bit files of type 0x%x not handled",
filename, fh.magic);
return -1;
}
@ -998,7 +999,7 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
if (mh.magic != MH_MAGIC_64)
return -1;
dprintf("found Mach-O at %d\n", machofs);
buf2 = load_data(S, fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds);
buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds);
for (i = 0, lc = buf2; i < mh.ncmds; i++) {
dprintf("lc %2d: 0x%08x\n", i, lc->cmd);
switch (lc->cmd) {
@ -1006,9 +1007,9 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
{
struct symtab_command *sc = (struct symtab_command*)lc;
nsyms = sc->nsyms;
symtab = load_data(S, fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
strsize = sc->strsize;
strtab = load_data(S, fd, machofs + sc->stroff, strsize);
strtab = load_data(fd, machofs + sc->stroff, strsize);
break;
}
case LC_ID_DYLIB:
@ -1027,11 +1028,11 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
int subfd = open(name, O_RDONLY | O_BINARY);
dprintf(" REEXPORT %s\n", name);
if (subfd < 0)
tcc_warning(S, "can't open %s (reexported from %s)", name, filename);
tcc_warning("can't open %s (reexported from %s)", name, filename);
else {
/* Hopefully the REEXPORTs never form a cycle, we don't check
for that! */
macho_load_dll(S, subfd, name, lev + 1);
macho_load_dll(s1, subfd, name, lev + 1);
close(subfd);
}
break;
@ -1047,11 +1048,11 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
lc = (struct load_command*) ((char*)lc + lc->cmdsize);
}
if (0 != macho_add_dllref(S, lev, soname))
if (0 != macho_add_dllref(s1, lev, soname))
goto the_end;
if (!nsyms || !nextdef)
tcc_warning(S, "%s doesn't export any symbols?", filename);
tcc_warning("%s doesn't export any symbols?", filename);
//dprintf("symbols (all):\n");
dprintf("symbols (exported):\n");
@ -1062,14 +1063,14 @@ ST_FUNC int macho_load_dll(TCCState * S, int fd, const char* filename, int lev)
dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n",
i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value,
strtab + sym->n_strx);
set_elf_sym(S->dynsymtab_section, 0, 0,
set_elf_sym(s1->dynsymtab_section, 0, 0,
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
0, SHN_UNDEF, strtab + sym->n_strx);
}
the_end:
tcc_free(S, strtab);
tcc_free(S, symtab);
tcc_free(S, buf2);
tcc_free(strtab);
tcc_free(symtab);
tcc_free(buf2);
return 0;
}

355
tccpe.c
View File

@ -345,7 +345,7 @@ struct pe_import_info {
};
struct pe_info {
TCCState *S;
TCCState *s1;
Section *reloc;
Section *thunk;
const char *filename;
@ -377,15 +377,15 @@ struct pe_info {
/* --------------------------------------------*/
static const char *pe_export_name(TCCState *S, ElfW(Sym) *sym)
static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
{
const char *name = (char*)symtab_section->link->data + sym->st_name;
if (S->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
return name + 1;
return name;
}
static int pe_find_import(TCCState * S, ElfW(Sym) *sym)
static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
{
char buffer[200];
const char *s, *p;
@ -393,7 +393,7 @@ static int pe_find_import(TCCState * S, ElfW(Sym) *sym)
int a, err = 0;
do {
s = pe_export_name(S, sym);
s = pe_export_name(s1, sym);
a = 0;
if (n) {
/* second try: */
@ -414,7 +414,7 @@ static int pe_find_import(TCCState * S, ElfW(Sym) *sym)
}
s = buffer;
}
sym_index = find_elf_sym(S->dynsymtab_section, s);
sym_index = find_elf_sym(s1->dynsymtab_section, s);
// printf("find (%d) %d %s\n", n, sym_index, s);
if (sym_index
&& ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT
@ -460,7 +460,7 @@ static void pe_align_section(Section *s, int a)
{
int i = s->data_offset & (a-1);
if (i)
section_ptr_add(s->S, s, a - i);
section_ptr_add(s, a - i);
}
static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size)
@ -615,11 +615,11 @@ static int pe_write(struct pe_info *pe)
DWORD file_offset;
struct section_info *si;
IMAGE_SECTION_HEADER *psh;
TCCState *S = pe->S;
TCCState *s1 = pe->s1;
pf.op = fopen(pe->filename, "wb");
if (NULL == pf.op) {
tcc_error_noabort(S, "could not write '%s': %s", pe->filename, strerror(errno));
tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
return -1;
}
@ -630,7 +630,7 @@ static int pe_write(struct pe_info *pe)
file_offset = pe->sizeofheaders;
if (2 == pe->S->verbose)
if (2 == pe->s1->verbose)
printf("-------------------------------"
"\n virt file size section" "\n");
for (i = 0; i < pe->sec_count; ++i) {
@ -643,7 +643,7 @@ static int pe_write(struct pe_info *pe)
size = si->sh_size;
psh = &si->ish;
if (2 == pe->S->verbose)
if (2 == pe->s1->verbose)
printf("%6x %6x %6x %s\n",
(unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
@ -712,11 +712,11 @@ static int pe_write(struct pe_info *pe)
pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
pe_header.opthdr.ImageBase = pe->imagebase;
pe_header.opthdr.Subsystem = pe->subsystem;
if (pe->S->pe_stack_size)
pe_header.opthdr.SizeOfStackReserve = pe->S->pe_stack_size;
if (pe->s1->pe_stack_size)
pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
if (PE_DLL == pe->type)
pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
pe_header.filehdr.Characteristics |= pe->S->pe_characteristics;
pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
pe_fwrite(&pe_header, sizeof pe_header, &pf);
for (i = 0; i < pe->sec_count; ++i)
@ -747,9 +747,9 @@ static int pe_write(struct pe_info *pe)
chmod(pe->filename, 0777);
#endif
if (2 == pe->S->verbose)
if (2 == pe->s1->verbose)
printf("-------------------------------\n");
if (pe->S->verbose)
if (pe->s1->verbose)
printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
return 0;
@ -765,7 +765,7 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
struct import_symbol *s;
ElfW(Sym) *isym;
isym = (ElfW(Sym) *)pe->S->dynsymtab_section->data + sym_index;
isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
dll_index = isym->st_size;
i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
@ -773,17 +773,17 @@ static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
p = pe->imp_info[i];
goto found_dll;
}
p = tcc_mallocz(pe->S, sizeof *p);
p = tcc_mallocz(sizeof *p);
p->dll_index = dll_index;
dynarray_add(pe->S, &pe->imp_info, &pe->imp_count, p);
dynarray_add(&pe->imp_info, &pe->imp_count, p);
found_dll:
i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
if (-1 != i)
return p->symbols[i];
s = tcc_mallocz(pe->S, sizeof *s);
dynarray_add(pe->S, &p->symbols, &p->sym_count, s);
s = tcc_mallocz(sizeof *s);
dynarray_add(&p->symbols, &p->sym_count, s);
s->sym_index = sym_index;
return s;
}
@ -793,9 +793,9 @@ void pe_free_imports(struct pe_info *pe)
int i;
for (i = 0; i < pe->imp_count; ++i) {
struct pe_import_info *p = pe->imp_info[i];
dynarray_reset(pe->S, &p->symbols, &p->sym_count);
dynarray_reset(&p->symbols, &p->sym_count);
}
dynarray_reset(pe->S, &pe->imp_info, &pe->imp_count);
dynarray_reset(&pe->imp_info, &pe->imp_count);
}
/*----------------------------------------------------------------------------*/
@ -804,7 +804,7 @@ static void pe_build_imports(struct pe_info *pe)
int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
int ndlls = pe->imp_count;
TCCState *S = pe->S;
TCCState *s1 = pe->s1;
for (sym_cnt = i = 0; i < ndlls; ++i)
sym_cnt += pe->imp_info[i]->sym_count;
@ -820,7 +820,7 @@ static void pe_build_imports(struct pe_info *pe)
ent_ptr = thk_ptr + pe->iat_size;
pe->imp_offs = dll_ptr + rva_base;
pe->iat_offs = thk_ptr + rva_base;
section_ptr_add(pe->S, pe->thunk, pe->imp_size + 2*pe->iat_size);
section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
for (i = 0; i < pe->imp_count; ++i) {
IMAGE_IMPORT_DESCRIPTOR *hdr;
@ -832,12 +832,12 @@ static void pe_build_imports(struct pe_info *pe)
dllindex = p->dll_index;
if (dllindex)
name = tcc_basename((dllref = pe->S->loaded_dlls[dllindex-1])->name);
name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name);
else
name = "", dllref = NULL;
/* put the dll name into the import header */
v = put_elf_str(pe->S, pe->thunk, name);
v = put_elf_str(pe->thunk, name);
hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
hdr->FirstThunk = thk_ptr + rva_base;
hdr->OriginalFirstThunk = ent_ptr + rva_base;
@ -847,9 +847,9 @@ static void pe_build_imports(struct pe_info *pe)
if (k < n) {
int iat_index = p->symbols[k]->iat_index;
int sym_index = p->symbols[k]->sym_index;
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->S->dynsymtab_section->data + sym_index;
ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
const char *name = (char*)pe->S->dynsymtab_section->link->data + imp_sym->st_name;
const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
int ordinal;
org_sym->st_value = thk_ptr;
@ -875,8 +875,8 @@ static void pe_build_imports(struct pe_info *pe)
v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
} else {
v = pe->thunk->data_offset + rva_base;
section_ptr_add(pe->S, pe->thunk, sizeof(WORD)); /* hint, not used */
put_elf_str(pe->S, pe->thunk, name);
section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
put_elf_str(pe->thunk, name);
}
} else {
@ -915,7 +915,7 @@ static void pe_build_exports(struct pe_info *pe)
IMAGE_EXPORT_DIRECTORY *hdr;
int sym_count, ord;
struct pe_sort_sym **sorted, *p;
TCCState *S = pe->S;
TCCState *s1 = pe->s1;
FILE *op;
char buf[260];
@ -928,12 +928,12 @@ static void pe_build_exports(struct pe_info *pe)
sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
for (sym_index = 1; sym_index < sym_end; ++sym_index) {
sym = (ElfW(Sym)*)symtab_section->data + sym_index;
name = pe_export_name(pe->S, sym);
name = pe_export_name(pe->s1, sym);
if (sym->st_other & ST_PE_EXPORT) {
p = tcc_malloc(pe->S, sizeof *p);
p = tcc_malloc(sizeof *p);
p->index = sym_index;
p->name = name;
dynarray_add(pe->S, &sorted, &sym_count, p);
dynarray_add(&sorted, &sym_count, p);
}
#if 0
if (sym->st_other & ST_PE_EXPORT)
@ -957,7 +957,7 @@ static void pe_build_exports(struct pe_info *pe)
ord_o = name_o + sym_count * sizeof (DWORD);
str_o = ord_o + sym_count * sizeof(WORD);
hdr = section_ptr_add(pe->S, pe->thunk, str_o - base_o);
hdr = section_ptr_add(pe->thunk, str_o - base_o);
hdr->Characteristics = 0;
hdr->Base = 1;
hdr->NumberOfFunctions = sym_count;
@ -966,7 +966,7 @@ static void pe_build_exports(struct pe_info *pe)
hdr->AddressOfNames = name_o + rva_base;
hdr->AddressOfNameOrdinals = ord_o + rva_base;
hdr->Name = str_o + rva_base;
put_elf_str(pe->S, pe->thunk, dllname);
put_elf_str(pe->thunk, dllname);
#if 1
/* automatically write exports to <output-filename>.def */
@ -974,10 +974,10 @@ static void pe_build_exports(struct pe_info *pe)
strcpy(tcc_fileextension(buf), ".def");
op = fopen(buf, "wb");
if (NULL == op) {
tcc_error_noabort(pe->S, "could not create '%s': %s", buf, strerror(errno));
tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
} else {
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
if (pe->S->verbose)
if (pe->s1->verbose)
printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
}
#endif
@ -992,7 +992,7 @@ static void pe_build_exports(struct pe_info *pe)
= pe->thunk->data_offset + rva_base;
*(WORD*)(pe->thunk->data + ord_o)
= ord;
put_elf_str(pe->S, pe->thunk, name);
put_elf_str(pe->thunk, name);
func_o += sizeof (DWORD);
name_o += sizeof (DWORD);
ord_o += sizeof (WORD);
@ -1002,7 +1002,7 @@ static void pe_build_exports(struct pe_info *pe)
pe->exp_offs = base_o + rva_base;
pe->exp_size = pe->thunk->data_offset - base_o;
dynarray_reset(pe->S, &sorted, &sym_count);
dynarray_reset(&sorted, &sym_count);
if (op)
fclose(op);
}
@ -1028,11 +1028,11 @@ static void pe_build_reloc (struct pe_info *pe)
continue;
if (count == 0) { /* new block */
block_ptr = pe->reloc->data_offset;
section_ptr_add(pe->S, pe->reloc, sizeof(struct pe_reloc_header));
section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
offset = addr & 0xFFFFFFFF<<12;
}
if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
WORD *wp = section_ptr_add(pe->S, pe->reloc, sizeof (WORD));
WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
*wp = addr | PE_IMAGE_REL<<12;
++count;
continue;
@ -1058,7 +1058,7 @@ static void pe_build_reloc (struct pe_info *pe)
/* fill the last block and ready for a new one */
if (count & 1) /* align for DWORDS */
section_ptr_add(pe->S, pe->reloc, sizeof(WORD)), ++count;
section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
hdr -> offset = offset - pe->imagebase;
hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
@ -1110,16 +1110,16 @@ static int pe_assign_addresses (struct pe_info *pe)
int *section_order;
struct section_info *si;
Section *s;
TCCState *S = pe->S;
TCCState *s1 = pe->s1;
if (PE_DLL == pe->type)
pe->reloc = new_section(pe->S, ".reloc", SHT_PROGBITS, 0);
// pe->thunk = new_section(pe->S, ".iedat", SHT_PROGBITS, SHF_ALLOC);
pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
// pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
section_order = tcc_malloc(pe->S, pe->S->nb_sections * sizeof (int));
section_order = tcc_malloc(pe->s1->nb_sections * sizeof (int));
for (o = k = 0 ; k < sec_last; ++k) {
for (i = 1; i < S->nb_sections; ++i) {
s = S->sections[i];
for (i = 1; i < s1->nb_sections; ++i) {
s = s1->sections[i];
if (k == pe_section_class(s))
section_order[o++] = i;
}
@ -1130,10 +1130,10 @@ static int pe_assign_addresses (struct pe_info *pe)
for (i = 0; i < o; ++i) {
k = section_order[i];
s = S->sections[k];
s = s1->sections[k];
c = pe_section_class(s);
if ((c == sec_stab || c == sec_stabstr) && 0 == S->do_debug)
if ((c == sec_stab || c == sec_stabstr) && 0 == s1->do_debug)
continue;
if (PE_MERGE_DATA && c == sec_bss)
@ -1164,8 +1164,8 @@ static int pe_assign_addresses (struct pe_info *pe)
if (si)
goto add_section;
si = tcc_mallocz(pe->S, sizeof *si);
dynarray_add(pe->S, &pe->sec_info, &pe->sec_count, si);
si = tcc_mallocz(sizeof *si);
dynarray_add(&pe->sec_info, &pe->sec_count, si);
strcpy(si->name, s->name);
si->cls = c;
@ -1195,10 +1195,10 @@ add_section:
}
//printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name);
}
tcc_free(pe->S, section_order);
tcc_free(section_order);
#if 0
for (i = 1; i < S->nb_sections; ++i) {
Section *s = S->sections[i];
for (i = 1; i < s1->nb_sections; ++i) {
Section *s = s1->sections[i];
int type = s->sh_type;
int flags = s->sh_flags;
printf("section %-16s %-10s %08x %04x %s,%s,%s\n",
@ -1215,14 +1215,14 @@ add_section:
flags & SHF_EXECINSTR ? "exec" : ""
);
}
S->verbose = 2;
s1->verbose = 2;
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
static int pe_isafunc(TCCState *S, int sym_index)
static int pe_isafunc(TCCState *s1, int sym_index)
{
Section *sr = text_section->reloc;
ElfW_Rel *rel, *rel_end;
@ -1250,7 +1250,7 @@ static int pe_check_symbols(struct pe_info *pe)
ElfW(Sym) *sym;
int sym_index, sym_end;
int ret = 0;
TCCState *S = pe->S;
TCCState *s1 = pe->s1;
pe_align_section(text_section, 8);
@ -1262,7 +1262,7 @@ static int pe_check_symbols(struct pe_info *pe)
const char *name = (char*)symtab_section->link->data + sym->st_name;
unsigned type = ELFW(ST_TYPE)(sym->st_info);
int imp_sym = pe_find_import(pe->S, sym);
int imp_sym = pe_find_import(pe->s1, sym);
struct import_symbol *is;
if (imp_sym <= 0)
@ -1270,7 +1270,7 @@ static int pe_check_symbols(struct pe_info *pe)
if (type == STT_NOTYPE) {
/* symbols from assembler have no type, find out which */
if (pe_isafunc(S, sym_index))
if (pe_isafunc(s1, sym_index))
type = STT_FUNC;
else
type = STT_OBJECT;
@ -1289,7 +1289,7 @@ static int pe_check_symbols(struct pe_info *pe)
/* add a helper symbol, will be patched later in
pe_build_imports */
sprintf(buffer, "IAT.%s", name);
is->iat_index = put_elf_sym(pe->S,
is->iat_index = put_elf_sym(
symtab_section, 0, sizeof(DWORD),
ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
0, SHN_UNDEF, buffer);
@ -1299,13 +1299,13 @@ static int pe_check_symbols(struct pe_info *pe)
/* add the 'jmp IAT[x]' instruction */
#ifdef TCC_TARGET_ARM
p = section_ptr_add(pe->S, text_section, 8+4); // room for code and address
p = section_ptr_add(text_section, 8+4); // room for code and address
write32le(p + 0, 0xE59FC000); // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
write32le(p + 4, 0xE59CF000); // arm code ldr pc, [ip]
put_elf_reloc(symtab_section, text_section,
offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
#else
p = section_ptr_add(pe->S, text_section, 8);
p = section_ptr_add(text_section, 8);
write16le(p, 0x25FF);
#ifdef TCC_TARGET_X86_64
write32le(p + 2, (DWORD)-4);
@ -1336,11 +1336,11 @@ static int pe_check_symbols(struct pe_info *pe)
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
/* STB_WEAK undefined symbols are accepted */
continue;
tcc_error_noabort(pe->S, "undefined symbol '%s'%s", name,
tcc_error_noabort("undefined symbol '%s'%s", name,
imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
ret = -1;
} else if (pe->S->rdynamic
} else if (pe->s1->rdynamic
&& ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
/* if -rdynamic option, then export all non local symbols */
sym->st_other |= ST_PE_EXPORT;
@ -1473,17 +1473,17 @@ static void pe_print_section(FILE * f, Section * s)
fprintf(f, "\n\n");
}
static void pe_print_sections(TCCState *S, const char *fname)
static void pe_print_sections(TCCState *s1, const char *fname)
{
Section *s;
FILE *f;
int i;
f = fopen(fname, "w");
for (i = 1; i < S->nb_sections; ++i) {
s = S->sections[i];
for (i = 1; i < s1->nb_sections; ++i) {
s = s1->sections[i];
pe_print_section(f, s);
}
pe_print_section(f, S->dynsymtab_section);
pe_print_section(f, s1->dynsymtab_section);
fclose(f);
}
#endif
@ -1492,7 +1492,7 @@ static void pe_print_sections(TCCState *S, const char *fname)
/* helper function for load/store to insert one more indirection */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
{
int r2;
if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
@ -1505,14 +1505,14 @@ ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
v2->r = VT_CONST | VT_SYM | VT_LVAL;
v2->sym = sv->sym;
r2 = get_reg(S, RC_INT);
load(S, r2, v2);
r2 = get_reg(RC_INT);
load(r2, v2);
v2->r = r2;
if ((uint32_t)sv->c.i) {
vpushv(S, v2);
vpushi(S, sv->c.i);
gen_opi(S, '+');
*v2 = *S->tccgen_vtop--;
vpushv(v2);
vpushi(sv->c.i);
gen_opi('+');
*v2 = *vtop--;
}
v2->type.t = sv->type.t;
v2->r |= sv->r & VT_LVAL;
@ -1520,10 +1520,10 @@ ST_FUNC SValue *pe_getimport(TCCState* S, SValue *sv, SValue *v2)
}
#endif
ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t value)
ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
{
return set_elf_sym(
S->dynsymtab_section,
s1->dynsymtab_section,
value,
dllindex, /* st_size */
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
@ -1533,14 +1533,14 @@ ST_FUNC int pe_putimport(TCCState *S, int dllindex, const char *name, addr_t val
);
}
static int pe_add_dllref(TCCState *S, const char *dllname)
static int pe_add_dllref(TCCState *s1, const char *dllname)
{
int i;
for (i = 0; i < S->nb_loaded_dlls; ++i)
if (0 == strcmp(S->loaded_dlls[i]->name, dllname))
for (i = 0; i < s1->nb_loaded_dlls; ++i)
if (0 == strcmp(s1->loaded_dlls[i]->name, dllname))
return i + 1;
tcc_add_dllref(S, dllname);
return S->nb_loaded_dlls;
tcc_add_dllref(s1, dllname);
return s1->nb_loaded_dlls;
}
static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
@ -1551,7 +1551,7 @@ static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
/* ------------------------------------------------------------- */
static int get_dllexports(TCCState* S, int fd, char **pp)
static int get_dllexports(int fd, char **pp)
{
int l, i, n, n0, ret;
char *p;
@ -1618,9 +1618,9 @@ found:
namep += sizeof ptr;
for (l = 0;;) {
if (n+1 >= n0)
p = tcc_realloc(S, p, n0 = n0 ? n0 * 2 : 256);
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
tcc_free(S, p), p = NULL;
tcc_free(p), p = NULL;
goto the_end;
}
if (p[n++] == 0)
@ -1641,7 +1641,7 @@ the_end:
* as generated by 'windres.exe -O coff ...'.
*/
static int pe_load_res(TCCState *S, int fd)
static int pe_load_res(TCCState *s1, int fd)
{
struct pe_rsrc_header hdr;
Section *rsrc_section;
@ -1657,13 +1657,13 @@ static int pe_load_res(TCCState *S, int fd)
|| strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
goto quit;
rsrc_section = new_section(S, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
ptr = section_ptr_add(S, rsrc_section, hdr.sectionhdr.SizeOfRawData);
rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
offs = hdr.sectionhdr.PointerToRawData;
if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
goto quit;
offs = hdr.sectionhdr.PointerToRelocations;
sym_index = put_elf_sym(S, symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
struct pe_rsrc_reloc rel;
if (!read_mem(fd, offs, &rel, sizeof rel))
@ -1709,12 +1709,12 @@ static char *get_token(char **s, char *f)
return p;
}
static int pe_load_def(TCCState *S, int fd)
static int pe_load_def(TCCState *s1, int fd)
{
int state = 0, ret = -1, dllindex = 0, ord;
char dllname[80], *buf, *line, *p, *x, next;
buf = tcc_load_text(S, fd);
buf = tcc_load_text(fd);
for (line = buf;; ++line) {
p = get_token(&line, &next);
if (!(*p && *p != ';'))
@ -1732,7 +1732,7 @@ static int pe_load_def(TCCState *S, int fd)
++state;
break;
case 2:
dllindex = pe_add_dllref(S, dllname);
dllindex = pe_add_dllref(s1, dllname);
++state;
/* fall through */
default:
@ -1743,7 +1743,7 @@ static int pe_load_def(TCCState *S, int fd)
ord = (int)strtol(x + 1, &x, 10);
}
//printf("token %s ; %s : %d\n", dllname, p, ord);
pe_putimport(S, dllindex, p, ord);
pe_putimport(s1, dllindex, p, ord);
break;
}
skip:
@ -1754,63 +1754,63 @@ skip:
}
ret = 0;
quit:
tcc_free(S, buf);
tcc_free(buf);
return ret;
}
/* ------------------------------------------------------------- */
static int pe_load_dll(TCCState *S, int fd, const char *filename)
static int pe_load_dll(TCCState *s1, int fd, const char *filename)
{
char *p, *q;
int index, ret;
ret = get_dllexports(S, fd, &p);
ret = get_dllexports(fd, &p);
if (ret) {
return -1;
} else if (p) {
index = pe_add_dllref(S, filename);
index = pe_add_dllref(s1, filename);
for (q = p; *q; q += 1 + strlen(q))
pe_putimport(S, index, q, 0);
tcc_free(S, p);
pe_putimport(s1, index, q, 0);
tcc_free(p);
}
return 0;
}
ST_FUNC int pe_load_file(TCCState *S, int fd, const char *filename)
ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename)
{
int ret = -1;
char buf[10];
if (0 == strcmp(tcc_fileextension(filename), ".def"))
ret = pe_load_def(S, fd);
else if (pe_load_res(S, fd) == 0)
ret = pe_load_def(s1, fd);
else if (pe_load_res(s1, fd) == 0)
ret = 0;
else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
ret = pe_load_dll(S, fd, filename);
ret = pe_load_dll(s1, fd, filename);
return ret;
}
PUB_FUNC int tcc_get_dllexports(TCCState *S, const char *filename, char **pp)
PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
{
int ret, fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
ret = get_dllexports(S, fd, pp);
ret = get_dllexports(fd, pp);
close(fd);
return ret;
}
/* ------------------------------------------------------------- */
#ifdef TCC_TARGET_X86_64
static unsigned pe_add_uwwind_info(TCCState *S)
static unsigned pe_add_uwwind_info(TCCState *s1)
{
if (NULL == S->uw_pdata) {
S->uw_pdata = find_section(S, ".pdata");
S->uw_pdata->sh_addralign = 4;
if (NULL == s1->uw_pdata) {
s1->uw_pdata = find_section(s1, ".pdata");
s1->uw_pdata->sh_addralign = 4;
}
if (0 == S->uw_sym)
S->uw_sym = put_elf_sym(S, symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
if (0 == S->uw_offs) {
if (0 == s1->uw_sym)
s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
if (0 == s1->uw_offs) {
/* As our functions all have the same stackframe, we use one entry for all */
static const unsigned char uw_info[] = {
0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
@ -1826,17 +1826,18 @@ static unsigned pe_add_uwwind_info(TCCState *S)
Section *s = text_section;
unsigned char *p;
section_ptr_add(S, s, -s->data_offset & 3); /* align */
S->uw_offs = s->data_offset;
p = section_ptr_add(S, s, sizeof uw_info);
section_ptr_add(s, -s->data_offset & 3); /* align */
s1->uw_offs = s->data_offset;
p = section_ptr_add(s, sizeof uw_info);
memcpy(p, uw_info, sizeof uw_info);
}
return S->uw_offs;
return s1->uw_offs;
}
ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsigned stack)
ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
{
TCCState *s1 = tcc_state;
Section *pd;
unsigned o, n, d;
struct /* _RUNTIME_FUNCTION */ {
@ -1845,10 +1846,10 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
DWORD UnwindData;
} *p;
d = pe_add_uwwind_info(S);
pd = S->uw_pdata;
d = pe_add_uwwind_info(s1);
pd = s1->uw_pdata;
o = pd->data_offset;
p = section_ptr_add(S, pd, sizeof *p);
p = section_ptr_add(pd, sizeof *p);
/* record this function */
p->BeginAddress = start;
@ -1857,7 +1858,7 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
/* put relocations on it */
for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, S->uw_sym);
put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
}
#endif
/* ------------------------------------------------------------- */
@ -1867,18 +1868,18 @@ ST_FUNC void pe_add_unwind_data(TCCState *S, unsigned start, unsigned end, unsig
#define PE_STDSYM(n,s) "_" n s
#endif
static void tcc_add_support(TCCState *S, const char *filename)
static void tcc_add_support(TCCState *s1, const char *filename)
{
if (tcc_add_dll(S, filename, 0) < 0)
tcc_error_noabort(S, "%s not found", filename);
if (tcc_add_dll(s1, filename, 0) < 0)
tcc_error_noabort("%s not found", filename);
}
static void pe_add_runtime(TCCState *S, struct pe_info *pe)
static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
{
const char *start_symbol;
int pe_type;
if (TCC_OUTPUT_DLL == S->output_type) {
if (TCC_OUTPUT_DLL == s1->output_type) {
pe_type = PE_DLL;
start_symbol = PE_STDSYM("__dllstart","@12");
} else {
@ -1901,61 +1902,61 @@ static void pe_add_runtime(TCCState *S, struct pe_info *pe)
pe_type = PE_EXE;
}
if (TCC_OUTPUT_MEMORY == S->output_type)
if (TCC_OUTPUT_MEMORY == s1->output_type)
start_symbol = run_symbol;
}
pe->start_symbol = start_symbol + 1;
if (!S->leading_underscore || strchr(start_symbol, '@'))
if (!s1->leading_underscore || strchr(start_symbol, '@'))
++start_symbol;
#ifdef CONFIG_TCC_BACKTRACE
if (S->do_backtrace) {
if (s1->do_backtrace) {
#ifdef CONFIG_TCC_BCHECK
if (S->do_bounds_check && S->output_type != TCC_OUTPUT_DLL)
tcc_add_support(S, "bcheck.o");
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(s1, "bcheck.o");
#endif
if (S->output_type == TCC_OUTPUT_EXE)
tcc_add_support(S, "bt-exe.o");
if (S->output_type == TCC_OUTPUT_DLL)
tcc_add_support(S, "bt-dll.o");
if (S->output_type != TCC_OUTPUT_DLL)
tcc_add_support(S, "bt-log.o");
if (S->output_type != TCC_OUTPUT_MEMORY)
tcc_add_btstub(S);
if (s1->output_type == TCC_OUTPUT_EXE)
tcc_add_support(s1, "bt-exe.o");
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_add_support(s1, "bt-dll.o");
if (s1->output_type != TCC_OUTPUT_DLL)
tcc_add_support(s1, "bt-log.o");
if (s1->output_type != TCC_OUTPUT_MEMORY)
tcc_add_btstub(s1);
}
#endif
/* grab the startup code from libtcc1.a */
#ifdef TCC_IS_NATIVE
if (TCC_OUTPUT_MEMORY != S->output_type || S->runtime_main)
if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
#endif
set_global_sym(S, start_symbol, NULL, 0);
set_global_sym(s1, start_symbol, NULL, 0);
if (0 == S->nostdlib) {
if (0 == s1->nostdlib) {
static const char * const libs[] = {
"msvcrt", "kernel32", "", "user32", "gdi32", NULL
};
const char * const *pp, *p;
if (TCC_LIBTCC1[0])
tcc_add_support(S, TCC_LIBTCC1);
tcc_add_support(s1, TCC_LIBTCC1);
for (pp = libs; 0 != (p = *pp); ++pp) {
if (*p)
tcc_add_library_err(S, p);
tcc_add_library_err(s1, p);
else if (PE_DLL != pe_type && PE_GUI != pe_type)
break;
}
}
/* need this for 'tccelf.c:relocate_sections()' */
if (TCC_OUTPUT_DLL == S->output_type)
S->output_type = TCC_OUTPUT_EXE;
if (TCC_OUTPUT_MEMORY == S->output_type)
if (TCC_OUTPUT_DLL == s1->output_type)
s1->output_type = TCC_OUTPUT_EXE;
if (TCC_OUTPUT_MEMORY == s1->output_type)
pe_type = PE_RUN;
pe->type = pe_type;
}
static void pe_set_options(TCCState * S, struct pe_info *pe)
static void pe_set_options(TCCState * s1, struct pe_info *pe)
{
if (PE_DLL == pe->type) {
/* XXX: check if is correct for arm-pe target */
@ -1978,8 +1979,8 @@ static void pe_set_options(TCCState * S, struct pe_info *pe)
pe->subsystem = 3;
#endif
/* Allow override via -Wl,-subsystem=... option */
if (S->pe_subsystem != 0)
pe->subsystem = S->pe_subsystem;
if (s1->pe_subsystem != 0)
pe->subsystem = s1->pe_subsystem;
/* set default file/section alignment */
if (pe->subsystem == 1) {
@ -1990,58 +1991,58 @@ static void pe_set_options(TCCState * S, struct pe_info *pe)
pe->file_align = 0x200;
}
if (S->section_align != 0)
pe->section_align = S->section_align;
if (S->pe_file_align != 0)
pe->file_align = S->pe_file_align;
if (s1->section_align != 0)
pe->section_align = s1->section_align;
if (s1->pe_file_align != 0)
pe->file_align = s1->pe_file_align;
if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
pe->imagebase = 0;
if (S->has_text_addr)
pe->imagebase = S->text_addr;
if (s1->has_text_addr)
pe->imagebase = s1->text_addr;
}
ST_FUNC int pe_output_file(TCCState *S, const char *filename)
ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
{
int ret;
struct pe_info pe;
memset(&pe, 0, sizeof pe);
pe.filename = filename;
pe.S = S;
S->filetype = 0;
pe.s1 = s1;
s1->filetype = 0;
#ifdef CONFIG_TCC_BCHECK
tcc_add_bcheck(S);
tcc_add_bcheck(s1);
#endif
tcc_add_pragma_libs(S);
pe_add_runtime(S, &pe);
resolve_common_syms(S);
pe_set_options(S, &pe);
tcc_add_pragma_libs(s1);
pe_add_runtime(s1, &pe);
resolve_common_syms(s1);
pe_set_options(s1, &pe);
ret = pe_check_symbols(&pe);
if (ret)
;
else if (filename) {
pe_assign_addresses(&pe);
relocate_syms(S, S->symtab, 0);
S->pe_imagebase = pe.imagebase;
relocate_sections(S);
relocate_syms(s1, s1->symtab, 0);
s1->pe_imagebase = pe.imagebase;
relocate_sections(s1);
pe.start_addr = (DWORD)
(get_sym_addr(S, pe.start_symbol, 1, 1) - pe.imagebase);
if (S->nb_errors)
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
if (s1->nb_errors)
ret = -1;
else
ret = pe_write(&pe);
dynarray_reset(S, &pe.sec_info, &pe.sec_count);
dynarray_reset(&pe.sec_info, &pe.sec_count);
} else {
#ifdef TCC_IS_NATIVE
pe.thunk = data_section;
pe_build_imports(&pe);
S->runtime_main = pe.start_symbol;
s1->runtime_main = pe.start_symbol;
#ifdef TCC_TARGET_X86_64
S->uw_pdata = find_section(S, ".pdata");
s1->uw_pdata = find_section(s1, ".pdata");
#endif
#endif
}
@ -2049,8 +2050,8 @@ ST_FUNC int pe_output_file(TCCState *S, const char *filename)
pe_free_imports(&pe);
#if PE_PRINT_SECTIONS
if (S->g_debug & 8)
pe_print_sections(S, "tcc.log");
if (s1->g_debug & 8)
pe_print_sections(s1, "tcc.log");
#endif
return ret;
}

2167
tccpp.c

File diff suppressed because it is too large Load Diff

View File

@ -1,261 +0,0 @@
/* Copyright (C) 2011 by Valentin Ochs
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/* Minor changes by Rich Felker for integration in musl, 2011-04-27. */
/* Smoothsort, an adaptive variant of Heapsort. Memory usage: O(1).
Run time: Worst case O(n log n), close to O(n) in the mostly-sorted case. */
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
//#include "atomic.h"
#ifndef a_ctz_32
#define a_ctz_32 a_ctz_32
static inline int a_ctz_32(uint32_t x)
{
#ifdef a_clz_32
return 31-a_clz_32(x&-x);
#else
static const char debruijn32[32] = {
0, 1, 23, 2, 29, 24, 19, 3, 30, 27, 25, 11, 20, 8, 4, 13,
31, 22, 28, 18, 26, 10, 7, 12, 21, 17, 9, 6, 16, 5, 15, 14
};
return debruijn32[(x&-x)*0x076be629 >> 27];
#endif
}
#endif
#ifndef a_ctz_64
#define a_ctz_64 a_ctz_64
static inline int a_ctz_64(uint64_t x)
{
static const char debruijn64[64] = {
0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
};
if (sizeof(long) < 8) {
uint32_t y = x;
if (!y) {
y = x>>32;
return 32 + a_ctz_32(y);
}
return a_ctz_32(y);
}
return debruijn64[(x&-x)*0x022fdd63cc95386dull >> 58];
}
#endif
static inline int a_ctz_l(unsigned long x)
{
return (sizeof(long) < 8) ? a_ctz_32(x) : a_ctz_64(x);
}
#define ntz(x) a_ctz_l((x))
typedef int (*tcc_cmpfun)(const void *, const void *, void *);
static inline int pntz(size_t p[2]) {
int r = ntz(p[0] - 1);
if(r != 0 || (r = 8*sizeof(size_t) + ntz(p[1])) != 8*sizeof(size_t)) {
return r;
}
return 0;
}
static void cycle(size_t width, unsigned char* ar[], int n)
{
unsigned char tmp[256];
size_t l;
int i;
if(n < 2) {
return;
}
ar[n] = tmp;
while(width) {
l = sizeof(tmp) < width ? sizeof(tmp) : width;
memcpy(ar[n], ar[0], l);
for(i = 0; i < n; i++) {
memcpy(ar[i], ar[i + 1], l);
ar[i] += l;
}
width -= l;
}
}
/* shl() and shr() need n > 0 */
static inline void shl(size_t p[2], int n)
{
if(n >= 8 * sizeof(size_t)) {
n -= 8 * sizeof(size_t);
p[1] = p[0];
p[0] = 0;
}
p[1] <<= n;
p[1] |= p[0] >> (sizeof(size_t) * 8 - n);
p[0] <<= n;
}
static inline void shr(size_t p[2], int n)
{
if(n >= 8 * sizeof(size_t)) {
n -= 8 * sizeof(size_t);
p[0] = p[1];
p[1] = 0;
}
p[0] >>= n;
p[0] |= p[1] << (sizeof(size_t) * 8 - n);
p[1] >>= n;
}
static void sift(unsigned char *head, size_t width, tcc_cmpfun cmp, int pshift, size_t lp[], void* ctx)
{
unsigned char *rt, *lf;
unsigned char *ar[14 * sizeof(size_t) + 1];
int i = 1;
ar[0] = head;
while(pshift > 1) {
rt = head - width;
lf = head - width - lp[pshift - 2];
if((*cmp)(ar[0], lf, ctx) >= 0 && (*cmp)(ar[0], rt, ctx) >= 0) {
break;
}
if((*cmp)(lf, rt, ctx) >= 0) {
ar[i++] = lf;
head = lf;
pshift -= 1;
} else {
ar[i++] = rt;
head = rt;
pshift -= 2;
}
}
cycle(width, ar, i);
}
static void trinkle(unsigned char *head, size_t width, tcc_cmpfun cmp, size_t pp[2], int pshift, int trusty, size_t lp[], void* ctx)
{
unsigned char *stepson,
*rt, *lf;
size_t p[2];
unsigned char *ar[14 * sizeof(size_t) + 1];
int i = 1;
int trail;
p[0] = pp[0];
p[1] = pp[1];
ar[0] = head;
while(p[0] != 1 || p[1] != 0) {
stepson = head - lp[pshift];
if((*cmp)(stepson, ar[0], ctx) <= 0) {
break;
}
if(!trusty && pshift > 1) {
rt = head - width;
lf = head - width - lp[pshift - 2];
if((*cmp)(rt, stepson, ctx) >= 0 || (*cmp)(lf, stepson, ctx) >= 0) {
break;
}
}
ar[i++] = stepson;
head = stepson;
trail = pntz(p);
shr(p, trail);
pshift += trail;
trusty = 0;
}
if(!trusty) {
cycle(width, ar, i);
sift(head, width, cmp, pshift, lp, ctx);
}
}
LIBTCCAPI void tcc_qsort_s(void *base, size_t nel, size_t width, tcc_cmpfun cmp, void *ctx)
{
size_t lp[12*sizeof(size_t)];
size_t i, size = width * nel;
unsigned char *head, *high;
size_t p[2] = {1, 0};
int pshift = 1;
int trail;
if (!size) return;
head = base;
high = head + size - width;
/* Precompute Leonardo numbers, scaled by element width */
for(lp[0]=lp[1]=width, i=2; (lp[i]=lp[i-2]+lp[i-1]+width) < size; i++);
while(head < high) {
if((p[0] & 3) == 3) {
sift(head, width, cmp, pshift, lp, ctx);
shr(p, 2);
pshift += 2;
} else {
if(lp[pshift - 1] >= high - head) {
trinkle(head, width, cmp, p, pshift, 0, lp, ctx);
} else {
sift(head, width, cmp, pshift, lp, ctx);
}
if(pshift == 1) {
shl(p, 1);
pshift = 0;
} else {
shl(p, pshift - 1);
pshift = 1;
}
}
p[0] |= 1;
head += width;
}
trinkle(head, width, cmp, p, pshift, 0, lp, ctx);
while(pshift != 1 || p[0] != 1 || p[1] != 0) {
if(pshift <= 1) {
trail = pntz(p);
shr(p, trail);
pshift += trail;
} else {
shl(p, 2);
pshift -= 2;
p[0] ^= 7;
shr(p, 1);
trinkle(head - lp[pshift] - width, width, cmp, p, pshift + 1, 1, lp, ctx);
shl(p, 1);
p[0] |= 1;
trinkle(head - width, width, cmp, p, pshift, 1, lp, ctx);
}
head -= width;
}
}

128
tccrun.c
View File

@ -55,11 +55,11 @@ static void rt_exit(int code);
# include <sys/mman.h>
#endif
static void set_pages_executable(TCCState *S, int mode, void *ptr, unsigned long length);
static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff);
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
#ifdef _WIN64
static void *win64_add_function_table(TCCState *S);
static void *win64_add_function_table(TCCState *s1);
static void win64_del_function_table(void *);
#endif
@ -67,15 +67,15 @@ static void win64_del_function_table(void *);
/* Do all relocations (needed before using tcc_get_symbol())
Returns -1 on error. */
LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr)
LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
{
int size;
addr_t ptr_diff = 0;
if (TCC_RELOCATE_AUTO != ptr)
return tcc_relocate_ex(S, ptr, 0);
return tcc_relocate_ex(s1, ptr, 0);
size = tcc_relocate_ex(S, NULL, 0);
size = tcc_relocate_ex(s1, NULL, 0);
if (size < 0)
return -1;
@ -93,52 +93,52 @@ LIBTCCAPI int tcc_relocate(TCCState *S, void *ptr)
/* mmap RX memory at a fixed distance */
prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0);
if (ptr == MAP_FAILED || prx == MAP_FAILED)
tcc_error(S, "tccrun: could not map memory");
tcc_error("tccrun: could not map memory");
ptr_diff = (char*)prx - (char*)ptr;
close(fd);
//printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff);
}
#else
ptr = tcc_malloc(S, size);
ptr = tcc_malloc(size);
#endif
tcc_relocate_ex(S, ptr, ptr_diff); /* no more errors expected */
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, (void*)(addr_t)size);
dynarray_add(S, &S->runtime_mem, &S->nb_runtime_mem, ptr);
tcc_relocate_ex(s1, ptr, ptr_diff); /* no more errors expected */
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
return 0;
}
ST_FUNC void tcc_run_free(TCCState *S)
ST_FUNC void tcc_run_free(TCCState *s1)
{
int i;
for (i = 0; i < S->nb_runtime_mem; i += 2) {
unsigned size = (unsigned)(addr_t)S->runtime_mem[i];
void *ptr = S->runtime_mem[i+1];
for (i = 0; i < s1->nb_runtime_mem; i += 2) {
unsigned size = (unsigned)(addr_t)s1->runtime_mem[i];
void *ptr = s1->runtime_mem[i+1];
#ifdef HAVE_SELINUX
munmap(ptr, size * 2);
#else
/* unprotect memory to make it usable for malloc again */
set_pages_executable(S, 2, ptr, size);
set_pages_executable(s1, 2, ptr, size);
#ifdef _WIN64
win64_del_function_table(*(void**)ptr);
#endif
tcc_free(S, ptr);
tcc_free(ptr);
#endif
}
tcc_free(S, S->runtime_mem);
tcc_free(s1->runtime_mem);
}
static void run_cdtors(TCCState *S, const char *start, const char *end,
static void run_cdtors(TCCState *s1, const char *start, const char *end,
int argc, char **argv, char **envp)
{
void **a = (void **)get_sym_addr(S, start, 0, 0);
void **b = (void **)get_sym_addr(S, end, 0, 0);
void **a = (void **)get_sym_addr(s1, start, 0, 0);
void **b = (void **)get_sym_addr(s1, end, 0, 0);
while (a != b)
((void(*)(int, char **, char **))*a++)(argc, argv, envp);
}
/* launch the compiled program with the given arguments */
LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
{
int (*prog_main)(int, char **, char **), ret;
#ifdef CONFIG_TCC_BACKTRACE
@ -154,20 +154,20 @@ LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
char **envp = environ;
#endif
S->runtime_main = S->nostdlib ? "_start" : "main";
if ((S->dflag & TCC_OPTION_d_t) && (addr_t)-1 == get_sym_addr(S, S->runtime_main, 0, 1))
s1->runtime_main = s1->nostdlib ? "_start" : "main";
if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
return 0;
#ifdef CONFIG_TCC_BACKTRACE
if (S->do_debug)
tcc_add_symbol(S, "exit", rt_exit);
if (s1->do_debug)
tcc_add_symbol(s1, "exit", rt_exit);
#endif
if (tcc_relocate(S, TCC_RELOCATE_AUTO) < 0)
if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
return -1;
prog_main = (void*)get_sym_addr(S, S->runtime_main, 1, 1);
prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
#ifdef CONFIG_TCC_BACKTRACE
memset(rc, 0, sizeof *rc);
if (S->do_debug) {
if (s1->do_debug) {
void *p;
rc->stab_sym = (Stab_Sym *)stab_section->data;
rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
@ -178,15 +178,15 @@ LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
#if PTR_SIZE == 8
rc->prog_base = text_section->sh_addr & 0xffffffff00000000ULL;
#endif
rc->top_func = tcc_get_symbol(S, "main");
rc->num_callers = S->rt_num_callers;
rc->top_func = tcc_get_symbol(s1, "main");
rc->num_callers = s1->rt_num_callers;
rc->do_jmp = 1;
if ((p = tcc_get_symbol(S, "__rt_error")))
if ((p = tcc_get_symbol(s1, "__rt_error")))
*(void**)p = _rt_error;
#ifdef CONFIG_TCC_BCHECK
if (S->do_bounds_check) {
if (s1->do_bounds_check) {
rc->bounds_start = (void*)bounds_section->sh_addr;
if ((p = tcc_get_symbol(S, "__bound_init")))
if ((p = tcc_get_symbol(s1, "__bound_init")))
((void(*)(void*,int))p)(rc->bounds_start, 1);
}
#endif
@ -198,16 +198,16 @@ LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
fflush(stdout);
fflush(stderr);
/* These aren't C symbols, so don't need leading underscore handling. */
run_cdtors(S, "__init_array_start", "__init_array_end", argc, argv, envp);
run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
#ifdef CONFIG_TCC_BACKTRACE
if (!rc->do_jmp || !(ret = setjmp(rc->jmp_buf)))
#endif
{
ret = prog_main(argc, argv, envp);
}
run_cdtors(S, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
if ((S->dflag & TCC_OPTION_d_t) && ret)
fprintf(S->ppfp, "[returns %d]\n", ret), fflush(S->ppfp);
run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
if ((s1->dflag & 16) && ret)
fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
return ret;
}
@ -229,7 +229,7 @@ LIBTCCAPI int tcc_run(TCCState *S, int argc, char **argv)
/* relocate code. Return -1 on error, required size if ptr is NULL,
otherwise copy code into buffer passed by the caller */
static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff)
static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
{
Section *s;
unsigned offset, length, align, max_align, i, k, f;
@ -237,15 +237,15 @@ static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff)
addr_t mem, addr;
if (NULL == ptr) {
S->nb_errors = 0;
s1->nb_errors = 0;
#ifdef TCC_TARGET_PE
pe_output_file(S, NULL);
pe_output_file(s1, NULL);
#else
tcc_add_runtime(S);
resolve_common_syms(S);
build_got_entries(S);
tcc_add_runtime(s1);
resolve_common_syms(s1);
build_got_entries(s1);
#endif
if (S->nb_errors)
if (s1->nb_errors)
return -1;
}
@ -257,11 +257,11 @@ static int tcc_relocate_ex(TCCState *S, void *ptr, addr_t ptr_diff)
redo:
for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
n = 0; addr = 0;
for(i = 1; i < S->nb_sections; i++) {
for(i = 1; i < s1->nb_sections; i++) {
static const char shf[] = {
SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE
};
s = S->sections[i];
s = s1->sections[i];
if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
continue;
length = s->data_offset;
@ -277,11 +277,11 @@ redo:
else
memcpy(ptr, s->data, length);
#ifdef _WIN64
if (s == S->uw_pdata)
*(void**)mem = win64_add_function_table(S);
if (s == s1->uw_pdata)
*(void**)mem = win64_add_function_table(s1);
#endif
if (s->data) {
tcc_free(S, s->data);
tcc_free(s->data);
s->data = NULL;
s->data_allocated = 0;
}
@ -316,7 +316,7 @@ redo:
printf("protect %d %p %04x\n", f, (void*)addr, n);
#endif
if (n)
set_pages_executable(S, f, (void*)addr, n);
set_pages_executable(s1, f, (void*)addr, n);
}
}
@ -324,21 +324,21 @@ redo:
return 0;
/* relocate symbols */
relocate_syms(S, S->symtab, !(S->nostdlib));
if (S->nb_errors)
relocate_syms(s1, s1->symtab, !(s1->nostdlib));
if (s1->nb_errors)
return -1;
if (0 == mem)
return offset + max_align;
#ifdef TCC_TARGET_PE
S->pe_imagebase = mem;
s1->pe_imagebase = mem;
#endif
/* relocate sections */
#ifndef TCC_TARGET_PE
relocate_plt(S);
relocate_plt(s1);
#endif
relocate_sections(S);
relocate_sections(s1);
copy = 1;
goto redo;
}
@ -346,7 +346,7 @@ redo:
/* ------------------------------------------------------------- */
/* allow to run code in memory */
static void set_pages_executable(TCCState *S, int mode, void *ptr, unsigned long length)
static void set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)
{
#ifdef _WIN32
static const unsigned char protect[] = {
@ -369,7 +369,7 @@ static void set_pages_executable(TCCState *S, int mode, void *ptr, unsigned long
end = (addr_t)ptr + length;
end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
if (mprotect((void *)start, end - start, protect[mode]))
tcc_error(S, "mprotect failed: did you mean to configure --with-selinux?");
tcc_error("mprotect failed: did you mean to configure --with-selinux?");
/* XXX: BSD sometimes dump core with bad system call */
# if (TCC_TARGET_ARM && !TARGETOS_BSD) || TCC_TARGET_ARM64
@ -383,17 +383,17 @@ static void set_pages_executable(TCCState *S, int mode, void *ptr, unsigned long
}
#ifdef _WIN64
static void *win64_add_function_table(TCCState *S)
static void *win64_add_function_table(TCCState *s1)
{
void *p = NULL;
if (S->uw_pdata) {
p = (void*)S->uw_pdata->sh_addr;
if (s1->uw_pdata) {
p = (void*)s1->uw_pdata->sh_addr;
RtlAddFunctionTable(
(RUNTIME_FUNCTION*)p,
S->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
S->pe_imagebase
s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
s1->pe_imagebase
);
S->uw_pdata = NULL;
s1->uw_pdata = NULL;
}
return p;
}

View File

@ -66,7 +66,7 @@ static int ar_usage(int ret) {
return ret;
}
ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
{
static const ArHdr arhdr_init = {
"/ ",
@ -135,7 +135,7 @@ ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
}
funcmax = 250;
afpos = tcc_realloc(S, NULL, funcmax * sizeof *afpos); // 250 func
afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
memcpy(&arhdro.ar_mode, "100666", 6);
// i_obj = first input object file
@ -155,7 +155,7 @@ ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
fseek(fi, 0, SEEK_END);
fsize = ftell(fi);
fseek(fi, 0, SEEK_SET);
buf = tcc_malloc(S, fsize + 1);
buf = tcc_malloc(fsize + 1);
fread(buf, fsize, 1, fi);
fclose(fi);
@ -203,12 +203,12 @@ ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
)) {
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
istrlen = strlen(strtab + sym->st_name)+1;
anames = tcc_realloc(S, anames, strpos+istrlen);
anames = tcc_realloc(anames, strpos+istrlen);
strcpy(anames + strpos, strtab + sym->st_name);
strpos += istrlen;
if (++funccnt >= funcmax) {
funcmax += 250;
afpos = tcc_realloc(S, afpos, funcmax * sizeof *afpos); // 250 func more
afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
}
afpos[funccnt] = fpos;
}
@ -229,7 +229,7 @@ ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
memcpy(&arhdro.ar_size, stmp, 10);
fwrite(&arhdro, sizeof(arhdro), 1, fo);
fwrite(buf, fsize, 1, fo);
tcc_free(S, buf);
tcc_free(buf);
i_obj++;
fpos += (fsize + sizeof(arhdro));
}
@ -253,16 +253,16 @@ ST_FUNC int tcc_tool_ar(TCCState *S, int argc, char **argv)
fseek(fo, 0, SEEK_END);
fsize = ftell(fo);
fseek(fo, 0, SEEK_SET);
buf = tcc_malloc(S, fsize + 1);
buf = tcc_malloc(fsize + 1);
fread(buf, fsize, 1, fo);
fwrite(buf, fsize, 1, fh);
tcc_free(S, buf);
tcc_free(buf);
ret = 0;
the_end:
if (anames)
tcc_free(S, anames);
tcc_free(anames);
if (afpos)
tcc_free(S, afpos);
tcc_free(afpos);
if (fh)
fclose(fh);
if (fo)
@ -294,7 +294,7 @@ the_end:
#ifdef TCC_TARGET_PE
ST_FUNC int tcc_tool_impdef(TCCState *S, int argc, char **argv)
ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
{
int ret, v, i;
char infile[260];
@ -353,7 +353,7 @@ usage:
if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
file = path;
#endif
ret = tcc_get_dllexports(S, file, &p);
ret = tcc_get_dllexports(file, &p);
if (ret || !p) {
fprintf(stderr, "tcc: impdef: %s '%s'\n",
ret == -1 ? "can't find file" :
@ -386,7 +386,7 @@ usage:
the_end:
if (p)
tcc_free(S, p);
tcc_free(p);
if (fp)
fclose(fp);
if (op)
@ -421,9 +421,9 @@ the_end:
#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int option)
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int option)
{
tcc_error(S, "-m%d not implemented.", option);
tcc_error("-m%d not implemented.", option);
}
#else
@ -439,7 +439,7 @@ static char *str_replace(const char *str, const char *p, const char *r)
sl = strlen(str);
pl = strlen(p);
rl = strlen(r);
for (d0 = NULL;; d0 = tcc_malloc(S, sl + 1)) {
for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
if (d) {
memcpy(d, s0, sl = s - s0), d += sl;
@ -470,7 +470,7 @@ static int execvp_win32(const char *prog, char **argv)
#define execvp execvp_win32
#endif /* _WIN32 */
ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int target)
ST_FUNC void tcc_tool_cross(TCCState *s1, char **argv, int target)
{
char program[4096];
char *a0 = argv[0];
@ -489,7 +489,7 @@ ST_FUNC void tcc_tool_cross(TCCState *S, char **argv, int target)
if (strcmp(a0, program))
execvp(argv[0] = program, argv);
tcc_error(S, "could not run '%s'", program);
tcc_error("could not run '%s'", program);
}
#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
@ -506,8 +506,8 @@ const int _dowildcard = 1;
/* -------------------------------------------------------------- */
/* generate xxx.d file */
static char *escape_target_dep(TCCState *S, const char *s) {
char *res = tcc_malloc(S, strlen(s) * 2 + 1);
static char *escape_target_dep(const char *s) {
char *res = tcc_malloc(strlen(s) * 2 + 1);
int j;
for (j = 0; *s; s++, j++) {
if (is_space(*s)) {
@ -519,7 +519,7 @@ static char *escape_target_dep(TCCState *S, const char *s) {
return res;
}
ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename)
ST_FUNC void gen_makedeps(TCCState *s1, const char *target, const char *filename)
{
FILE *depout;
char buf[1024], *escaped_target;
@ -532,7 +532,7 @@ ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename)
filename = buf;
}
if (S->verbose)
if (s1->verbose)
printf("<- %s\n", filename);
if(!strcmp(filename, "-"))
@ -541,15 +541,15 @@ ST_FUNC void gen_makedeps(TCCState *S, const char *target, const char *filename)
/* XXX return err codes instead of error() ? */
depout = fopen(filename, "w");
if (!depout)
tcc_error(S, "could not open '%s'", filename);
tcc_error("could not open '%s'", filename);
fprintf(depout, "%s:", target);
for (i = 0; i<S->nb_target_deps; ++i) {
for (i = 0; i<s1->nb_target_deps; ++i) {
for (k = 0; k < i; ++k)
if (0 == strcmp(S->target_deps[i], S->target_deps[k]))
if (0 == strcmp(s1->target_deps[i], s1->target_deps[k]))
goto next;
escaped_target = escape_target_dep(S, S->target_deps[i]);
escaped_target = escape_target_dep(s1->target_deps[i]);
fprintf(depout, " \\\n %s", escaped_target);
tcc_free(S, escaped_target);
tcc_free(escaped_target);
next:;
}
fprintf(depout, "\n");

File diff suppressed because it is too large Load Diff

View File

@ -105,9 +105,9 @@ int gotplt_entry_type (int reloc_type)
}
#if !defined(TCC_TARGET_MACHO) || defined TCC_IS_NATIVE
ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_attr *attr)
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = S->plt;
Section *plt = s1->plt;
uint8_t *p;
int modrm;
unsigned plt_offset, relofs;
@ -118,7 +118,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
(GOT + 2 * PTR_SIZE) */
if (plt->data_offset == 0) {
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* pushl got + PTR_SIZE */
p[1] = modrm + 0x10;
write32le(p + 2, PTR_SIZE);
@ -131,10 +131,10 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* The PLT slot refers to the relocation entry it needs via offset.
The reloc entry is created below, so its offset is the current
data_offset */
relofs = S->plt->reloc ? S->plt->reloc->data_offset : 0;
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
p = section_ptr_add(S, plt, 16);
p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */
p[1] = modrm;
write32le(p + 2, got_offset);
@ -148,32 +148,32 @@ ST_FUNC unsigned create_plt_entry(TCCState *S, unsigned got_offset, struct sym_a
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *S)
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!S->plt)
if (!s1->plt)
return;
p = S->plt->data;
p_end = p + S->plt->data_offset;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
int x = S->got->sh_addr - S->plt->sh_addr - 6;
int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
add32le(p + 2, x);
add32le(p + 8, x - 6);
p += 16;
while (p < p_end) {
add32le(p + 2, x + (S->plt->data - p));
add32le(p + 2, x + (s1->plt->data - p));
p += 16;
}
}
if (S->plt->reloc) {
if (s1->plt->reloc) {
ElfW_Rel *rel;
int x = S->plt->sh_addr + 16 + 6;
p = S->got->data;
for_each_elem(S->plt->reloc, 0, rel, ElfW_Rel) {
int x = s1->plt->sh_addr + 16 + 6;
p = s1->got->data;
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
write64le(p + rel->r_offset, x);
x += 16;
}
@ -182,7 +182,7 @@ ST_FUNC void relocate_plt(TCCState *S)
#endif
#endif
void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
int sym_index, esym_index;
@ -190,8 +190,8 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
switch (type) {
case R_X86_64_64:
if (S->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
@ -208,7 +208,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break;
case R_X86_64_32:
case R_X86_64_32S:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_X86_64_32 even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
@ -221,9 +221,9 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break;
case R_X86_64_PC32:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
@ -243,20 +243,20 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
long long diff;
diff = (long long)val - addr;
if (diff < -2147483648LL || diff > 2147483647LL) {
tcc_error(S, "internal error: relocation failed");
tcc_error("internal error: relocation failed");
}
add32le(ptr, diff);
}
break;
case R_X86_64_PLTOFF64:
add64le(ptr, val - S->got->sh_addr + rel->r_addend);
add64le(ptr, val - s1->got->sh_addr + rel->r_addend);
break;
case R_X86_64_PC64:
if (S->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */
esym_index = get_sym_attr(S, sym_index, 0)->dyn_index;
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
if (esym_index) {
qrel->r_offset = rel->r_offset;
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC64);
@ -276,28 +276,28 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
add32le(ptr, S->got->sh_addr - addr +
get_sym_attr(S, sym_index, 0)->got_offset - 4);
add32le(ptr, s1->got->sh_addr - addr +
get_sym_attr(s1, sym_index, 0)->got_offset - 4);
break;
case R_X86_64_GOTPC32:
add32le(ptr, S->got->sh_addr - addr + rel->r_addend);
add32le(ptr, s1->got->sh_addr - addr + rel->r_addend);
break;
case R_X86_64_GOTPC64:
add64le(ptr, S->got->sh_addr - addr + rel->r_addend);
add64le(ptr, s1->got->sh_addr - addr + rel->r_addend);
break;
case R_X86_64_GOTTPOFF:
add32le(ptr, val - S->got->sh_addr);
add32le(ptr, val - s1->got->sh_addr);
break;
case R_X86_64_GOT32:
/* we load the got offset */
add32le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
break;
case R_X86_64_GOT64:
/* we load the got offset */
add64le(ptr, get_sym_attr(S, sym_index, 0)->got_offset);
add64le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
break;
case R_X86_64_GOTOFF64:
add64le(ptr, val - S->got->sh_addr);
add64le(ptr, val - s1->got->sh_addr);
break;
case R_X86_64_TLSGD:
{
@ -320,12 +320,12 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
memcpy(ptr-4, replace, sizeof(replace));
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx];
sec = s1->sections[sym->st_shndx];
x = sym->st_value - sec->sh_addr - sec->data_offset;
add32le(ptr + 8, x);
}
else
tcc_error(S, "unexpected R_X86_64_TLSGD pattern");
tcc_error("unexpected R_X86_64_TLSGD pattern");
}
break;
case R_X86_64_TLSLD:
@ -345,7 +345,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
}
else
tcc_error(S, "unexpected R_X86_64_TLSLD pattern");
tcc_error("unexpected R_X86_64_TLSLD pattern");
}
break;
case R_X86_64_DTPOFF32:
@ -356,7 +356,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
int32_t x;
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
sec = S->sections[sym->st_shndx];
sec = s1->sections[sym->st_shndx];
x = val - sec->sh_addr - sec->data_offset;
add32le(ptr, x);
}
@ -365,7 +365,7 @@ void relocate(TCCState *S, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t a
break;
case R_X86_64_RELATIVE:
#ifdef TCC_TARGET_PE
add32le(ptr, val - S->pe_imagebase);
add32le(ptr, val - s1->pe_imagebase);
#endif
/* do nothing */
break;