mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-17 15:44:18 +08:00
feat: implement Thread Local Storage frontend support
This commit is contained in:
parent
fad812360b
commit
8443e25bf5
8
tcc.h
8
tcc.h
@ -889,6 +889,7 @@ struct TCCState {
|
||||
|
||||
/* predefined sections */
|
||||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||
Section *tdata_section, *tbss_section;
|
||||
Section *common_section;
|
||||
Section *cur_text_section; /* current section where function code is generated */
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
@ -1063,7 +1064,8 @@ struct filespec {
|
||||
#define VT_STATIC 0x00002000 /* static variable */
|
||||
#define VT_TYPEDEF 0x00004000 /* typedef definition */
|
||||
#define VT_INLINE 0x00008000 /* inline definition */
|
||||
/* currently unused: 0x000[1248]0000 */
|
||||
#define VT_TLS 0x00010000 /* thread-local storage */
|
||||
/* currently unused: 0x000[248]0000 */
|
||||
|
||||
#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
|
||||
#define VT_STRUCT_MASK (((1U << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
|
||||
@ -1081,7 +1083,7 @@ struct filespec {
|
||||
#define VT_ATOMIC VT_VOLATILE
|
||||
|
||||
/* type mask (except storage) */
|
||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_TLS)
|
||||
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
|
||||
|
||||
/* symbol was created by tccasm.c first */
|
||||
@ -1970,6 +1972,8 @@ static inline void post_sem(TCCSem *p) {
|
||||
#define data_section TCC_STATE_VAR(data_section)
|
||||
#define rodata_section TCC_STATE_VAR(rodata_section)
|
||||
#define bss_section TCC_STATE_VAR(bss_section)
|
||||
#define tdata_section TCC_STATE_VAR(tdata_section)
|
||||
#define tbss_section TCC_STATE_VAR(tbss_section)
|
||||
#define common_section TCC_STATE_VAR(common_section)
|
||||
#define cur_text_section TCC_STATE_VAR(cur_text_section)
|
||||
#define bounds_section TCC_STATE_VAR(bounds_section)
|
||||
|
||||
48
tccelf.c
48
tccelf.c
@ -70,6 +70,8 @@ ST_FUNC void tccelf_new(TCCState *s)
|
||||
/* create ro data section (make ro after relocation done with GNU_RELRO) */
|
||||
rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
|
||||
bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
||||
tdata_section = new_section(s, ".tdata", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS);
|
||||
tbss_section = new_section(s, ".tbss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE | SHF_TLS);
|
||||
common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
|
||||
common_section->sh_num = SHN_COMMON;
|
||||
|
||||
@ -2294,7 +2296,7 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||
if (k < 0x900)
|
||||
++d->shnum;
|
||||
if (k < 0x700) {
|
||||
f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
|
||||
f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR);
|
||||
#if TARGETOS_NetBSD
|
||||
/* NetBSD only supports 2 PT_LOAD sections.
|
||||
See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
|
||||
@ -2353,6 +2355,18 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||
++phnum;
|
||||
if (d->roinf)
|
||||
++phnum;
|
||||
{
|
||||
int has_tls = 0;
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (s->sh_flags & SHF_TLS) {
|
||||
has_tls = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_tls)
|
||||
++phnum;
|
||||
}
|
||||
d->phnum = phnum;
|
||||
d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
|
||||
|
||||
@ -2429,10 +2443,6 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||
ph->p_flags |= PF_W;
|
||||
if (f & SHF_EXECINSTR)
|
||||
ph->p_flags |= PF_X;
|
||||
if (f & SHF_TLS) {
|
||||
ph->p_type = PT_TLS;
|
||||
ph->p_align = align + 1;
|
||||
}
|
||||
|
||||
ph->p_offset = file_offset;
|
||||
ph->p_vaddr = addr;
|
||||
@ -2477,6 +2487,34 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
|
||||
fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section);
|
||||
if (d->roinf)
|
||||
fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
|
||||
{
|
||||
/* Create PT_TLS segment covering all TLS sections */
|
||||
Section *tls_start_sec = NULL;
|
||||
addr_t tls_start = 0, tls_end = 0;
|
||||
for (i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
if (s->sh_flags & SHF_TLS && s->sh_size) {
|
||||
if (!tls_start_sec) {
|
||||
tls_start_sec = s;
|
||||
tls_start = s->sh_addr;
|
||||
tls_end = s->sh_addr + s->sh_size;
|
||||
} else {
|
||||
if (s->sh_addr < tls_start)
|
||||
tls_start = s->sh_addr;
|
||||
if (s->sh_addr + s->sh_size > tls_end)
|
||||
tls_end = s->sh_addr + s->sh_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tls_start_sec) {
|
||||
ph = fill_phdr(++ph, PT_TLS, tls_start_sec);
|
||||
ph->p_vaddr = tls_start;
|
||||
ph->p_paddr = tls_start;
|
||||
ph->p_filesz = tls_end - tls_start;
|
||||
ph->p_memsz = ph->p_filesz;
|
||||
ph->p_align = tls_start_sec->sh_addralign;
|
||||
}
|
||||
}
|
||||
if (d->interp)
|
||||
fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
|
||||
if (phfill) {
|
||||
|
||||
16
tccgen.c
16
tccgen.c
@ -526,6 +526,8 @@ ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
|
||||
sym_type = STT_NOTYPE;
|
||||
if (IS_ASM_FUNC(t))
|
||||
sym_type = STT_FUNC;
|
||||
} else if (t & VT_TLS) {
|
||||
sym_type = STT_TLS;
|
||||
} else {
|
||||
sym_type = STT_OBJECT;
|
||||
}
|
||||
@ -4931,7 +4933,12 @@ static int parse_btype(CType *type, AttributeDef *ad, int ignore_label)
|
||||
}
|
||||
goto basic_type2;
|
||||
case TOK_THREAD_LOCAL:
|
||||
tcc_error("_Thread_local is not implemented");
|
||||
case TOK___thread:
|
||||
if (t & VT_TLS)
|
||||
tcc_error("multiple thread-local storage specifiers");
|
||||
t |= VT_TLS;
|
||||
next();
|
||||
break;
|
||||
default:
|
||||
if (typespec_found)
|
||||
goto the_end;
|
||||
@ -8376,7 +8383,12 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
||||
CType *tp = type;
|
||||
while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
|
||||
tp = &tp->ref->type;
|
||||
if (tp->t & VT_CONSTANT) {
|
||||
if (type->t & VT_TLS) {
|
||||
if (has_init)
|
||||
sec = tdata_section;
|
||||
else
|
||||
sec = tbss_section;
|
||||
} else if (tp->t & VT_CONSTANT) {
|
||||
sec = rodata_section;
|
||||
} else if (has_init) {
|
||||
sec = data_section;
|
||||
|
||||
1
tcctok.h
1
tcctok.h
@ -39,6 +39,7 @@
|
||||
DEF(TOK_RESTRICT3, "__restrict__")
|
||||
DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
|
||||
DEF(TOK_THREAD_LOCAL, "_Thread_local") /* C11 thread-local storage */
|
||||
DEF(TOK___thread, "__thread") /* GCC thread-local storage extension */
|
||||
|
||||
DEF(TOK_GENERIC, "_Generic")
|
||||
DEF(TOK_STATIC_ASSERT, "_Static_assert")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user