diff options
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.c | 34 | ||||
-rw-r--r-- | gcc/config/vxworks.c | 77 |
2 files changed, 98 insertions, 13 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index dee2410..43c669f 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -2854,6 +2854,9 @@ x86_64_elf_select_section (tree decl, int reloc, /* We don't split these for medium model. Place them into default sections and hope for best. */ break; + case SECCAT_EMUTLS_VAR: + case SECCAT_EMUTLS_TMPL: + gcc_unreachable (); } if (sname) { @@ -2890,16 +2893,16 @@ x86_64_elf_unique_section (tree decl, int reloc) case SECCAT_DATA_REL_LOCAL: case SECCAT_DATA_REL_RO: case SECCAT_DATA_REL_RO_LOCAL: - prefix = one_only ? ".gnu.linkonce.ld." : ".ldata."; + prefix = one_only ? ".ld" : ".ldata"; break; case SECCAT_BSS: - prefix = one_only ? ".gnu.linkonce.lb." : ".lbss."; + prefix = one_only ? ".lb" : ".lbss"; break; case SECCAT_RODATA: case SECCAT_RODATA_MERGE_STR: case SECCAT_RODATA_MERGE_STR_INIT: case SECCAT_RODATA_MERGE_CONST: - prefix = one_only ? ".gnu.linkonce.lr." : ".lrodata."; + prefix = one_only ? ".lr" : ".lrodata"; break; case SECCAT_SRODATA: case SECCAT_SDATA: @@ -2911,23 +2914,28 @@ x86_64_elf_unique_section (tree decl, int reloc) /* We don't split these for medium model. Place them into default sections and hope for best. */ break; + case SECCAT_EMUTLS_VAR: + prefix = targetm.emutls.var_section; + break; + case SECCAT_EMUTLS_TMPL: + prefix = targetm.emutls.tmpl_section; + break; } if (prefix) { - const char *name; - size_t nlen, plen; + const char *name, *linkonce; char *string; - plen = strlen (prefix); name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); name = targetm.strip_name_encoding (name); - nlen = strlen (name); - - string = (char *) alloca (nlen + plen + 1); - memcpy (string, prefix, plen); - memcpy (string + plen, name, nlen + 1); - - DECL_SECTION_NAME (decl) = build_string (nlen + plen, string); + + /* If we're using one_only, then there needs to be a .gnu.linkonce + prefix to the section name. */ + linkonce = one_only ? ".gnu.linkonce" : ""; + + string = ACONCAT ((linkonce, prefix, ".", name, NULL)); + + DECL_SECTION_NAME (decl) = build_string (strlen (string), string); return; } } diff --git a/gcc/config/vxworks.c b/gcc/config/vxworks.c index 4fde6ad..709791b 100644 --- a/gcc/config/vxworks.c +++ b/gcc/config/vxworks.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "output.h" #include "tm.h" +#include "tree.h" /* Like default_named_section_asm_out_constructor, except that even constructors with DEFAULT_INIT_PRIORITY must go in a numbered @@ -56,11 +57,87 @@ vxworks_asm_out_destructor (rtx symbol, int priority) assemble_addr_to_section (symbol, sec); } +/* Return the list of FIELD_DECLs that make up an emulated TLS + variable's control object. TYPE is the structure these are fields + of and *NAME will be filled in with the structure tag that should + be used. */ + +static tree +vxworks_emutls_var_fields (tree type, tree *name) +{ + tree field, next_field; + + *name = get_identifier ("__tls_var"); + + field = build_decl (FIELD_DECL, get_identifier ("size"), + unsigned_type_node); + DECL_CONTEXT (field) = type; + next_field = field; + + field = build_decl (FIELD_DECL, get_identifier ("module_id"), + unsigned_type_node); + DECL_CONTEXT (field) = type; + TREE_CHAIN (field) = next_field; + next_field = field; + + field = build_decl (FIELD_DECL, get_identifier ("offset"), + unsigned_type_node); + DECL_CONTEXT (field) = type; + TREE_CHAIN (field) = next_field; + + return field; +} + +/* Return the CONSTRUCTOR to initialize an emulated TLS control + object. VAR is the control object. DECL is the TLS object itself + and TMPL_ADDR is the address (an ADDR_EXPR) of the initializer for + that object. */ + +static tree +vxworks_emutls_var_init (tree var, tree decl, tree tmpl_addr) +{ + VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 3); + constructor_elt *elt; + + tree type = TREE_TYPE (var); + tree field = TYPE_FIELDS (type); + + elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = field; + elt->value = fold_convert (TREE_TYPE (field), tmpl_addr); + + elt = VEC_quick_push (constructor_elt, v, NULL); + field = TREE_CHAIN (field); + elt->index = field; + elt->value = build_int_cst (TREE_TYPE (field), 0); + + elt = VEC_quick_push (constructor_elt, v, NULL); + field = TREE_CHAIN (field); + elt->index = field; + elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); + + return build_constructor (type, v); +} + /* Do VxWorks-specific parts of OVERRIDE_OPTIONS. */ void vxworks_override_options (void) { + /* We don't support __thread via target hooks. */ + targetm.have_tls = false; + + targetm.emutls.get_address = "__builtin___tls_lookup"; + targetm.emutls.register_common = NULL; + targetm.emutls.var_section = ".tls_vars"; + targetm.emutls.tmpl_section = ".tls_data"; + targetm.emutls.var_prefix = "__tls__"; + targetm.emutls.tmpl_prefix = ""; + targetm.emutls.var_fields = vxworks_emutls_var_fields; + targetm.emutls.var_init = vxworks_emutls_var_init; + targetm.emutls.var_align_fixed = true; + targetm.emutls.debug_form_tls_address = true; + /* We can use .ctors/.dtors sections only in RTP mode. */ targetm.have_ctors_dtors = TARGET_VXWORKS_RTP; |