Clean up lots of rogue tabs.

Still some more tabs to be taken care of. arm-gen.c and tcccoff.c
have so many style issues that I'm just going to throw clang-format
at them.
This commit is contained in:
gus knight 2015-07-27 14:14:41 -04:00
parent 41031221c8
commit d6b64e2574
10 changed files with 426 additions and 427 deletions

View file

@ -30,13 +30,13 @@ typedef int RegArgs;
/* a register can belong to several classes. The classes must be /* a register can belong to several classes. The classes must be
sorted from more general to more precise (see gv2() code which does sorted from more general to more precise (see gv2() code which does
assumptions on it). */ assumptions on it). */
#define RC_INT 0x0001 /* generic integer register */ #define RC_INT 0x0001 /* generic integer register */
#define RC_FLOAT 0x0002 /* generic float register */ #define RC_FLOAT 0x0002 /* generic float register */
#define RC_EAX 0x0004 #define RC_EAX 0x0004
#define RC_ST0 0x0008 #define RC_ST0 0x0008
#define RC_ECX 0x0010 #define RC_ECX 0x0010
#define RC_EDX 0x0020 #define RC_EDX 0x0020
#define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */ #define RC_INT_BSIDE 0x00000040 /* generic integer register on b side */
#define RC_C67_A4 0x00000100 #define RC_C67_A4 0x00000100
#define RC_C67_A5 0x00000200 #define RC_C67_A5 0x00000200
#define RC_C67_B4 0x00000400 #define RC_C67_B4 0x00000400
@ -204,7 +204,7 @@ void C67_g(int c)
#endif #endif
ind1 = ind + 4; ind1 = ind + 4;
if (ind1 > (int) cur_text_section->data_allocated) if (ind1 > (int) cur_text_section->data_allocated)
section_realloc(cur_text_section, ind1); section_realloc(cur_text_section, ind1);
cur_text_section->data[ind] = c & 0xff; cur_text_section->data[ind] = c & 0xff;
cur_text_section->data[ind + 1] = (c >> 8) & 0xff; cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
cur_text_section->data[ind + 2] = (c >> 16) & 0xff; cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
@ -218,26 +218,26 @@ void gsym_addr(int t, int a)
{ {
int n, *ptr; int n, *ptr;
while (t) { while (t) {
ptr = (int *) (cur_text_section->data + t); ptr = (int *) (cur_text_section->data + t);
{ {
Sym *sym; Sym *sym;
// extract 32 bit address from MVKH/MVKL // extract 32 bit address from MVKH/MVKL
n = ((*ptr >> 7) & 0xffff); n = ((*ptr >> 7) & 0xffff);
n |= ((*(ptr + 1) >> 7) & 0xffff) << 16; n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
// define a label that will be relocated // define a label that will be relocated
sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0); sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
greloc(cur_text_section, sym, t, R_C60LO16); greloc(cur_text_section, sym, t, R_C60LO16);
greloc(cur_text_section, sym, t + 4, R_C60HI16); greloc(cur_text_section, sym, t + 4, R_C60HI16);
// clear out where the pointer was // clear out where the pointer was
*ptr &= ~(0xffff << 7); *ptr &= ~(0xffff << 7);
*(ptr + 1) &= ~(0xffff << 7); *(ptr + 1) &= ~(0xffff << 7);
} }
t = n; t = n;
} }
} }

2
coff.h
View file

@ -370,7 +370,7 @@ struct syment
#define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF)) #define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF))
#define DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF)) #define DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF))
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/
/* AUXILIARY SYMBOL ENTRY */ /* AUXILIARY SYMBOL ENTRY */
/*------------------------------------------------------------------------*/ /*------------------------------------------------------------------------*/

View file

@ -672,7 +672,7 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
} }
#else #else
if (! (sym->type.t & VT_STATIC)) if (! (sym->type.t & VT_STATIC))
other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT; other = (sym->type.t & VT_VIS_MASK) >> VT_VIS_SHIFT;
#endif #endif
if (tcc_state->leading_underscore && can_add_underscore) { if (tcc_state->leading_underscore && can_add_underscore) {
buf1[0] = '_'; buf1[0] = '_';
@ -2101,11 +2101,11 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
s->static_link = 1; s->static_link = 1;
break; break;
case TCC_OPTION_std: case TCC_OPTION_std:
/* silently ignore, a current purpose: /* silently ignore, a current purpose:
allow to use a tcc as a reference compiler for "make test" */ allow to use a tcc as a reference compiler for "make test" */
break; break;
case TCC_OPTION_shared: case TCC_OPTION_shared:
if (s->output_type) if (s->output_type)
tcc_warning("-shared: some compiler action already specified (%d)", s->output_type); tcc_warning("-shared: some compiler action already specified (%d)", s->output_type);
s->output_type = TCC_OUTPUT_DLL; s->output_type = TCC_OUTPUT_DLL;
break; break;
@ -2124,7 +2124,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
break; break;
case TCC_OPTION_r: case TCC_OPTION_r:
/* generate a .o merging several output files */ /* generate a .o merging several output files */
if (s->output_type) if (s->output_type)
tcc_warning("-r: some compiler action already specified (%d)", s->output_type); tcc_warning("-r: some compiler action already specified (%d)", s->output_type);
s->option_r = 1; s->option_r = 1;
s->output_type = TCC_OUTPUT_OBJ; s->output_type = TCC_OUTPUT_OBJ;
@ -2163,7 +2163,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
s->print_search_dirs = 1; s->print_search_dirs = 1;
break; break;
case TCC_OPTION_run: case TCC_OPTION_run:
if (s->output_type) if (s->output_type)
tcc_warning("-run: some compiler action already specified (%d)", s->output_type); tcc_warning("-run: some compiler action already specified (%d)", s->output_type);
s->output_type = TCC_OUTPUT_MEMORY; s->output_type = TCC_OUTPUT_MEMORY;
tcc_set_options(s, optarg); tcc_set_options(s, optarg);
@ -2194,7 +2194,7 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
cstr_ccat(&linker_arg, '\0'); cstr_ccat(&linker_arg, '\0');
break; break;
case TCC_OPTION_E: case TCC_OPTION_E:
if (s->output_type) if (s->output_type)
tcc_warning("-E: some compiler action already specified (%d)", s->output_type); tcc_warning("-E: some compiler action already specified (%d)", s->output_type);
s->output_type = TCC_OUTPUT_PREPROCESS; s->output_type = TCC_OUTPUT_PREPROCESS;
break; break;
@ -2251,13 +2251,13 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
} }
if (s->output_type == 0) if (s->output_type == 0)
s->output_type = TCC_OUTPUT_EXE; s->output_type = TCC_OUTPUT_EXE;
if (pthread && s->output_type != TCC_OUTPUT_OBJ) if (pthread && s->output_type != TCC_OUTPUT_OBJ)
tcc_set_options(s, "-lpthread"); tcc_set_options(s, "-lpthread");
if (s->output_type == TCC_OUTPUT_EXE) if (s->output_type == TCC_OUTPUT_EXE)
tcc_set_linker(s, (const char *)linker_arg.data); tcc_set_linker(s, (const char *)linker_arg.data);
cstr_free(&linker_arg); cstr_free(&linker_arg);
return optind; return optind;

View file

@ -92,10 +92,10 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
break; break;
case TOK_CCHAR: case TOK_CCHAR:
case TOK_LCHAR: case TOK_LCHAR:
pe->v = tokc.i; pe->v = tokc.i;
pe->sym = NULL; pe->sym = NULL;
next(); next();
break; break;
case '(': case '(':
next(); next();
asm_expr(s1, pe); asm_expr(s1, pe);
@ -493,7 +493,7 @@ static void asm_parse_directive(TCCState *s1)
case TOK_ASM_weak: case TOK_ASM_weak:
case TOK_ASM_hidden: case TOK_ASM_hidden:
tok1 = tok; tok1 = tok;
do { do {
Sym *sym; Sym *sym;
next(); next();
@ -502,15 +502,15 @@ static void asm_parse_directive(TCCState *s1)
sym = label_push(&s1->asm_labels, tok, 0); sym = label_push(&s1->asm_labels, tok, 0);
sym->type.t = VT_VOID; sym->type.t = VT_VOID;
} }
if (tok1 != TOK_ASM_hidden) if (tok1 != TOK_ASM_hidden)
sym->type.t &= ~VT_STATIC; sym->type.t &= ~VT_STATIC;
if (tok1 == TOK_ASM_weak) if (tok1 == TOK_ASM_weak)
sym->type.t |= VT_WEAK; sym->type.t |= VT_WEAK;
else if (tok1 == TOK_ASM_hidden) else if (tok1 == TOK_ASM_hidden)
sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT; sym->type.t |= STV_HIDDEN << VT_VIS_SHIFT;
next(); next();
} while (tok == ','); } while (tok == ',');
break; break;
case TOK_ASM_string: case TOK_ASM_string:
case TOK_ASM_ascii: case TOK_ASM_ascii:
case TOK_ASM_asciz: case TOK_ASM_asciz:
@ -536,24 +536,24 @@ static void asm_parse_directive(TCCState *s1)
break; break;
} }
} }
} }
break; break;
case TOK_ASM_text: case TOK_ASM_text:
case TOK_ASM_data: case TOK_ASM_data:
case TOK_ASM_bss: case TOK_ASM_bss:
{ {
char sname[64]; char sname[64];
tok1 = tok; tok1 = tok;
n = 0; n = 0;
next(); next();
if (tok != ';' && tok != TOK_LINEFEED) { if (tok != ';' && tok != TOK_LINEFEED) {
n = asm_int_expr(s1); n = asm_int_expr(s1);
next(); next();
} }
sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n); sprintf(sname, (n?".%s%d":".%s"), get_tok_str(tok1, NULL), n);
use_section(s1, sname); use_section(s1, sname);
} }
break; break;
case TOK_ASM_file: case TOK_ASM_file:
{ {
char filename[512]; char filename[512];

278
tccelf.c
View file

@ -451,7 +451,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
if (addr) { if (addr) {
sym->st_value = (addr_t)addr; sym->st_value = (addr_t)addr;
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value); printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
#endif #endif
goto found; goto found;
} }
@ -580,10 +580,10 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
{ {
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko; int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
x = (*(int *) ptr) & 0xffffff; x = (*(int *) ptr) & 0xffffff;
if (sym->st_shndx == SHN_UNDEF) if (sym->st_shndx == SHN_UNDEF)
val = s1->plt->sh_addr; val = s1->plt->sh_addr;
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val); printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
#endif #endif
(*(int *)ptr) &= 0xff000000; (*(int *)ptr) &= 0xff000000;
if (x & 0x800000) if (x & 0x800000)
@ -595,8 +595,8 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl)); is_call = (type == R_ARM_CALL || (type == R_ARM_PC24 && is_bl));
x += val - addr; x += val - addr;
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf (" newx=0x%x name=%s\n", x, printf (" newx=0x%x name=%s\n", x,
(char *) symtab_section->link->data + sym->st_name); (char *) symtab_section->link->data + sym->st_name);
#endif #endif
h = x & 2; h = x & 2;
th_ko = (x & 3) && (!blx_avail || !is_call); th_ko = (x & 3) && (!blx_avail || !is_call);
@ -797,21 +797,21 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
break; break;
case R_AARCH64_JUMP26: case R_AARCH64_JUMP26:
case R_AARCH64_CALL26: case R_AARCH64_CALL26:
/* This check must match the one in build_got_entries, testing /* This check must match the one in build_got_entries, testing
if we really need a PLT slot. */ if we really need a PLT slot. */
if (sym->st_shndx == SHN_UNDEF) if (sym->st_shndx == SHN_UNDEF)
/* We've put the PLT slot offset into r_addend when generating /* We've put the PLT slot offset into r_addend when generating
it, and that's what we must use as relocation value (adjusted it, and that's what we must use as relocation value (adjusted
by section offset of course). */ by section offset of course). */
val = s1->plt->sh_addr + rel->r_addend; val = s1->plt->sh_addr + rel->r_addend;
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val, printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, val,
(char *) symtab_section->link->data + sym->st_name); (char *) symtab_section->link->data + sym->st_name);
#endif #endif
if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc) if (((val - addr) + ((uint64_t)1 << 27)) & ~(uint64_t)0xffffffc)
{ {
tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val); tcc_error("R_AARCH64_(JUMP|CALL)26 relocation failed (val=%lx, addr=%lx)", addr, val);
} }
*(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 | *(uint32_t *)ptr = 0x14000000 | (type == R_AARCH64_CALL26) << 31 |
((val - addr) >> 2 & 0x3ffffff); ((val - addr) >> 2 & 0x3ffffff);
break; break;
@ -836,9 +836,9 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
case R_AARCH64_JUMP_SLOT: case R_AARCH64_JUMP_SLOT:
/* They don't need addend */ /* They don't need addend */
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr, printf ("reloc %d @ 0x%lx: val=0x%lx name=%s\n", type, addr,
val - rel->r_addend, val - rel->r_addend,
(char *) symtab_section->link->data + sym->st_name); (char *) symtab_section->link->data + sym->st_name);
#endif #endif
*(addr_t *)ptr = val - rel->r_addend; *(addr_t *)ptr = val - rel->r_addend;
break; break;
@ -879,12 +879,12 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
qrel->r_offset = rel->r_offset; qrel->r_offset = rel->r_offset;
if (esym_index) { if (esym_index) {
qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64); qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
qrel->r_addend = rel->r_addend; qrel->r_addend = rel->r_addend;
qrel++; qrel++;
break; break;
} else { } else {
qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE); qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
qrel->r_addend = *(long long *)ptr + val; qrel->r_addend = *(long long *)ptr + val;
qrel++; qrel++;
} }
} }
@ -917,14 +917,14 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
goto plt32pc32; goto plt32pc32;
case R_X86_64_PLT32: case R_X86_64_PLT32:
/* We've put the PLT slot offset into r_addend when generating /* We've put the PLT slot offset into r_addend when generating
it, and that's what we must use as relocation value (adjusted it, and that's what we must use as relocation value (adjusted
by section offset of course). */ by section offset of course). */
val = s1->plt->sh_addr + rel->r_addend; val = s1->plt->sh_addr + rel->r_addend;
/* fallthrough. */ /* fallthrough. */
plt32pc32: plt32pc32:
{ {
long long diff; long long diff;
diff = (long long)val - addr; diff = (long long)val - addr;
if (diff < -2147483648LL || diff > 2147483647LL) { if (diff < -2147483648LL || diff > 2147483647LL) {
@ -1080,8 +1080,8 @@ static void build_got(TCCState *s1)
and 'info' can be modifed if more precise info comes from the DLL. and 'info' can be modifed if more precise info comes from the DLL.
Returns offset of GOT or PLT slot. */ Returns offset of GOT or PLT slot. */
static unsigned long put_got_entry(TCCState *s1, static unsigned long put_got_entry(TCCState *s1,
int reloc_type, unsigned long size, int info, int reloc_type, unsigned long size, int info,
int sym_index) int sym_index)
{ {
int index, need_plt_entry; int index, need_plt_entry;
const char *name; const char *name;
@ -1107,18 +1107,18 @@ static unsigned long put_got_entry(TCCState *s1,
#endif #endif
if (need_plt_entry && !s1->plt) { if (need_plt_entry && !s1->plt) {
/* add PLT */ /* add PLT */
s1->plt = new_section(s1, ".plt", SHT_PROGBITS, s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
SHF_ALLOC | SHF_EXECINSTR); SHF_ALLOC | SHF_EXECINSTR);
s1->plt->sh_entsize = 4; s1->plt->sh_entsize = 4;
} }
/* If a got/plt entry already exists for that symbol, no need to add one */ /* If a got/plt entry already exists for that symbol, no need to add one */
if (sym_index < s1->nb_sym_attrs) { if (sym_index < s1->nb_sym_attrs) {
if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset) if (need_plt_entry && s1->sym_attrs[sym_index].plt_offset)
return s1->sym_attrs[sym_index].plt_offset; return s1->sym_attrs[sym_index].plt_offset;
else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset) else if (!need_plt_entry && s1->sym_attrs[sym_index].got_offset)
return s1->sym_attrs[sym_index].got_offset; return s1->sym_attrs[sym_index].got_offset;
} }
symattr = alloc_sym_attr(s1, sym_index); symattr = alloc_sym_attr(s1, sym_index);
@ -1135,7 +1135,7 @@ static unsigned long put_got_entry(TCCState *s1,
Section *plt; Section *plt;
uint8_t *p; uint8_t *p;
int modrm; int modrm;
unsigned long relofs; unsigned long relofs;
#if defined(TCC_OUTPUT_DLL_WITH_PLT) #if defined(TCC_OUTPUT_DLL_WITH_PLT)
modrm = 0x25; modrm = 0x25;
@ -1160,10 +1160,10 @@ static unsigned long put_got_entry(TCCState *s1,
put32(p + 8, PTR_SIZE * 2); put32(p + 8, PTR_SIZE * 2);
} }
/* The PLT slot refers to the relocation entry it needs /* The PLT slot refers to the relocation entry it needs
via offset. The reloc entry is created below, so its via offset. The reloc entry is created below, so its
offset is the current data_offset. */ offset is the current data_offset. */
relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0;
symattr->plt_offset = plt->data_offset; symattr->plt_offset = plt->data_offset;
p = section_ptr_add(plt, 16); p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */ p[0] = 0xff; /* jmp *(got + x) */
@ -1171,19 +1171,19 @@ static unsigned long put_got_entry(TCCState *s1,
put32(p + 2, s1->got->data_offset); put32(p + 2, s1->got->data_offset);
p[6] = 0x68; /* push $xxx */ p[6] = 0x68; /* push $xxx */
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
/* On x86-64, the relocation is referred to by _index_. */ /* On x86-64, the relocation is referred to by _index_. */
put32(p + 7, relofs / sizeof (ElfW_Rel)); put32(p + 7, relofs / sizeof (ElfW_Rel));
#else #else
put32(p + 7, relofs); put32(p + 7, relofs);
#endif #endif
p[11] = 0xe9; /* jmp plt_start */ p[11] = 0xe9; /* jmp plt_start */
put32(p + 12, -(plt->data_offset)); put32(p + 12, -(plt->data_offset));
/* If this was an UNDEF symbol set the offset in the /* If this was an UNDEF symbol set the offset in the
dynsymtab to the PLT slot, so that PC32 relocs to it dynsymtab to the PLT slot, so that PC32 relocs to it
can be resolved. */ can be resolved. */
if (sym->st_shndx == SHN_UNDEF) if (sym->st_shndx == SHN_UNDEF)
offset = plt->data_offset - 16; offset = plt->data_offset - 16;
} }
#elif defined(TCC_TARGET_ARM) #elif defined(TCC_TARGET_ARM)
if (need_plt_entry) { if (need_plt_entry) {
@ -1220,7 +1220,7 @@ static unsigned long put_got_entry(TCCState *s1,
/* the symbol is modified so that it will be relocated to /* the symbol is modified so that it will be relocated to
the PLT */ the PLT */
if (sym->st_shndx == SHN_UNDEF) if (sym->st_shndx == SHN_UNDEF)
offset = plt->data_offset - 16; offset = plt->data_offset - 16;
} }
#elif defined(TCC_TARGET_ARM64) #elif defined(TCC_TARGET_ARM64)
@ -1250,19 +1250,19 @@ static unsigned long put_got_entry(TCCState *s1,
#error unsupported CPU #error unsupported CPU
#endif #endif
if (s1->dynsym) { if (s1->dynsym) {
/* XXX This might generate multiple syms for name. */ /* XXX This might generate multiple syms for name. */
index = put_elf_sym(s1->dynsym, offset, index = put_elf_sym(s1->dynsym, offset,
size, info, 0, sym->st_shndx, name); size, info, 0, sym->st_shndx, name);
/* Create the relocation (it's against the GOT for PLT /* Create the relocation (it's against the GOT for PLT
and GOT relocs). */ and GOT relocs). */
put_elf_reloc(s1->dynsym, s1->got, put_elf_reloc(s1->dynsym, s1->got,
s1->got->data_offset, s1->got->data_offset,
reloc_type, index); reloc_type, index);
} else { } else {
/* Without .dynsym (i.e. static link or memory output) we /* Without .dynsym (i.e. static link or memory output) we
still need relocs against the generated got, so as to fill still need relocs against the generated got, so as to fill
the entries with the symbol values (determined later). */ the entries with the symbol values (determined later). */
put_elf_reloc(symtab_section, s1->got, put_elf_reloc(symtab_section, s1->got,
s1->got->data_offset, s1->got->data_offset,
reloc_type, sym_index); reloc_type, sym_index);
} }
@ -1324,8 +1324,8 @@ ST_FUNC void build_got_entries(TCCState *s1)
build_got(s1); build_got(s1);
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
&& sym->st_shndx == SHN_UNDEF) { && sym->st_shndx == SHN_UNDEF) {
unsigned long ofs; unsigned long ofs;
/* look at the symbol got offset. If none, then add one */ /* look at the symbol got offset. If none, then add one */
if (type == R_ARM_GOT32) if (type == R_ARM_GOT32)
@ -1333,27 +1333,27 @@ ST_FUNC void build_got_entries(TCCState *s1)
else else
reloc_type = R_ARM_JUMP_SLOT; reloc_type = R_ARM_JUMP_SLOT;
ofs = put_got_entry(s1, reloc_type, sym->st_size, ofs = put_got_entry(s1, reloc_type, sym->st_size,
sym->st_info, sym_index); sym->st_info, sym_index);
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("maybegot: %s, %d, %d --> ofs=0x%x\n", printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
(char *) symtab_section->link->data + sym->st_name, (char *) symtab_section->link->data + sym->st_name,
type, sym->st_shndx, ofs); type, sym->st_shndx, ofs);
#endif #endif
if (type != R_ARM_GOT32) { if (type != R_ARM_GOT32) {
addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
+ rel->r_offset); + rel->r_offset);
/* x must be signed! */ /* x must be signed! */
int x = *ptr & 0xffffff; int x = *ptr & 0xffffff;
x = (x << 8) >> 8; x = (x << 8) >> 8;
x <<= 2; x <<= 2;
x += ofs; x += ofs;
x >>= 2; x >>= 2;
#ifdef DEBUG_RELOC #ifdef DEBUG_RELOC
printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr, printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
(*ptr & 0xff000000) | x, x); (*ptr & 0xff000000) | x, x);
#endif #endif
*ptr = (*ptr & 0xff000000) | x; *ptr = (*ptr & 0xff000000) | x;
} }
} }
break; break;
case R_ARM_THM_JUMP24: case R_ARM_THM_JUMP24:
@ -1397,22 +1397,22 @@ ST_FUNC void build_got_entries(TCCState *s1)
sym_index); sym_index);
break; break;
case R_AARCH64_JUMP26: case R_AARCH64_JUMP26:
case R_AARCH64_CALL26: case R_AARCH64_CALL26:
if (!s1->got) if (!s1->got)
build_got(s1); build_got(s1);
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (sym->st_shndx == SHN_UNDEF) { if (sym->st_shndx == SHN_UNDEF) {
unsigned long ofs; unsigned long ofs;
reloc_type = R_AARCH64_JUMP_SLOT; reloc_type = R_AARCH64_JUMP_SLOT;
ofs = put_got_entry(s1, reloc_type, sym->st_size, ofs = put_got_entry(s1, reloc_type, sym->st_size,
sym->st_info, sym_index); sym->st_info, sym_index);
/* We store the place of the generated PLT slot /* We store the place of the generated PLT slot
in our addend. */ in our addend. */
rel->r_addend += ofs; rel->r_addend += ofs;
} }
break; break;
#elif defined(TCC_TARGET_C67) #elif defined(TCC_TARGET_C67)
case R_C60_GOT32: case R_C60_GOT32:
case R_C60_GOTOFF: case R_C60_GOTOFF:
@ -1439,29 +1439,29 @@ ST_FUNC void build_got_entries(TCCState *s1)
case R_X86_64_PLT32: case R_X86_64_PLT32:
sym_index = ELFW(R_SYM)(rel->r_info); sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if (type == R_X86_64_PLT32 && if (type == R_X86_64_PLT32 &&
ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT)
{ {
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
break; break;
} }
if (!s1->got) if (!s1->got)
build_got(s1); build_got(s1);
if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL || if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
type == R_X86_64_PLT32) { type == R_X86_64_PLT32) {
unsigned long ofs; unsigned long ofs;
/* look at the symbol got offset. If none, then add one */ /* look at the symbol got offset. If none, then add one */
if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL) if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
reloc_type = R_X86_64_GLOB_DAT; reloc_type = R_X86_64_GLOB_DAT;
else else
reloc_type = R_X86_64_JUMP_SLOT; reloc_type = R_X86_64_JUMP_SLOT;
ofs = put_got_entry(s1, reloc_type, sym->st_size, ofs = put_got_entry(s1, reloc_type, sym->st_size,
sym->st_info, sym_index); sym->st_info, sym_index);
if (type == R_X86_64_PLT32) if (type == R_X86_64_PLT32)
/* We store the place of the generated PLT slot /* We store the place of the generated PLT slot
in our addend. */ in our addend. */
rel->r_addend += ofs; rel->r_addend += ofs;
} }
break; break;
#else #else
@ -1546,21 +1546,21 @@ static int tcc_add_support(TCCState *s1, const char *filename)
snprintf(buf, sizeof(buf), "%s/%s/%s", s1->tcc_lib_path, snprintf(buf, sizeof(buf), "%s/%s/%s", s1->tcc_lib_path,
/* an cpu specific path inside tcc_lib_path, mainly for keeping libtcc1.a */ /* an cpu specific path inside tcc_lib_path, mainly for keeping libtcc1.a */
#ifdef TCC_TARGET_I386 #ifdef TCC_TARGET_I386
"i386" "i386"
#endif #endif
#ifdef TCC_TARGET_X86_64 #ifdef TCC_TARGET_X86_64
"x86-64" "x86-64"
#endif #endif
#ifdef TCC_TARGET_ARM #ifdef TCC_TARGET_ARM
"arm" "arm"
#endif #endif
#ifdef TCC_TARGET_ARM64 #ifdef TCC_TARGET_ARM64
"arm64" "arm64"
#endif #endif
#ifdef TCC_TARGET_C67 #ifdef TCC_TARGET_C67
"C67" "C67"
#endif #endif
,filename); ,filename);
return tcc_add_file(s1, buf, TCC_FILETYPE_BINARY); return tcc_add_file(s1, buf, TCC_FILETYPE_BINARY);
} }
@ -1587,17 +1587,17 @@ ST_FUNC void tcc_add_bcheck(TCCState *s1)
when __bound_ptr_add, __bound_new_region, when __bound_ptr_add, __bound_new_region,
__bound_delete_region called */ __bound_delete_region called */
int sym_index = find_elf_sym(symtab_section, "__bound_init"); int sym_index = find_elf_sym(symtab_section, "__bound_init");
if (sym_index) { if (sym_index) {
Section *init_section = find_section(s1, ".init"); Section *init_section = find_section(s1, ".init");
unsigned char *pinit = section_ptr_add(init_section, 5); unsigned char *pinit = section_ptr_add(init_section, 5);
pinit[0] = 0xe8; pinit[0] = 0xe8;
put32(pinit + 1, -4); put32(pinit + 1, -4);
put_elf_reloc(symtab_section, init_section, put_elf_reloc(symtab_section, init_section,
init_section->data_offset - 4, R_386_PC32, sym_index); init_section->data_offset - 4, R_386_PC32, sym_index);
} }
else else
tcc_warning("__bound_init not defined"); tcc_warning("__bound_init not defined");
} }
#endif #endif
} }
@ -1905,11 +1905,11 @@ static void export_global_syms(TCCState *s1)
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) { for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) { if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
name = (char *) symtab_section->link->data + sym->st_name; name = (char *) symtab_section->link->data + sym->st_name;
dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_shndx, name); sym->st_info, 0, sym->st_shndx, name);
index = sym - (ElfW(Sym) *) symtab_section->data; index = sym - (ElfW(Sym) *) symtab_section->data;
s1->symtab_to_dynsym[index] = dynindex; s1->symtab_to_dynsym[index] = dynindex;
} }
} }
} }
@ -2179,15 +2179,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
file_offset += s->sh_size; file_offset += s->sh_size;
} }
} }
if (j == 0) { if (j == 0) {
/* Make the first PT_LOAD segment include the program /* Make the first PT_LOAD segment include the program
headers itself (and the ELF header as well), it'll headers itself (and the ELF header as well), it'll
come out with same memory use but will make various come out with same memory use but will make various
tools like binutils strip work better. */ tools like binutils strip work better. */
ph->p_offset &= ~(ph->p_align - 1); ph->p_offset &= ~(ph->p_align - 1);
ph->p_vaddr &= ~(ph->p_align - 1); ph->p_vaddr &= ~(ph->p_align - 1);
ph->p_paddr &= ~(ph->p_align - 1); ph->p_paddr &= ~(ph->p_align - 1);
} }
ph->p_filesz = file_offset - ph->p_offset; ph->p_filesz = file_offset - ph->p_offset;
ph->p_memsz = addr - ph->p_vaddr; ph->p_memsz = addr - ph->p_vaddr;
ph++; ph++;
@ -2662,10 +2662,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) { for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
if (sym->st_shndx == SHN_UNDEF) { if (sym->st_shndx == SHN_UNDEF) {
/* relocate to PLT if symbol corresponds to a PLT entry, /* relocate to PLT if symbol corresponds to a PLT entry,
but not if it's a weak symbol */ but not if it's a weak symbol */
if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK) if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
sym->st_value = 0; sym->st_value = 0;
else if (sym->st_value) else if (sym->st_value)
sym->st_value += s1->plt->sh_addr; sym->st_value += s1->plt->sh_addr;
} else if (sym->st_shndx < SHN_LORESERVE) { } else if (sym->st_shndx < SHN_LORESERVE) {
/* do symbol relocation */ /* do symbol relocation */
@ -2690,14 +2690,14 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* Create the ELF file with name 'filename' */ /* Create the ELF file with name 'filename' */
ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
if (s1->do_strip) { if (s1->do_strip) {
int rc; int rc;
const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers const char *strip_cmd = "sstrip "; // super strip utility from ELFkickers
const char *null_dev = " 2> /dev/null"; const char *null_dev = " 2> /dev/null";
char buf[1050]; char buf[1050];
snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev); snprintf(buf, sizeof(buf), "%s%s%s", strip_cmd, filename, null_dev);
rc = system(buf); rc = system(buf);
if (rc) if (rc)
system(buf+1); // call a strip utility from binutils system(buf+1); // call a strip utility from binutils
} }
the_end: the_end:
tcc_free(s1->symtab_to_dynsym); tcc_free(s1->symtab_to_dynsym);

338
tccgen.c
View file

@ -323,7 +323,7 @@ static void apply_visibility(Sym *sym, CType *type)
ElfW(Sym) *esym; ElfW(Sym) *esym;
esym = &((ElfW(Sym) *)symtab_section->data)[sym->c]; esym = &((ElfW(Sym) *)symtab_section->data)[sym->c];
vis >>= VT_VIS_SHIFT; vis >>= VT_VIS_SHIFT;
esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis; esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1)) | vis;
} }
} }
@ -1631,7 +1631,7 @@ static inline int is_null_pointer(SValue *p)
return 0; return 0;
return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) || return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) || ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0) ||
((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0); ((p->type.t & VT_BTYPE) == VT_PTR && p->c.ptr_offset == 0);
} }
static inline int is_integer_btype(int bt) static inline int is_integer_btype(int bt)
@ -1761,18 +1761,18 @@ ST_FUNC void gen_op(int op)
#if 0 #if 0
/* #ifdef CONFIG_TCC_BCHECK /* #ifdef CONFIG_TCC_BCHECK
The main reason to removing this code: The main reason to removing this code:
#include <stdio.h> #include <stdio.h>
int main () int main ()
{ {
int v[10]; int v[10];
int i = 10; int i = 10;
int j = 9; int j = 9;
fprintf(stderr, "v+i-j = %p\n", v+i-j); fprintf(stderr, "v+i-j = %p\n", v+i-j);
fprintf(stderr, "v+(i-j) = %p\n", v+(i-j)); fprintf(stderr, "v+(i-j) = %p\n", v+(i-j));
} }
When this code is on. then the output looks like When this code is on. then the output looks like
v+i-j = 0xfffffffe v+i-j = 0xfffffffe
v+(i-j) = 0xbff84000 v+(i-j) = 0xbff84000
*/ */
/* if evaluating constant expression, no code should be /* if evaluating constant expression, no code should be
generated, so no bound check */ generated, so no bound check */
@ -2450,18 +2450,18 @@ static void gen_assign_cast(CType *dt)
dbt = dt->t & VT_BTYPE; dbt = dt->t & VT_BTYPE;
sbt = st->t & VT_BTYPE; sbt = st->t & VT_BTYPE;
if (sbt == VT_VOID || dbt == VT_VOID) { if (sbt == VT_VOID || dbt == VT_VOID) {
if (sbt == VT_VOID && dbt == VT_VOID) if (sbt == VT_VOID && dbt == VT_VOID)
; /* ; /*
It is Ok if both are void It is Ok if both are void
A test program: A test program:
void func1() {} void func1() {}
void func2() { void func2() {
return func1(); return func1();
} }
gcc accepts this program gcc accepts this program
*/ */
else else
tcc_error("cannot cast from/to void"); tcc_error("cannot cast from/to void");
} }
if (dt->t & VT_CONSTANT) if (dt->t & VT_CONSTANT)
tcc_warning("assignment of read-only location"); tcc_warning("assignment of read-only location");
@ -2542,7 +2542,7 @@ ST_FUNC void vstore(void)
dbt = ft & VT_BTYPE; dbt = ft & VT_BTYPE;
if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) || if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
(sbt == VT_INT && dbt == VT_SHORT)) (sbt == VT_INT && dbt == VT_SHORT))
&& !(vtop->type.t & VT_BITFIELD)) { && !(vtop->type.t & VT_BITFIELD)) {
/* optimize char/short casts */ /* optimize char/short casts */
delayed_cast = VT_MUSTCAST; delayed_cast = VT_MUSTCAST;
vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT))); vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)));
@ -2764,20 +2764,20 @@ static void parse_attribute(AttributeDef *ad)
next(); next();
skip(')'); skip(')');
break; break;
case TOK_VISIBILITY1: case TOK_VISIBILITY1:
case TOK_VISIBILITY2: case TOK_VISIBILITY2:
skip('('); skip('(');
if (tok != TOK_STR) if (tok != TOK_STR)
expect("visibility(\"default|hidden|internal|protected\")"); expect("visibility(\"default|hidden|internal|protected\")");
if (!strcmp (tokc.cstr->data, "default")) if (!strcmp (tokc.cstr->data, "default"))
ad->a.visibility = STV_DEFAULT; ad->a.visibility = STV_DEFAULT;
else if (!strcmp (tokc.cstr->data, "hidden")) else if (!strcmp (tokc.cstr->data, "hidden"))
ad->a.visibility = STV_HIDDEN; ad->a.visibility = STV_HIDDEN;
else if (!strcmp (tokc.cstr->data, "internal")) else if (!strcmp (tokc.cstr->data, "internal"))
ad->a.visibility = STV_INTERNAL; ad->a.visibility = STV_INTERNAL;
else if (!strcmp (tokc.cstr->data, "protected")) else if (!strcmp (tokc.cstr->data, "protected"))
ad->a.visibility = STV_PROTECTED; ad->a.visibility = STV_PROTECTED;
else else
expect("visibility(\"default|hidden|internal|protected\")"); expect("visibility(\"default|hidden|internal|protected\")");
next(); next();
skip(')'); skip(')');
@ -2973,8 +2973,8 @@ static void struct_decl(CType *type, int u, int tdef)
while (tok != '}') { while (tok != '}') {
parse_btype(&btype, &ad); parse_btype(&btype, &ad);
while (1) { while (1) {
if (flexible) if (flexible)
tcc_error("flexible array member '%s' not at the end of struct", tcc_error("flexible array member '%s' not at the end of struct",
get_tok_str(v, NULL)); get_tok_str(v, NULL));
bit_size = -1; bit_size = -1;
v = 0; v = 0;
@ -2982,21 +2982,21 @@ static void struct_decl(CType *type, int u, int tdef)
if (tok != ':') { if (tok != ':') {
type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT); type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
if (v == 0) { if (v == 0) {
if ((type1.t & VT_BTYPE) != VT_STRUCT) if ((type1.t & VT_BTYPE) != VT_STRUCT)
expect("identifier"); expect("identifier");
else { else {
int v = btype.ref->v; int v = btype.ref->v;
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) { if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
if (tcc_state->ms_extensions == 0) if (tcc_state->ms_extensions == 0)
expect("identifier"); expect("identifier");
} }
} }
} }
if (type_size(&type1, &align) < 0) { if (type_size(&type1, &align) < 0) {
if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c) if ((a == TOK_STRUCT) && (type1.t & VT_ARRAY) && c)
flexible = 1; flexible = 1;
else else
tcc_error("field '%s' has incomplete type", tcc_error("field '%s' has incomplete type",
get_tok_str(v, NULL)); get_tok_str(v, NULL));
} }
if ((type1.t & VT_BTYPE) == VT_FUNC || if ((type1.t & VT_BTYPE) == VT_FUNC ||
@ -3807,11 +3807,11 @@ ST_FUNC void unary(void)
gen_cast(&type); gen_cast(&type);
} }
} else if (tok == '{') { } else if (tok == '{') {
/* /*
if (nocode_wanted) if (nocode_wanted)
tcc_error("statement expression in global scope"); */ tcc_error("statement expression in global scope"); */
/* this check breaks compilation of the linux 2.4.26 with the meesage: /* this check breaks compilation of the linux 2.4.26 with the meesage:
linux/include/net/tcp.h:945: error: statement expression in global scope */ linux/include/net/tcp.h:945: error: statement expression in global scope */
/* save all registers */ /* save all registers */
save_regs(0); save_regs(0);
@ -3872,12 +3872,12 @@ ST_FUNC void unary(void)
if ((vtop->type.t & VT_BTYPE) == VT_PTR) if ((vtop->type.t & VT_BTYPE) == VT_PTR)
tcc_error("pointer not accepted for unary plus"); tcc_error("pointer not accepted for unary plus");
/* In order to force cast, we add zero, except for floating point /* In order to force cast, we add zero, except for floating point
where we really need an noop (otherwise -0.0 will be transformed where we really need an noop (otherwise -0.0 will be transformed
into +0.0). */ into +0.0). */
if (!is_float(vtop->type.t)) { if (!is_float(vtop->type.t)) {
vpushi(0); vpushi(0);
gen_op('+'); gen_op('+');
} }
break; break;
case TOK_SIZEOF: case TOK_SIZEOF:
case TOK_ALIGNOF1: case TOK_ALIGNOF1:
@ -4050,20 +4050,20 @@ ST_FUNC void unary(void)
next(); next();
unary(); unary();
t = vtop->type.t & VT_BTYPE; t = vtop->type.t & VT_BTYPE;
if (is_float(t)) { if (is_float(t)) {
/* In IEEE negate(x) isn't subtract(0,x), but rather /* In IEEE negate(x) isn't subtract(0,x), but rather
subtract(-0, x). */ subtract(-0, x). */
vpush(&vtop->type); vpush(&vtop->type);
if (t == VT_FLOAT) if (t == VT_FLOAT)
vtop->c.f = -0.0f; vtop->c.f = -0.0f;
else if (t == VT_DOUBLE) else if (t == VT_DOUBLE)
vtop->c.d = -0.0; vtop->c.d = -0.0;
else else
vtop->c.ld = -0.0; vtop->c.ld = -0.0;
} else } else
vpushi(0); vpushi(0);
vswap(); vswap();
gen_op('-'); gen_op('-');
break; break;
case TOK_LAND: case TOK_LAND:
if (!gnu_ext) if (!gnu_ext)
@ -4142,7 +4142,7 @@ ST_FUNC void unary(void)
/* if forward reference, we must point to s */ /* if forward reference, we must point to s */
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
vtop->sym = s; vtop->sym = s;
vtop->c.ptr_offset = 0; vtop->c.ptr_offset = 0;
} }
break; break;
} }
@ -4312,10 +4312,10 @@ ST_FUNC void unary(void)
size = type_size(&s->type, &align); size = type_size(&s->type, &align);
/* We're writing whole regs often, make sure there's enough /* We're writing whole regs often, make sure there's enough
space. Assume register size is power of 2. */ space. Assume register size is power of 2. */
if (regsize > align) if (regsize > align)
align = regsize; align = regsize;
loc = (loc - size) & -align; loc = (loc - size) & -align;
addr = loc; addr = loc;
#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) #if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE)
@ -4610,16 +4610,16 @@ static void expr_cond(void)
(t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED)) (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
type.t |= VT_UNSIGNED; type.t |= VT_UNSIGNED;
} else if (bt1 == VT_PTR || bt2 == VT_PTR) { } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
/* If one is a null ptr constant the result type /* If one is a null ptr constant the result type
is the other. */ is the other. */
if (is_null_pointer (vtop)) if (is_null_pointer (vtop))
type = type1; type = type1;
else if (is_null_pointer (&sv)) else if (is_null_pointer (&sv))
type = type2; type = type2;
/* XXX: test pointer compatibility, C99 has more elaborate /* XXX: test pointer compatibility, C99 has more elaborate
rules here. */ rules here. */
else else
type = type1; type = type1;
} else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
/* XXX: test function pointer compatibility */ /* XXX: test function pointer compatibility */
type = bt1 == VT_FUNC ? type1 : type2; type = bt1 == VT_FUNC ? type1 : type2;
@ -4785,14 +4785,14 @@ static void label_or_decl(int l)
/* fast test first */ /* fast test first */
if (tok >= TOK_UIDENT) if (tok >= TOK_UIDENT)
{ {
/* no need to save tokc because tok is an identifier */ /* no need to save tokc because tok is an identifier */
last_tok = tok; last_tok = tok;
next(); next();
if (tok == ':') { if (tok == ':') {
unget_tok(last_tok); unget_tok(last_tok);
return; return;
} }
unget_tok(last_tok); unget_tok(last_tok);
} }
decl(l); decl(l);
} }
@ -4891,10 +4891,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
Sym *p; Sym *p;
switch(vtop->type.t & VT_BTYPE) { switch(vtop->type.t & VT_BTYPE) {
/* case VT_PTR: */ /* case VT_PTR: */
/* this breaks a compilation of the linux kernel v2.4.26 */ /* this breaks a compilation of the linux kernel v2.4.26 */
/* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */ /* pmd_t *new = ({ __asm__ __volatile__("ud2\n") ; ((pmd_t *)1); }); */
/* Look a commit a80acab: Display error on statement expressions with complex return type */ /* Look a commit a80acab: Display error on statement expressions with complex return type */
/* A pointer is not a complex return type */ /* A pointer is not a complex return type */
case VT_STRUCT: case VT_STRUCT:
case VT_ENUM: case VT_ENUM:
case VT_FUNC: case VT_FUNC:
@ -5642,38 +5642,38 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
AttributeDef ad1; AttributeDef ad1;
CType type1; CType type1;
next(); next();
if (tcc_state->old_struct_init_code) { if (tcc_state->old_struct_init_code) {
/* an old version of struct initialization. /* an old version of struct initialization.
It have a problems. But with a new version It have a problems. But with a new version
linux 2.4.26 can't load ramdisk. linux 2.4.26 can't load ramdisk.
*/ */
while (tok == '(') { while (tok == '(') {
par_count++; par_count++;
next(); next();
} }
if (!parse_btype(&type1, &ad1)) if (!parse_btype(&type1, &ad1))
expect("cast"); expect("cast");
type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
#if 0 #if 0
if (!is_assignable_types(type, &type1)) if (!is_assignable_types(type, &type1))
tcc_error("invalid type for cast"); tcc_error("invalid type for cast");
#endif #endif
skip(')'); skip(')');
} }
else else
{ {
if (tok != '(') { if (tok != '(') {
if (!parse_btype(&type1, &ad1)) if (!parse_btype(&type1, &ad1))
expect("cast"); expect("cast");
type_decl(&type1, &ad1, &n, TYPE_ABSTRACT); type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
#if 0 #if 0
if (!is_assignable_types(type, &type1)) if (!is_assignable_types(type, &type1))
tcc_error("invalid type for cast"); tcc_error("invalid type for cast");
#endif #endif
skip(')'); skip(')');
} else } else
unget_tok(tok); unget_tok(tok);
} }
} }
no_oblock = 1; no_oblock = 1;
@ -5699,28 +5699,28 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
/* gr: skip fields from same union - ugly. */ /* gr: skip fields from same union - ugly. */
while (f->next) { while (f->next) {
int align = 0; int align = 0;
int f_size = type_size(&f->type, &align); int f_size = type_size(&f->type, &align);
int f_type = (f->type.t & VT_BTYPE); int f_type = (f->type.t & VT_BTYPE);
///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t); ///printf("index: %2d %08x -- %2d %08x\n", f->c, f->type.t, f->next->c, f->next->type.t);
/* test for same offset */ /* test for same offset */
if (f->next->c != f->c) if (f->next->c != f->c)
break; break;
if ((f_type == VT_STRUCT) && (f_size == 0)) { if ((f_type == VT_STRUCT) && (f_size == 0)) {
/* /*
Lets assume a structure of size 0 can't be a member of the union. Lets assume a structure of size 0 can't be a member of the union.
This allow to compile the following code from a linux kernel v2.4.26 This allow to compile the following code from a linux kernel v2.4.26
typedef struct { } rwlock_t; typedef struct { } rwlock_t;
struct fs_struct { struct fs_struct {
int count; int count;
rwlock_t lock; rwlock_t lock;
int umask; int umask;
}; };
struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, }; struct fs_struct init_fs = { { (1) }, (rwlock_t) {}, 0022, };
tcc-0.9.23 can succesfully compile this version of the kernel. tcc-0.9.23 can succesfully compile this version of the kernel.
gcc don't have problems with this code too. gcc don't have problems with this code too.
*/ */
break; break;
} }
/* if yes, test for bitfield shift */ /* if yes, test for bitfield shift */
@ -5760,21 +5760,21 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
/* just skip expression */ /* just skip expression */
parlevel = parlevel1 = 0; parlevel = parlevel1 = 0;
while ((parlevel > 0 || parlevel1 > 0 || while ((parlevel > 0 || parlevel1 > 0 ||
(tok != '}' && tok != ',')) && tok != -1) { (tok != '}' && tok != ',')) && tok != -1) {
if (tok == '(') if (tok == '(')
parlevel++; parlevel++;
else if (tok == ')') { else if (tok == ')') {
if (parlevel == 0 && parlevel1 == 0) if (parlevel == 0 && parlevel1 == 0)
break; break;
parlevel--; parlevel--;
} }
else if (tok == '{') else if (tok == '{')
parlevel1++; parlevel1++;
else if (tok == '}') { else if (tok == '}') {
if (parlevel == 0 && parlevel1 == 0) if (parlevel == 0 && parlevel1 == 0)
break; break;
parlevel1--; parlevel1--;
} }
next(); next();
} }
} else { } else {
@ -5995,12 +5995,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
} else { } else {
/* push global reference */ /* push global reference */
sym = get_sym_ref(type, sec, addr, size); sym = get_sym_ref(type, sec, addr, size);
vpushsym(type, sym); vpushsym(type, sym);
} }
/* patch symbol weakness */ /* patch symbol weakness */
if (type->t & VT_WEAK) if (type->t & VT_WEAK)
weaken_symbol(sym); weaken_symbol(sym);
apply_visibility(sym, type); apply_visibility(sym, type);
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
/* handles bounds now because the symbol must be defined /* handles bounds now because the symbol must be defined
before for the relocation */ before for the relocation */
@ -6236,11 +6236,11 @@ static int decl0(int l, int is_for_loop_init)
if (((btype.t & VT_BTYPE) == VT_ENUM || if (((btype.t & VT_BTYPE) == VT_ENUM ||
(btype.t & VT_BTYPE) == VT_STRUCT) && (btype.t & VT_BTYPE) == VT_STRUCT) &&
tok == ';') { tok == ';') {
if ((btype.t & VT_BTYPE) == VT_STRUCT) { if ((btype.t & VT_BTYPE) == VT_STRUCT) {
int v = btype.ref->v; int v = btype.ref->v;
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM) if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
tcc_warning("unnamed struct/union that defines no instances"); tcc_warning("unnamed struct/union that defines no instances");
} }
next(); next();
continue; continue;
} }
@ -6286,7 +6286,7 @@ static int decl0(int l, int is_for_loop_init)
if (ad.a.func_export) if (ad.a.func_export)
type.t |= VT_EXPORT; type.t |= VT_EXPORT;
#endif #endif
type.t |= ad.a.visibility << VT_VIS_SHIFT; type.t |= ad.a.visibility << VT_VIS_SHIFT;
if (tok == '{') { if (tok == '{') {
if (l == VT_LOCAL) if (l == VT_LOCAL)
@ -6327,10 +6327,10 @@ static int decl0(int l, int is_for_loop_init)
if (sym->type.t & VT_STATIC) if (sym->type.t & VT_STATIC)
type.t = (type.t & ~VT_EXTERN) | VT_STATIC; type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
/* If the definition has no visibility use the /* If the definition has no visibility use the
one from prototype. */ one from prototype. */
if (! (type.t & VT_VIS_MASK)) if (! (type.t & VT_VIS_MASK))
type.t |= sym->type.t & VT_VIS_MASK; type.t |= sym->type.t & VT_VIS_MASK;
if (!is_compatible_types(&sym->type, &type)) { if (!is_compatible_types(&sym->type, &type)) {
func_error1: func_error1:

48
tccpe.c
View file

@ -398,22 +398,22 @@ static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
s = pe_export_name(s1, sym); s = pe_export_name(s1, sym);
if (n) { if (n) {
/* second try: */ /* second try: */
if (sym->st_other & ST_PE_STDCALL) { if (sym->st_other & ST_PE_STDCALL) {
/* try w/0 stdcall deco (windows API convention) */ /* try w/0 stdcall deco (windows API convention) */
p = strrchr(s, '@'); p = strrchr(s, '@');
if (!p || s[0] != '_') if (!p || s[0] != '_')
break; break;
strcpy(buffer, s+1)[p-s-1] = 0; strcpy(buffer, s+1)[p-s-1] = 0;
} else if (s[0] != '_') { /* try non-ansi function */ } else if (s[0] != '_') { /* try non-ansi function */
buffer[0] = '_', strcpy(buffer + 1, s); buffer[0] = '_', strcpy(buffer + 1, s);
} else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */ } else if (0 == memcmp(s, "__imp__", 7)) { /* mingw 2.0 */
strcpy(buffer, s + 6); strcpy(buffer, s + 6);
} else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */ } else if (0 == memcmp(s, "_imp___", 7)) { /* mingw 3.7 */
strcpy(buffer, s + 6); strcpy(buffer, s + 6);
} else { } else {
break; break;
} }
s = buffer; s = buffer;
} }
sym_index = find_elf_sym(s1->dynsymtab_section, s); sym_index = find_elf_sym(s1->dynsymtab_section, s);
// printf("find (%d) %d %s\n", n, sym_index, s); // printf("find (%d) %d %s\n", n, sym_index, s);
@ -565,9 +565,9 @@ static int pe_write(struct pe_info *pe)
#endif #endif
/* NT additional fields. */ /* NT additional fields. */
#if defined(TCC_TARGET_ARM) #if defined(TCC_TARGET_ARM)
0x00100000, /*DWORD ImageBase; */ 0x00100000, /*DWORD ImageBase; */
#else #else
0x00400000, /*DWORD ImageBase; */ 0x00400000, /*DWORD ImageBase; */
#endif #endif
0x00001000, /*DWORD SectionAlignment; */ 0x00001000, /*DWORD SectionAlignment; */
0x00000200, /*DWORD FileAlignment; */ 0x00000200, /*DWORD FileAlignment; */
@ -1841,13 +1841,13 @@ ST_FUNC int pe_output_file(TCCState * s1, const char *filename)
pe.subsystem = s1->pe_subsystem; pe.subsystem = s1->pe_subsystem;
/* set default file/section alignment */ /* set default file/section alignment */
if (pe.subsystem == 1) { if (pe.subsystem == 1) {
pe.section_align = 0x20; pe.section_align = 0x20;
pe.file_align = 0x20; pe.file_align = 0x20;
} else { } else {
pe.section_align = 0x1000; pe.section_align = 0x1000;
pe.file_align = 0x200; pe.file_align = 0x200;
} }
if (s1->section_align != 0) if (s1->section_align != 0)
pe.section_align = s1->section_align; pe.section_align = s1->section_align;

View file

@ -786,7 +786,7 @@ redo_start:
else if (tok == TOK_LINEFEED) else if (tok == TOK_LINEFEED)
goto redo_start; goto redo_start;
} else if (parse_flags & PARSE_FLAG_ASM_FILE) } else if (parse_flags & PARSE_FLAG_ASM_FILE)
p = parse_line_comment(p); p = parse_line_comment(p);
break; break;
_default: _default:
default: default:
@ -1786,7 +1786,7 @@ _line_num:
total_lines += file->line_num - n; total_lines += file->line_num - n;
file->line_num = n; file->line_num = n;
if (s1->do_debug) if (s1->do_debug)
put_stabs(file->filename, N_BINCL, 0, 0, 0); put_stabs(file->filename, N_BINCL, 0, 0, 0);
break; break;
case TOK_ERROR: case TOK_ERROR:
case TOK_WARNING: case TOK_WARNING:
@ -2272,7 +2272,7 @@ static void parse_number(const char *p)
if (n & 0xffffffff00000000LL || must_64bit) { if (n & 0xffffffff00000000LL || must_64bit) {
tok = TOK_CLLONG; tok = TOK_CLLONG;
n1 = n >> 32; n1 = n >> 32;
} else { } else {
tok = TOK_CINT; tok = TOK_CINT;
n1 = n; n1 = n;
} }
@ -2538,7 +2538,7 @@ maybe_newline:
} else if (c == '.') { } else if (c == '.') {
PEEKC(c, p); PEEKC(c, p);
if (c != '.') if (c != '.')
expect("'.'"); expect("'.'");
PEEKC(c, p); PEEKC(c, p);
tok = TOK_DOTS; tok = TOK_DOTS;
} else { } else {

View file

@ -127,7 +127,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
for (i=0; i<argc; ++i) for (i=0; i<argc; ++i)
bound_new_region(argv[i], strlen(argv[i])); bound_new_region(argv[i], strlen(argv[i]));
errno = 0; /* clean errno value */ errno = 0; /* clean errno value */
ret = (*prog_main)(argc, argv); ret = (*prog_main)(argc, argv);
/* unmark argv area */ /* unmark argv area */
@ -139,7 +139,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
} else } else
#endif #endif
{ {
errno = 0; /* clean errno value */ errno = 0; /* clean errno value */
ret = (*prog_main)(argc, argv); ret = (*prog_main)(argc, argv);
} }
return ret; return ret;
@ -652,7 +652,7 @@ static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
if (rt_bound_error_msg && *rt_bound_error_msg) if (rt_bound_error_msg && *rt_bound_error_msg)
rt_error(uc, *rt_bound_error_msg); rt_error(uc, *rt_bound_error_msg);
else else
rt_error(uc, "access violation"); rt_error(uc, "access violation");
break; break;
case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_STACK_OVERFLOW:
rt_error(uc, "stack overflow"); rt_error(uc, "stack overflow");
@ -697,12 +697,12 @@ static int rt_get_caller_pc(addr_t *paddr, CONTEXT *uc, int level)
fp = uc->Ebp; fp = uc->Ebp;
#endif #endif
if (level > 0) { if (level > 0) {
for(i=1;i<level;i++) { for(i = 1; i < level; i++) {
/* XXX: check address validity with program info */ /* XXX: check address validity with program info */
if (fp <= 0x1000 || fp >= 0xc0000000) if (fp <= 0x1000 || fp >= 0xc0000000)
return -1; return -1;
fp = ((addr_t*)fp)[0]; fp = ((addr_t*)fp)[0];
} }
pc = ((addr_t*)fp)[1]; pc = ((addr_t*)fp)[1];
} }
*paddr = pc; *paddr = pc;

View file

@ -477,18 +477,17 @@ void load(int r, SValue *sv)
gen_modrm(r, VT_LOCAL, sv->sym, fc); gen_modrm(r, VT_LOCAL, sv->sym, fc);
} else if (v == VT_CMP) { } else if (v == VT_CMP) {
orex(0,r,0,0); orex(0,r,0,0);
if ((fc & ~0x100) != TOK_NE) if ((fc & ~0x100) != TOK_NE)
oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */ oad(0xb8 + REG_VALUE(r), 0); /* mov $0, r */
else else
oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */ oad(0xb8 + REG_VALUE(r), 1); /* mov $1, r */
if (fc & 0x100) if (fc & 0x100) {
{ /* This was a float compare. If the parity bit is
/* This was a float compare. If the parity bit is * set the result was unordered, meaning false for everything
set the result was unordered, meaning false for everything * except TOK_NE, and true for TOK_NE. */
except TOK_NE, and true for TOK_NE. */ fc &= ~0x100;
fc &= ~0x100; o(0x037a + (REX_BASE(r) << 8));
o(0x037a + (REX_BASE(r) << 8)); }
}
orex(0,r,0, 0x0f); /* setxx %br */ orex(0,r,0, 0x0f); /* setxx %br */
o(fc); o(fc);
o(0xc0 + REG_VALUE(r)); o(0xc0 + REG_VALUE(r));
@ -619,7 +618,7 @@ static void gcall_or_jmp(int is_jmp)
{ {
int r; int r;
if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) { ((vtop->r & VT_SYM) || (vtop->c.ll-4) == (int)(vtop->c.ll-4))) {
/* constant case */ /* constant case */
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
/* relocation case */ /* relocation case */
@ -1705,7 +1704,7 @@ void gfunc_prolog(CType *func_type)
param_addr = addr; param_addr = addr;
addr += size; addr += size;
break; break;
default: break; /* nothing to be done for x86_64_mode_none */ default: break; /* nothing to be done for x86_64_mode_none */
} }
sym_push(sym->v & ~SYM_FIELD, type, sym_push(sym->v & ~SYM_FIELD, type,
VT_LOCAL | VT_LVAL, param_addr); VT_LOCAL | VT_LVAL, param_addr);
@ -1717,8 +1716,8 @@ void gfunc_prolog(CType *func_type)
func_bound_offset = lbounds_section->data_offset; func_bound_offset = lbounds_section->data_offset;
func_bound_ind = ind; func_bound_ind = ind;
oad(0xb8, 0); /* lbound section pointer */ oad(0xb8, 0); /* lbound section pointer */
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
oad(0xb8, 0); /* call to function */ oad(0xb8, 0); /* call to function */
} }
#endif #endif
} }
@ -1730,7 +1729,7 @@ void gfunc_epilog(void)
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check if (tcc_state->do_bounds_check
&& func_bound_offset != lbounds_section->data_offset) && func_bound_offset != lbounds_section->data_offset)
{ {
addr_t saved_ind; addr_t saved_ind;
addr_t *bounds_ptr; addr_t *bounds_ptr;
@ -1754,7 +1753,7 @@ void gfunc_epilog(void)
o(0x5250); /* save returned value, if any */ o(0x5250); /* save returned value, if any */
greloc(cur_text_section, sym_data, ind + 1, R_386_32); greloc(cur_text_section, sym_data, ind + 1, R_386_32);
oad(0xb8, 0); /* mov xxx, %rax */ oad(0xb8, 0); /* mov xxx, %rax */
o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */ o(0xc78948); /* mov %rax,%rdi ## first arg in %rdi, this must be ptr */
gen_static_call(TOK___bound_local_delete); gen_static_call(TOK___bound_local_delete);
o(0x585a); /* restore returned value, if any */ o(0x585a); /* restore returned value, if any */
} }
@ -1806,24 +1805,24 @@ int gtst(int inv, int t)
v = vtop->r & VT_VALMASK; v = vtop->r & VT_VALMASK;
if (v == VT_CMP) { if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
if (vtop->c.i & 0x100) if (vtop->c.i & 0x100)
{ {
/* This was a float compare. If the parity flag is set /* This was a float compare. If the parity flag is set
the result was unordered. For anything except != this the result was unordered. For anything except != this
means false and we don't jump (anding both conditions). means false and we don't jump (anding both conditions).
For != this means true (oring both). For != this means true (oring both).
Take care about inverting the test. We need to jump Take care about inverting the test. We need to jump
to our target if the result was unordered and test wasn't NE, to our target if the result was unordered and test wasn't NE,
otherwise if unordered we don't want to jump. */ otherwise if unordered we don't want to jump. */
vtop->c.i &= ~0x100; vtop->c.i &= ~0x100;
if (!inv == (vtop->c.i != TOK_NE)) if (!inv == (vtop->c.i != TOK_NE))
o(0x067a); /* jp +6 */ o(0x067a); /* jp +6 */
else else
{ {
g(0x0f); g(0x0f);
t = psym(0x8a, t); /* jp t */ t = psym(0x8a, t); /* jp t */
} }
} }
g(0x0f); g(0x0f);
t = psym((vtop->c.i - 16) ^ inv, t); t = psym((vtop->c.i - 16) ^ inv, t);
} else if (v == VT_JMP || v == VT_JMPI) { } else if (v == VT_JMP || v == VT_JMPI) {