Hey, Okay, here we go. It's a bit hackish, but not more than the rest of tinycc, so I think that's okay. Currently only the i386 platform is supported and only the Initial Exec and the Local Exec TLS models are supported.
I didn't change linking yet, because I have some other problems related to debug sections right now. Binaries linked with gnu ld work as far as I can tell. cheers simon -- Serve - BSD +++ RENT this banner advert +++ ASCII Ribbon /"\ Work - Mac +++ space for low €€€ NOW!1 +++ Campaign \ / Party Enjoy Relax | http://dragonflybsd.org Against HTML \ Dude 2c 2 the max ! http://golden-apple.biz Mail + News / \
# HG changeset patch # User Simon 'corecode' Schubert <[EMAIL PROTECTED]> # Date 1188165918 -7200 # Node ID abe9732b8349a02e6a17ba1b9fa270ff10b06089 # Parent 6cd310489cbb841e913d0470ffa48452a54a088e Add __thread/tls handling. diff -r 6cd310489cbb -r abe9732b8349 elf.h --- a/elf.h Sun Aug 26 21:16:37 2007 +0200 +++ b/elf.h Mon Aug 27 00:05:18 2007 +0200 @@ -302,6 +302,7 @@ typedef struct #define SHF_WRITE (1 << 0) /* Writable */ #define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ #define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_TLS (1 << 10) /* Thread local storage */ #define SHF_MASKPROC 0xf0000000 /* Processor-specific */ /* Symbol table entry. */ @@ -392,6 +393,7 @@ typedef struct #define STT_SECTION 3 /* Symbol associated with a section */ #define STT_FILE 4 /* Symbol's name is file name */ #define STT_NUM 5 /* Number of defined types. */ +#define STT_TLS 6 /* Symbol is a TLS object. */ #define STT_LOOS 11 /* Start of OS-specific */ #define STT_HIOS 12 /* End of OS-specific */ #define STT_LOPROC 13 /* Start of processor-specific */ @@ -907,8 +909,11 @@ typedef struct #define R_386_RELATIVE 8 /* Adjust by program base */ #define R_386_GOTOFF 9 /* 32 bit offset to GOT */ #define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ /* Keep this the last entry. */ -#define R_386_NUM 11 +#define R_386_NUM 18 /* SUN SPARC specific definitions. */ diff -r 6cd310489cbb -r abe9732b8349 i386/i386-gen.c --- a/i386/i386-gen.c Sun Aug 26 21:16:37 2007 +0200 +++ b/i386/i386-gen.c Mon Aug 27 00:05:18 2007 +0200 @@ -155,19 +155,33 @@ static int oad(int c, int s) /* output constant with relocation if 'r & VT_SYM' is true */ static void gen_addr32(int r, Sym *sym, int c) { - if (r & VT_SYM) - greloc(cur_text_section, sym, ind, R_386_32); + if (r & VT_SYM) { + int reloc = R_386_32; + + if (sym->type.t & VT_TLS) { + if (sym->type.t & VT_EXTERN) + reloc = R_386_TLS_IE; + else + reloc = R_386_TLS_LE; + } + greloc(cur_text_section, sym, ind, reloc); + } gen_le32(c); } /* generate a modrm reference. 'op_reg' contains the addtionnal 3 opcode bits */ -static void gen_modrm(int op_reg, int r, Sym *sym, int c) +static void gen_modrm(int op_reg, int r, Sym *sym, int c, int disp_reg) { op_reg = op_reg << 3; if ((r & VT_VALMASK) == VT_CONST) { /* constant memory reference */ - o(0x05 | op_reg); + if (disp_reg != -1) { + /* displacement register */ + o(0x80 | disp_reg | op_reg); + } else { + o(0x05 | op_reg); + } gen_addr32(r, sym, c); } else if ((r & VT_VALMASK) == VT_LOCAL) { /* currently, we use only ebp as base */ @@ -189,10 +203,29 @@ void load(int r, SValue *sv) { int v, t, ft, fc, fr; SValue v1; + int tls = -1; fr = sv->r; ft = sv->type.t; fc = sv->c.ul; + + /* Thread local storage needs a load of the tls offset */ + if ((fr & VT_SYM) && (sv->sym->type.t & VT_TLS)) { + switch (ft & VT_BTYPE) { + default: + /* simply use the dest as scratch */ + tls = r; + break; + case VT_FLOAT: + case VT_DOUBLE: + case VT_LDOUBLE: + /* have to get a register to do address calc */ + tls = get_reg(RC_INT); + break; + } + o(0x8b65); /* movl %gs:0x0, tls */ + gen_modrm(tls, VT_CONST, NULL, 0, -1); + } v = fr & VT_VALMASK; if (fr & VT_LVAL) { @@ -223,14 +256,19 @@ void load(int r, SValue *sv) } else { o(0x8b); /* movl */ } - gen_modrm(r, fr, sv->sym, fc); + gen_modrm(r, fr, sv->sym, fc, tls); } else { if (v == VT_CONST) { - o(0xb8 + r); /* mov $xx, r */ - gen_addr32(fr, sv->sym, fc); + if (tls == -1) { + o(0xb8 + r); /* mov $xx, r */ + gen_addr32(fr, sv->sym, fc); + } else { + o(0x03); /* add xx, r */ + gen_modrm(tls, fr, sv->sym, fc, -1); + } } else if (v == VT_LOCAL) { o(0x8d); /* lea xxx(%ebp), r */ - gen_modrm(r, VT_LOCAL, sv->sym, fc); + gen_modrm(r, VT_LOCAL, sv->sym, fc, -1); } else if (v == VT_CMP) { oad(0xb8 + r, 0); /* mov $0, r */ o(0x0f); /* setxx %br */ @@ -253,11 +291,19 @@ void store(int r, SValue *v) void store(int r, SValue *v) { int fr, bt, ft, fc; + int tls = -1; ft = v->type.t; fc = v->c.ul; fr = v->r & VT_VALMASK; bt = ft & VT_BTYPE; + + /* Thread local storage needs a load of the tls offset */ + if ((v->r & VT_SYM) && (v->sym->type.t & VT_TLS)) { + tls = get_reg(RC_INT); + o(0x8b65); + gen_modrm(tls, VT_CONST, NULL, 0, -1); + } /* XXX: incorrect if float reg to reg */ if (bt == VT_FLOAT) { o(0xd9); /* fsts */ @@ -280,7 +326,7 @@ void store(int r, SValue *v) if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { - gen_modrm(r, v->r, v->sym, fc); + gen_modrm(r, v->r, v->sym, fc, tls); } else if (fr != r) { o(0xc0 + fr + r * 8); /* mov r, fr */ } @@ -460,7 +506,7 @@ void gfunc_prolog(CType *func_type) /* save FASTCALL register */ loc -= 4; o(0x89); /* movl */ - gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); + gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc, -1); param_addr = loc; } else { param_addr = addr; @@ -852,7 +898,7 @@ void gen_opf(int op) o(0xdc); else o(0xd8); - gen_modrm(a, r, vtop->sym, fc); + gen_modrm(a, r, vtop->sym, fc, -1); } vtop--; } diff -r 6cd310489cbb -r abe9732b8349 tcc.c --- a/tcc.c Sun Aug 26 21:16:37 2007 +0200 +++ b/tcc.c Mon Aug 27 00:05:18 2007 +0200 @@ -63,6 +63,7 @@ static int unget_buffer_enabled; static int unget_buffer_enabled; static int parse_flags; static Section *text_section, *data_section, *bss_section; /* predefined sections */ +static Section *tdata_section, *tbss_section; /* thread local storage sections */ #ifdef CONFIG_TCC_ASM static Section *last_text_section; /* to handle .previous asm directive */ #endif @@ -416,6 +417,8 @@ static void put_extern_sym2(Sym *sym, Se if (!sym->c) { if ((sym->type.t & VT_BTYPE) == VT_FUNC) sym_type = STT_FUNC; + else if (sym->type.t & VT_TLS) + sym_type = STT_TLS; else sym_type = STT_OBJECT; if (sym->type.t & VT_STATIC) @@ -5782,7 +5785,7 @@ static void struct_decl(CType *type, int if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT) expect("identifier"); if ((type1.t & VT_BTYPE) == VT_FUNC || - (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE))) + (type1.t & VT_STORAGE)) error("invalid type for '%s'", get_tok_str(v, NULL)); } @@ -6027,6 +6030,10 @@ static int parse_btype(CType *type, Attr t |= VT_INLINE; next(); break; + case TOK_THREAD: + t |= VT_TLS; + next(); + break; /* GNUC attribute */ case TOK_ATTRIBUTE1: @@ -8057,10 +8064,14 @@ static void decl_initializer_alloc(CType /* allocate symbol in corresponding section */ sec = ad->section; if (!sec) { - if (has_init) - sec = data_section; - else if ((type->t & VT_STATIC) || tcc_state->nocommon) - sec = bss_section; + if (type->t & VT_TLS) { + sec = has_init ? tdata_section : tbss_section; + } else { + if (has_init) + sec = data_section; + else if ((type->t & VT_STATIC) || tcc_state->nocommon) + sec = bss_section; + } } if (sec) { data_offset = sec->data_offset; @@ -8332,6 +8343,10 @@ static void decl(int l) if (sym->c == FUNC_OLD) func_decl_list(sym); } + + /* Functions can't have __thread storage */ + if ((type.t & VT_FUNC) && (type.t & VT_TLS)) + error("function declared __thread"); if (tok == '{') { if (l == VT_LOCAL) @@ -8442,7 +8457,8 @@ static void decl(int l) extern */ external_sym(v, &type, r); } else { - type.t |= (btype.t & VT_STATIC); // Retain "static". + /* Retain "static" and "__thread". */ + type.t |= (btype.t & (VT_STATIC|VT_TLS)); if (type.t & VT_STATIC) r |= VT_CONST; else @@ -8907,6 +8923,10 @@ TCCState *tcc_new(void) text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 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); /* symbols are always generated for linking stage */ symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0, diff -r 6cd310489cbb -r abe9732b8349 tcc.h --- a/tcc.h Sun Aug 26 21:16:37 2007 +0200 +++ b/tcc.h Mon Aug 27 00:05:18 2007 +0200 @@ -473,11 +473,12 @@ struct TCCState { #define VT_STATIC 0x00000100 /* static variable */ #define VT_TYPEDEF 0x00000200 /* typedef definition */ #define VT_INLINE 0x00000400 /* inline definition */ +#define VT_TLS 0x00004000 /* thread local storage definition */ #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */ /* 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)) /* token values */ diff -r 6cd310489cbb -r abe9732b8349 tcctok.h --- a/tcctok.h Sun Aug 26 21:16:37 2007 +0200 +++ b/tcctok.h Mon Aug 27 00:05:18 2007 +0200 @@ -32,6 +32,7 @@ DEF(TOK_INLINE1, "inline") DEF(TOK_INLINE2, "__inline") /* gcc keyword */ DEF(TOK_INLINE3, "__inline__") /* gcc keyword */ + DEF(TOK_THREAD, "__thread") /* gcc keyword */ DEF(TOK_RESTRICT1, "restrict") DEF(TOK_RESTRICT2, "__restrict") DEF(TOK_RESTRICT3, "__restrict__")
# HG changeset patch # User Simon 'corecode' Schubert <[EMAIL PROTECTED]> # Date 1188168025 -7200 # Node ID d4b10d0be5c3323ac00e089e3107d78ec8214017 # Parent abe9732b8349a02e6a17ba1b9fa270ff10b06089 Generate correct code for VT_EXTERN and local thread symbols. diff -r abe9732b8349 -r d4b10d0be5c3 i386/i386-gen.c --- a/i386/i386-gen.c Mon Aug 27 00:05:18 2007 +0200 +++ b/i386/i386-gen.c Mon Aug 27 00:40:25 2007 +0200 @@ -204,6 +204,7 @@ void load(int r, SValue *sv) int v, t, ft, fc, fr; SValue v1; int tls = -1; + int ext = 0; fr = sv->r; ft = sv->type.t; @@ -211,20 +212,22 @@ void load(int r, SValue *sv) /* Thread local storage needs a load of the tls offset */ if ((fr & VT_SYM) && (sv->sym->type.t & VT_TLS)) { - switch (ft & VT_BTYPE) { - default: - /* simply use the dest as scratch */ - tls = r; - break; - case VT_FLOAT: - case VT_DOUBLE: - case VT_LDOUBLE: - /* have to get a register to do address calc */ - tls = get_reg(RC_INT); - break; + /* simply use the dest as scratch */ + tls = r; + if (fr & VT_LVAL) { + switch (ft & VT_BTYPE) { + case VT_FLOAT: + case VT_DOUBLE: + case VT_LDOUBLE: + /* have to get a register to do address calc */ + tls = get_reg(RC_INT); + break; + } } o(0x8b65); /* movl %gs:0x0, tls */ gen_modrm(tls, VT_CONST, NULL, 0, -1); + if (sv->sym->type.t & VT_EXTERN) + ext = 1; } v = fr & VT_VALMASK; @@ -235,6 +238,13 @@ void load(int r, SValue *sv) v1.c.ul = fc; load(r, &v1); fr = r; + } + if (ext) { + /* calculate offset */ + o(0x03); /* add xx, tls */ + gen_modrm(tls, VT_SYM|VT_CONST, sv->sym, fc, -1); + fr = VT_CONST; + fc = 0; } if ((ft & VT_BTYPE) == VT_FLOAT) { o(0xd9); /* flds */ @@ -263,8 +273,13 @@ void load(int r, SValue *sv) o(0xb8 + r); /* mov $xx, r */ gen_addr32(fr, sv->sym, fc); } else { - o(0x03); /* add xx, r */ - gen_modrm(tls, fr, sv->sym, fc, -1); + if (ext) { + o(0x03); /* add xx, r */ + gen_modrm(r, fr, sv->sym, fc, -1); + } else { + o(0x8d); /* lea xx, r */ + gen_modrm(r, fr, sv->sym, fc, r); + } } } else if (v == VT_LOCAL) { o(0x8d); /* lea xxx(%ebp), r */
# HG changeset patch # User Simon 'corecode' Schubert <[EMAIL PROTECTED]> # Date 1188168693 -7200 # Node ID 34b0f3475dcecb6392e8fabc406814d1728b8a84 # Parent d4b10d0be5c3323ac00e089e3107d78ec8214017 Produce correct code for VT_EXTERN stores. diff -r d4b10d0be5c3 -r 34b0f3475dce i386/i386-gen.c --- a/i386/i386-gen.c Mon Aug 27 00:40:25 2007 +0200 +++ b/i386/i386-gen.c Mon Aug 27 00:51:33 2007 +0200 @@ -243,6 +243,7 @@ void load(int r, SValue *sv) /* calculate offset */ o(0x03); /* add xx, tls */ gen_modrm(tls, VT_SYM|VT_CONST, sv->sym, fc, -1); + /* XXXTLS get rid of the superfluous displacement */ fr = VT_CONST; fc = 0; } @@ -305,19 +306,28 @@ void load(int r, SValue *sv) /* store register 'r' in lvalue 'v' */ void store(int r, SValue *v) { - int fr, bt, ft, fc; + int fr, bt, ft, fc, vr; int tls = -1; ft = v->type.t; fc = v->c.ul; fr = v->r & VT_VALMASK; bt = ft & VT_BTYPE; + vr = v->r; /* Thread local storage needs a load of the tls offset */ if ((v->r & VT_SYM) && (v->sym->type.t & VT_TLS)) { tls = get_reg(RC_INT); o(0x8b65); gen_modrm(tls, VT_CONST, NULL, 0, -1); + if (v->sym->type.t & VT_EXTERN) { + /* calculate offset */ + o(0x03); /* add xx, tls */ + gen_modrm(tls, VT_SYM|VT_CONST, v->sym, fc, -1); + /* XXXTLS get rid of the superfluous displacement */ + vr = VT_CONST; + fc = 0; + } } /* XXX: incorrect if float reg to reg */ if (bt == VT_FLOAT) { @@ -341,7 +351,7 @@ void store(int r, SValue *v) if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) { - gen_modrm(r, v->r, v->sym, fc, tls); + gen_modrm(r, vr, v->sym, fc, tls); } else if (fr != r) { o(0xc0 + fr + r * 8); /* mov r, fr */ }
_______________________________________________ Tinycc-devel mailing list Tinycc-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/tinycc-devel