Cleanups (float consts, sections, symbols)
introduce common_section (SHN_COMMON), factorize some handling in decl_initializer_alloc, add section_add and use it to factorize some code that allocates stuff in sections (at the same time also fixing harmless bugs re section alignment), use init_putv to emit float consts into .data from gv() (fixing an XXX).
This commit is contained in:
parent
25522e4799
commit
c7dbc900c8
3 changed files with 44 additions and 81 deletions
3
tcc.h
3
tcc.h
|
|
@ -470,7 +470,6 @@ typedef struct Sym {
|
||||||
|
|
||||||
/* special flag, too */
|
/* special flag, too */
|
||||||
#define SECTION_ABS ((void *)1)
|
#define SECTION_ABS ((void *)1)
|
||||||
#define SECTION_COMMON ((void *)2)
|
|
||||||
|
|
||||||
typedef struct Section {
|
typedef struct Section {
|
||||||
unsigned long data_offset; /* current data offset */
|
unsigned long data_offset; /* current data offset */
|
||||||
|
|
@ -1360,6 +1359,7 @@ typedef struct {
|
||||||
} Stab_Sym;
|
} Stab_Sym;
|
||||||
|
|
||||||
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
|
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||||
|
ST_DATA Section *common_section;
|
||||||
ST_DATA Section *cur_text_section; /* current section where function code is generated */
|
ST_DATA Section *cur_text_section; /* current section where function code is generated */
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
|
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
|
||||||
|
|
@ -1381,6 +1381,7 @@ ST_FUNC void tccelf_stab_new(TCCState *s);
|
||||||
|
|
||||||
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int 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 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 void *section_ptr_add(Section *sec, addr_t size);
|
||||||
ST_FUNC void section_reserve(Section *sec, unsigned long size);
|
ST_FUNC void section_reserve(Section *sec, unsigned long size);
|
||||||
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
ST_FUNC Section *find_section(TCCState *s1, const char *name);
|
||||||
|
|
|
||||||
38
tccelf.c
38
tccelf.c
|
|
@ -27,6 +27,7 @@
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
|
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||||
|
ST_DATA Section *common_section;
|
||||||
ST_DATA Section *cur_text_section; /* current section where function code is generated */
|
ST_DATA Section *cur_text_section; /* current section where function code is generated */
|
||||||
#ifdef CONFIG_TCC_ASM
|
#ifdef CONFIG_TCC_ASM
|
||||||
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
|
ST_DATA Section *last_text_section; /* to handle .previous asm directive */
|
||||||
|
|
@ -55,6 +56,8 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||||
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
||||||
|
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
||||||
|
common_section->sh_num = SHN_COMMON;
|
||||||
|
|
||||||
/* symbols are always generated for linking stage */
|
/* symbols are always generated for linking stage */
|
||||||
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
|
||||||
|
|
@ -208,17 +211,27 @@ ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
|
||||||
sec->data_allocated = size;
|
sec->data_allocated = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reserve at least 'size' bytes aligned per 'align' in section
|
||||||
|
'sec' from current offset, and return the aligned offset */
|
||||||
|
ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
|
||||||
|
{
|
||||||
|
size_t offset, offset1;
|
||||||
|
|
||||||
|
offset = (sec->data_offset + align - 1) & -align;
|
||||||
|
offset1 = offset + size;
|
||||||
|
if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated)
|
||||||
|
section_realloc(sec, offset1);
|
||||||
|
sec->data_offset = offset1;
|
||||||
|
if (align > sec->sh_addralign)
|
||||||
|
sec->sh_addralign = align;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* reserve at least 'size' bytes in section 'sec' from
|
/* reserve at least 'size' bytes in section 'sec' from
|
||||||
sec->data_offset. */
|
sec->data_offset. */
|
||||||
ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
|
ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
|
||||||
{
|
{
|
||||||
size_t offset, offset1;
|
size_t offset = section_add(sec, size, 1);
|
||||||
|
|
||||||
offset = sec->data_offset;
|
|
||||||
offset1 = offset + size;
|
|
||||||
if (offset1 > sec->data_allocated)
|
|
||||||
section_realloc(sec, offset1);
|
|
||||||
sec->data_offset = offset1;
|
|
||||||
return sec->data + offset;
|
return sec->data + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,18 +715,13 @@ static void sort_syms(TCCState *s1, Section *s)
|
||||||
ST_FUNC void relocate_common_syms(void)
|
ST_FUNC void relocate_common_syms(void)
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
unsigned long offset, align;
|
|
||||||
|
|
||||||
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
if (sym->st_shndx == SHN_COMMON) {
|
if (sym->st_shndx == SHN_COMMON) {
|
||||||
/* align symbol */
|
/* symbol alignment is in st_value for SHN_COMMONs */
|
||||||
align = sym->st_value;
|
sym->st_value = section_add(bss_section, sym->st_size,
|
||||||
offset = bss_section->data_offset;
|
sym->st_value);
|
||||||
offset = (offset + align - 1) & -align;
|
|
||||||
sym->st_value = offset;
|
|
||||||
sym->st_shndx = bss_section->sh_num;
|
sym->st_shndx = bss_section->sh_num;
|
||||||
offset += sym->st_size;
|
|
||||||
bss_section->data_offset = offset;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
84
tccgen.c
84
tccgen.c
|
|
@ -76,6 +76,7 @@ static int is_compatible_types(CType *type1, CType *type2);
|
||||||
static int parse_btype(CType *type, AttributeDef *ad);
|
static int parse_btype(CType *type, AttributeDef *ad);
|
||||||
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||||
static void parse_expr_type(CType *type);
|
static void parse_expr_type(CType *type);
|
||||||
|
static void init_putv(CType *type, Section *sec, unsigned long c);
|
||||||
static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
|
static void decl_initializer(CType *type, Section *sec, unsigned long c, int first, int size_only);
|
||||||
static void block(int *bsym, int *csym, int is_expr);
|
static void block(int *bsym, int *csym, int is_expr);
|
||||||
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
|
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
|
||||||
|
|
@ -302,8 +303,6 @@ ST_FUNC void put_extern_sym2(Sym *sym, Section *section,
|
||||||
sh_num = SHN_UNDEF;
|
sh_num = SHN_UNDEF;
|
||||||
else if (section == SECTION_ABS)
|
else if (section == SECTION_ABS)
|
||||||
sh_num = SHN_ABS;
|
sh_num = SHN_ABS;
|
||||||
else if (section == SECTION_COMMON)
|
|
||||||
sh_num = SHN_COMMON;
|
|
||||||
else
|
else
|
||||||
sh_num = section->sh_num;
|
sh_num = section->sh_num;
|
||||||
|
|
||||||
|
|
@ -1065,7 +1064,7 @@ static void gbound(void)
|
||||||
register value (such as structures). */
|
register value (such as structures). */
|
||||||
ST_FUNC int gv(int rc)
|
ST_FUNC int gv(int rc)
|
||||||
{
|
{
|
||||||
int r, bit_pos, bit_size, size, align, i;
|
int r, bit_pos, bit_size, size, align;
|
||||||
int rc2;
|
int rc2;
|
||||||
|
|
||||||
/* NOTE: get_reg can modify vstack[] */
|
/* NOTE: get_reg can modify vstack[] */
|
||||||
|
|
@ -1096,44 +1095,15 @@ ST_FUNC int gv(int rc)
|
||||||
} else {
|
} else {
|
||||||
if (is_float(vtop->type.t) &&
|
if (is_float(vtop->type.t) &&
|
||||||
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
(vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
|
||||||
Sym *sym;
|
|
||||||
int *ptr;
|
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
|
|
||||||
CValue check;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* XXX: unify with initializers handling ? */
|
|
||||||
/* CPUs usually cannot use float constants, so we store them
|
/* CPUs usually cannot use float constants, so we store them
|
||||||
generically in data segment */
|
generically in data segment */
|
||||||
size = type_size(&vtop->type, &align);
|
size = type_size(&vtop->type, &align);
|
||||||
offset = (data_section->data_offset + align - 1) & -align;
|
offset = section_add(data_section, size, align);
|
||||||
data_section->data_offset = offset;
|
vpush_ref(&vtop->type, data_section, offset, size);
|
||||||
/* XXX: not portable yet */
|
vswap();
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
init_putv(&vtop->type, data_section, offset);
|
||||||
/* Zero pad x87 tenbyte long doubles */
|
vtop->r |= VT_LVAL;
|
||||||
if (size == LDOUBLE_SIZE) {
|
|
||||||
vtop->c.tab[2] &= 0xffff;
|
|
||||||
#if LDOUBLE_SIZE == 16
|
|
||||||
vtop->c.tab[3] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
ptr = section_ptr_add(data_section, size);
|
|
||||||
size = size >> 2;
|
|
||||||
#if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
|
|
||||||
check.d = 1;
|
|
||||||
if(check.tab[0])
|
|
||||||
for(i=0;i<size;i++)
|
|
||||||
ptr[i] = vtop->c.tab[size-1-i];
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
for(i=0;i<size;i++)
|
|
||||||
ptr[i] = vtop->c.tab[i];
|
|
||||||
sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
|
|
||||||
vtop->r |= VT_LVAL | VT_SYM;
|
|
||||||
vtop->sym = sym;
|
|
||||||
vtop->c.i = 0;
|
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
if (vtop->r & VT_MUSTBOUND)
|
if (vtop->r & VT_MUSTBOUND)
|
||||||
|
|
@ -4351,7 +4321,7 @@ ST_FUNC void unary(void)
|
||||||
t = VT_LLONG;
|
t = VT_LLONG;
|
||||||
goto push_tokc;
|
goto push_tokc;
|
||||||
case TOK_CULLONG:
|
case TOK_CULLONG:
|
||||||
t =VT_LLONG | VT_UNSIGNED;
|
t = VT_LLONG | VT_UNSIGNED;
|
||||||
goto push_tokc;
|
goto push_tokc;
|
||||||
case TOK_CFLOAT:
|
case TOK_CFLOAT:
|
||||||
t = VT_FLOAT;
|
t = VT_FLOAT;
|
||||||
|
|
@ -6098,9 +6068,7 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||||
gen_assign_cast(&dtype);
|
gen_assign_cast(&dtype);
|
||||||
bt = type->t & VT_BTYPE;
|
bt = type->t & VT_BTYPE;
|
||||||
size = type_size(type, &align);
|
size = type_size(type, &align);
|
||||||
if (c + size > sec->data_allocated) {
|
section_reserve(sec, c + size);
|
||||||
section_realloc(sec, c + size);
|
|
||||||
}
|
|
||||||
ptr = sec->data + c;
|
ptr = sec->data + c;
|
||||||
/* XXX: make code faster ? */
|
/* XXX: make code faster ? */
|
||||||
if (!(type->t & VT_BITFIELD)) {
|
if (!(type->t & VT_BITFIELD)) {
|
||||||
|
|
@ -6190,6 +6158,9 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
|
||||||
case VT_SHORT:
|
case VT_SHORT:
|
||||||
*(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
|
*(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
|
||||||
break;
|
break;
|
||||||
|
case VT_FLOAT:
|
||||||
|
*(float*)ptr = vtop->c.f;
|
||||||
|
break;
|
||||||
case VT_DOUBLE:
|
case VT_DOUBLE:
|
||||||
*(double *)ptr = vtop->c.d;
|
*(double *)ptr = vtop->c.d;
|
||||||
break;
|
break;
|
||||||
|
|
@ -6475,7 +6446,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
||||||
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
int has_init, int v, int scope)
|
int has_init, int v, int scope)
|
||||||
{
|
{
|
||||||
int size, align, addr, data_offset;
|
int size, align, addr;
|
||||||
ParseState saved_parse_state = {0};
|
ParseState saved_parse_state = {0};
|
||||||
TokenString *init_str = NULL;
|
TokenString *init_str = NULL;
|
||||||
Section *sec;
|
Section *sec;
|
||||||
|
|
@ -6624,41 +6595,24 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sec) {
|
if (sec) {
|
||||||
data_offset = sec->data_offset;
|
addr = section_add(sec, size, align);
|
||||||
data_offset = (data_offset + align - 1) & -align;
|
|
||||||
addr = data_offset;
|
|
||||||
/* very important to increment global pointer at this time
|
|
||||||
because initializers themselves can create new initializers */
|
|
||||||
data_offset += size;
|
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
/* add padding if bound check */
|
/* add padding if bound check */
|
||||||
if (tcc_state->do_bounds_check)
|
if (tcc_state->do_bounds_check)
|
||||||
data_offset++;
|
section_add(sec, 1, 1);
|
||||||
#endif
|
#endif
|
||||||
sec->data_offset = data_offset;
|
|
||||||
/* allocate section space to put the data */
|
|
||||||
if (sec->sh_type != SHT_NOBITS &&
|
|
||||||
data_offset > sec->data_allocated)
|
|
||||||
section_realloc(sec, data_offset);
|
|
||||||
/* align section if needed */
|
|
||||||
if (align > sec->sh_addralign)
|
|
||||||
sec->sh_addralign = align;
|
|
||||||
} else {
|
} else {
|
||||||
addr = 0; /* avoid warning */
|
addr = align; /* SHN_COMMON is special, symbol value is align */
|
||||||
|
sec = common_section;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v) {
|
if (v) {
|
||||||
if (scope != VT_CONST || !sym) {
|
if (!sym) {
|
||||||
sym = sym_push(v, type, r | VT_SYM, 0);
|
sym = sym_push(v, type, r | VT_SYM, 0);
|
||||||
sym->asm_label = ad->asm_label;
|
sym->asm_label = ad->asm_label;
|
||||||
}
|
}
|
||||||
/* update symbol definition */
|
/* update symbol definition */
|
||||||
if (sec) {
|
put_extern_sym(sym, sec, addr, size);
|
||||||
put_extern_sym(sym, sec, addr, size);
|
|
||||||
} else {
|
|
||||||
put_extern_sym(sym, SECTION_COMMON, align, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* push global reference */
|
/* push global reference */
|
||||||
sym = get_sym_ref(type, sec, addr, size);
|
sym = get_sym_ref(type, sec, addr, size);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue