tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] TLS/__thread support


From: Simon 'corecode' Schubert
Subject: Re: [Tinycc-devel] TLS/__thread support
Date: Mon, 27 Aug 2007 01:34:18 +0200
User-agent: Thunderbird 2.0.0.4 (X11/20070627)

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 <address@hidden>
# 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 <address@hidden>
# 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 <address@hidden>
# 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 */
     }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]