From 00402c9415a04840f2f1b08b001ff761fd2a40fc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 9 Nov 2015 01:20:21 -0800 Subject: [PATCH] i386: Add address spaces for fs/gs segments and tls * config/i386/i386-c.c (ix86_target_macros): Define __SEG_FS, __SEG_GS, __SEG_TLS. (ix86_register_pragmas): Register address spaces __seg_fs, __seg_gs, __seg_tls. * config/i386/i386-protos.h (enum ix86_address_seg): Remove. (ADDR_SPACE_SEG_FS, ADDR_SPACE_SEG_GS, ADDR_SPACE_SEG_TLS): New. (struct ix86_address): Use addr_space_t instead of ix86_address_seg. * config/i386/i386.c (ix86_decompose_address): Likewise. (ix86_legitimate_address_p): Likewise. (memory_address_length): Likewise. Check mem address space too. (ix86_print_operand): Use ix86_print_operand_address_as. (ix86_print_operand_address_as): Rename from ix86_print_operand_address, add new addr_space_t parameter. Validate that either the parameter or the ix86_address segment is default address space. Handle ADDR_SPACE_SEG_TLS. (ix86_print_operand_address): New. (ix86_addr_space_subset_p, TARGET_ADDR_SPACE_SUBSET_P): New. (ix86_addr_space_convert, TARGET_ADDR_SPACE_CONVERT): New. (ix86_addr_space_debug, TARGET_ADDR_SPACE_DEBUG): New. (ix86_addr_space_zero_address_valid): New. (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New. * config/i386/i386.h (DEFAULT_TLS_SEG_REG): Use addr_space_t constants. * config/i386/rdos.h (DEFAULT_TLS_SEG_REG): Likewise. * config/i386/predicates.md (address_no_seg_operand): Likewise. (vsib_address_operand): Likewise. (address_mpx_no_base_operand): Likewise. (address_mpx_no_index_operand): Likewise. * doc/extend.texi (x86 Named Address Spaces): New section. * gcc.target/i386/addr-space-1.c: New test. * gcc.target/i386/addr-space-2.c: New test. * gcc.target/i386/addr-space-3.c: New test. From-SVN: r230003 --- gcc/ChangeLog | 29 +++ gcc/config/i386/i386-c.c | 8 + gcc/config/i386/i386-protos.h | 7 +- gcc/config/i386/i386.c | 246 +++++++++++++------ gcc/config/i386/i386.h | 3 +- gcc/config/i386/predicates.md | 8 +- gcc/config/i386/rdos.h | 2 +- gcc/doc/extend.texi | 47 +++- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.target/i386/addr-space-1.c | 11 + gcc/testsuite/gcc.target/i386/addr-space-2.c | 11 + gcc/testsuite/gcc.target/i386/addr-space-3.c | 10 + 12 files changed, 307 insertions(+), 81 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-1.c create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-2.c create mode 100644 gcc/testsuite/gcc.target/i386/addr-space-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7e5728d29f..d0b119f0c5b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,34 @@ 2015-11-09 Richard Henderson + * config/i386/i386-c.c (ix86_target_macros): Define __SEG_FS, + __SEG_GS, __SEG_TLS. + (ix86_register_pragmas): Register address spaces __seg_fs, + __seg_gs, __seg_tls. + * config/i386/i386-protos.h (enum ix86_address_seg): Remove. + (ADDR_SPACE_SEG_FS, ADDR_SPACE_SEG_GS, ADDR_SPACE_SEG_TLS): New. + (struct ix86_address): Use addr_space_t instead of ix86_address_seg. + * config/i386/i386.c (ix86_decompose_address): Likewise. + (ix86_legitimate_address_p): Likewise. + (memory_address_length): Likewise. Check mem address space too. + (ix86_print_operand): Use ix86_print_operand_address_as. + (ix86_print_operand_address_as): Rename from + ix86_print_operand_address, add new addr_space_t parameter. + Validate that either the parameter or the ix86_address segment + is default address space. Handle ADDR_SPACE_SEG_TLS. + (ix86_print_operand_address): New. + (ix86_addr_space_subset_p, TARGET_ADDR_SPACE_SUBSET_P): New. + (ix86_addr_space_convert, TARGET_ADDR_SPACE_CONVERT): New. + (ix86_addr_space_debug, TARGET_ADDR_SPACE_DEBUG): New. + (ix86_addr_space_zero_address_valid): New. + (TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID): New. + * config/i386/i386.h (DEFAULT_TLS_SEG_REG): Use addr_space_t constants. + * config/i386/rdos.h (DEFAULT_TLS_SEG_REG): Likewise. + * config/i386/predicates.md (address_no_seg_operand): Likewise. + (vsib_address_operand): Likewise. + (address_mpx_no_base_operand): Likewise. + (address_mpx_no_index_operand): Likewise. + * doc/extend.texi (x86 Named Address Spaces): New section. + * config/i386/i386.c (ix86_check_no_addr_space): New. (decide_alg): Add have_as parameter. (alg_usable_p): Likewise; disable rep algorithms if set. diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index a3c0342950d..e3a301205e6 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -586,6 +586,10 @@ ix86_target_macros (void) ix86_tune, ix86_fpmath, cpp_define); + + cpp_define (parse_in, "__SEG_FS"); + cpp_define (parse_in, "__SEG_GS"); + cpp_define (parse_in, "__SEG_TLS"); } @@ -600,6 +604,10 @@ ix86_register_pragmas (void) /* Update pragma hook to allow parsing #pragma GCC target. */ targetm.target_option.pragma_parse = ix86_pragma_target_parse; + c_register_addr_space ("__seg_fs", ADDR_SPACE_SEG_FS); + c_register_addr_space ("__seg_gs", ADDR_SPACE_SEG_GS); + c_register_addr_space ("__seg_tls", ADDR_SPACE_SEG_TLS); + #ifdef REGISTER_SUBTARGET_PRAGMAS REGISTER_SUBTARGET_PRAGMAS (); #endif diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 5e46833ff3a..026b778f4e3 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -279,12 +279,11 @@ extern rtx maybe_get_pool_constant (rtx); extern char internal_label_prefix[16]; extern int internal_label_prefix_len; -enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS }; struct ix86_address { rtx base, index, disp; HOST_WIDE_INT scale; - enum ix86_address_seg seg; + addr_space_t seg; }; extern int ix86_decompose_address (rtx, struct ix86_address *); @@ -326,3 +325,7 @@ struct ix86_first_cycle_multipass_data_ # define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T \ struct ix86_first_cycle_multipass_data_ #endif /* RTX_CODE */ + +const addr_space_t ADDR_SPACE_SEG_FS = 1; +const addr_space_t ADDR_SPACE_SEG_GS = 2; +const addr_space_t ADDR_SPACE_SEG_TLS = 3; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 159e1d19a10..0d84cde9cbe 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -80,6 +80,7 @@ along with GCC; see the file COPYING3. If not see static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); static rtx legitimize_pe_coff_symbol (rtx, bool); +static void ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t); #ifndef CHECK_STACK_LIMIT #define CHECK_STACK_LIMIT (-1) @@ -13988,7 +13989,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) rtx scale_rtx = NULL_RTX; rtx tmp; int retval = 1; - enum ix86_address_seg seg = SEG_DEFAULT; + addr_space_t seg = ADDR_SPACE_GENERIC; /* Allow zero-extended SImode addresses, they will be emitted with addr32 prefix. */ @@ -14087,7 +14088,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) case UNSPEC: if (XINT (op, 1) == UNSPEC_TP && TARGET_TLS_DIRECT_SEG_REFS - && seg == SEG_DEFAULT) + && seg == ADDR_SPACE_GENERIC) seg = DEFAULT_TLS_SEG_REG; else return 0; @@ -14675,7 +14676,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) struct ix86_address parts; rtx base, index, disp; HOST_WIDE_INT scale; - enum ix86_address_seg seg; + addr_space_t seg; if (ix86_decompose_address (addr, &parts) <= 0) /* Decomposition failed. */ @@ -14721,7 +14722,7 @@ ix86_legitimate_address_p (machine_mode, rtx addr, bool strict) return false; /* Address override works only on the (%reg) part of %fs:(%reg). */ - if (seg != SEG_DEFAULT + if (seg != ADDR_SPACE_GENERIC && ((base && GET_MODE (base) != word_mode) || (index && GET_MODE (index) != word_mode))) return false; @@ -17128,32 +17129,22 @@ ix86_print_operand (FILE *file, rtx x, int code) else if (MEM_P (x)) { - /* No `byte ptr' prefix for call instructions or BLKmode operands. */ - if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P' - && GET_MODE (x) != BLKmode) + rtx addr = XEXP (x, 0); + + /* Avoid (%rip) for call operands. */ + if (code == 'P' && CONSTANT_ADDRESS_P (x) && !CONST_INT_P (x)) { - const char * size; - switch (GET_MODE_SIZE (GET_MODE (x))) - { - case 1: size = "BYTE"; break; - case 2: size = "WORD"; break; - case 4: size = "DWORD"; break; - case 8: size = "QWORD"; break; - case 12: size = "TBYTE"; break; - case 16: - if (GET_MODE (x) == XFmode) - size = "TBYTE"; - else - size = "XMMWORD"; - break; - case 32: size = "YMMWORD"; break; - case 64: size = "ZMMWORD"; break; - default: - gcc_unreachable (); - } + output_addr_const (file, addr); + return; + } - /* Check for explicit size override (codes 'b', 'w', 'k', - 'q' and 'x') */ + /* No `byte ptr' prefix for call instructions ... */ + if (ASSEMBLER_DIALECT == ASM_INTEL && code != 'X' && code != 'P') + { + machine_mode mode = GET_MODE (x); + const char *size; + + /* Check for explicit size override codes. */ if (code == 'b') size = "BYTE"; else if (code == 'w') @@ -17164,20 +17155,39 @@ ix86_print_operand (FILE *file, rtx x, int code) size = "QWORD"; else if (code == 'x') size = "XMMWORD"; - - fputs (size, file); - fputs (" PTR ", file); + else if (mode == BLKmode) + /* ... or BLKmode operands, when not overridden. */ + size = NULL; + else + switch (GET_MODE_SIZE (mode)) + { + case 1: size = "BYTE"; break; + case 2: size = "WORD"; break; + case 4: size = "DWORD"; break; + case 8: size = "QWORD"; break; + case 12: size = "TBYTE"; break; + case 16: + if (mode == XFmode) + size = "TBYTE"; + else + size = "XMMWORD"; + break; + case 32: size = "YMMWORD"; break; + case 64: size = "ZMMWORD"; break; + default: + gcc_unreachable (); + } + if (size) + { + fputs (size, file); + fputs (" PTR ", file); + } } - x = XEXP (x, 0); - /* Avoid (%rip) for call operands. */ - if (CONSTANT_ADDRESS_P (x) && code == 'P' - && !CONST_INT_P (x)) - output_addr_const (file, x); - else if (this_is_asm_operands && ! address_operand (x, VOIDmode)) + if (this_is_asm_operands && ! address_operand (addr, VOIDmode)) output_operand_lossage ("invalid constraints for operand"); else - output_address (x); + ix86_print_operand_address_as (file, addr, MEM_ADDR_SPACE (x)); } else if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode) @@ -17262,7 +17272,7 @@ ix86_print_operand_punct_valid_p (unsigned char code) /* Print a memory operand whose address is ADDR. */ static void -ix86_print_operand_address (FILE *file, rtx addr) +ix86_print_operand_address_as (FILE *file, rtx addr, addr_space_t as) { struct ix86_address parts; rtx base, index, disp; @@ -17315,18 +17325,24 @@ ix86_print_operand_address (FILE *file, rtx addr) disp = parts.disp; scale = parts.scale; - switch (parts.seg) + if (ADDR_SPACE_GENERIC_P (as)) + as = parts.seg; + else + gcc_assert (ADDR_SPACE_GENERIC_P (parts.seg)); + + if (!ADDR_SPACE_GENERIC_P (as)) { - case SEG_DEFAULT: - break; - case SEG_FS: - case SEG_GS: - if (ASSEMBLER_DIALECT == ASM_ATT) - putc ('%', file); - fputs ((parts.seg == SEG_FS ? "fs:" : "gs:"), file); - break; - default: - gcc_unreachable (); + const char *string; + + if (as == ADDR_SPACE_SEG_TLS) + as = DEFAULT_TLS_SEG_REG; + if (as == ADDR_SPACE_SEG_FS) + string = (ASSEMBLER_DIALECT == ASM_ATT ? "%fs:" : "fs:"); + else if (as == ADDR_SPACE_SEG_GS) + string = (ASSEMBLER_DIALECT == ASM_ATT ? "%gs:" : "gs:"); + else + gcc_unreachable (); + fputs (string, file); } /* Use one byte shorter RIP relative addressing for 64bit mode. */ @@ -17350,7 +17366,7 @@ ix86_print_operand_address (FILE *file, rtx addr) if (CONST_INT_P (disp)) { - if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == SEG_DEFAULT) + if (ASSEMBLER_DIALECT == ASM_INTEL && parts.seg == ADDR_SPACE_GENERIC) fputs ("ds:", file); fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (disp)); } @@ -17486,6 +17502,12 @@ ix86_print_operand_address (FILE *file, rtx addr) } } +static void +ix86_print_operand_address (FILE *file, rtx addr) +{ + ix86_print_operand_address_as (file, addr, ADDR_SPACE_GENERIC); +} + /* Implementation of TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ static bool @@ -27136,7 +27158,7 @@ memory_address_length (rtx addr, bool lea) ok = ix86_decompose_address (addr, &parts); gcc_assert (ok); - len = (parts.seg == SEG_DEFAULT) ? 0 : 1; + len = (parts.seg == ADDR_SPACE_GENERIC) ? 0 : 1; /* If this is not LEA instruction, add the length of addr32 prefix. */ if (TARGET_64BIT && !lea @@ -27297,25 +27319,35 @@ ix86_attr_length_address_default (rtx_insn *insn) extract_insn_cached (insn); for (i = recog_data.n_operands - 1; i >= 0; --i) - if (MEM_P (recog_data.operand[i])) - { - constrain_operands_cached (insn, reload_completed); - if (which_alternative != -1) - { - const char *constraints = recog_data.constraints[i]; - int alt = which_alternative; - - while (*constraints == '=' || *constraints == '+') - constraints++; - while (alt-- > 0) - while (*constraints++ != ',') - ; - /* Skip ignored operands. */ - if (*constraints == 'X') - continue; - } - return memory_address_length (XEXP (recog_data.operand[i], 0), false); - } + { + rtx op = recog_data.operand[i]; + if (MEM_P (op)) + { + constrain_operands_cached (insn, reload_completed); + if (which_alternative != -1) + { + const char *constraints = recog_data.constraints[i]; + int alt = which_alternative; + + while (*constraints == '=' || *constraints == '+') + constraints++; + while (alt-- > 0) + while (*constraints++ != ',') + ; + /* Skip ignored operands. */ + if (*constraints == 'X') + continue; + } + + int len = memory_address_length (XEXP (op, 0), false); + + /* Account for segment prefix for non-default addr spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (op))) + len++; + + return len; + } + } return 0; } @@ -53669,6 +53701,78 @@ ix86_operands_ok_for_move_multiple (rtx *operands, bool load, return true; } +/* Address space support. + + This is not "far pointers" in the 16-bit sense, but an easy way + to use %fs and %gs segment prefixes. Therefore: + + (a) All address spaces have the same modes, + (b) All address spaces have the same addresss forms, + (c) While %fs and %gs are technically subsets of the generic + address space, they are probably not subsets of each other. + (d) Since we have no access to the segment base register values + without resorting to a system call, we cannot convert a + non-default address space to a default address space. + Therefore we do not claim %fs or %gs are subsets of generic. + (e) However, __seg_tls uses UNSPEC_TP as the base (which itself is + stored at __seg_tls:0) so we can map between tls and generic. */ + +static bool +ix86_addr_space_subset_p (addr_space_t subset, addr_space_t superset) +{ + return (subset == superset + || (superset == ADDR_SPACE_GENERIC + && subset == ADDR_SPACE_SEG_TLS)); +} +#undef TARGET_ADDR_SPACE_SUBSET_P +#define TARGET_ADDR_SPACE_SUBSET_P ix86_addr_space_subset_p + +static rtx +ix86_addr_space_convert (rtx op, tree from_type, tree to_type) +{ + addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type)); + addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type)); + + /* Conversion between SEG_TLS and GENERIC is handled by adding or + subtracting the thread pointer. */ + if ((from_as == ADDR_SPACE_GENERIC && to_as == ADDR_SPACE_SEG_TLS) + || (from_as == ADDR_SPACE_SEG_TLS && to_as == ADDR_SPACE_GENERIC)) + { + machine_mode mode = GET_MODE (op); + if (mode == VOIDmode) + mode = ptr_mode; + rtx tp = get_thread_pointer (mode, optimize || mode != ptr_mode); + return expand_binop (mode, (to_as == ADDR_SPACE_GENERIC + ? add_optab : sub_optab), + op, tp, NULL, 1, OPTAB_WIDEN); + } + + return op; +} +#undef TARGET_ADDR_SPACE_CONVERT +#define TARGET_ADDR_SPACE_CONVERT ix86_addr_space_convert + +static int +ix86_addr_space_debug (addr_space_t as) +{ + /* Fold __seg_tls to __seg_fs or __seg_gs for debugging. */ + if (as == ADDR_SPACE_SEG_TLS) + as = DEFAULT_TLS_SEG_REG; + return as; +} +#undef TARGET_ADDR_SPACE_DEBUG +#define TARGET_ADDR_SPACE_DEBUG ix86_addr_space_debug + +/* All use of segmentation is assumed to make address 0 valid. */ + +static bool +ix86_addr_space_zero_address_valid (addr_space_t as) +{ + return as != ADDR_SPACE_GENERIC; +} +#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID +#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid + /* Initialize the GCC target structure. */ #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY ix86_return_in_memory diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index be96c75df77..3d5b2b25ced 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -602,7 +602,8 @@ extern tree x86_mfence; #define DEFAULT_ABI SYSV_ABI /* The default TLS segment register used by target. */ -#define DEFAULT_TLS_SEG_REG (TARGET_64BIT ? SEG_FS : SEG_GS) +#define DEFAULT_TLS_SEG_REG \ + (TARGET_64BIT ? ADDR_SPACE_SEG_FS : ADDR_SPACE_SEG_GS) /* Subtargets may reset this to 1 in order to enable 96-bit long double with the rounding mode forced to 53 bits. */ diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 1595142255d..c11f2d7d228 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -974,7 +974,7 @@ ok = ix86_decompose_address (op, &parts); gcc_assert (ok); - return parts.seg == SEG_DEFAULT; + return parts.seg == ADDR_SPACE_GENERIC; }) ;; Return true if op if a valid base register, displacement or @@ -988,7 +988,7 @@ ok = ix86_decompose_address (op, &parts); gcc_assert (ok); - if (parts.index || parts.seg != SEG_DEFAULT) + if (parts.index || parts.seg != ADDR_SPACE_GENERIC) return false; /* VSIB addressing doesn't support (%rip). */ @@ -1032,7 +1032,7 @@ if (parts.index && parts.base) return false; - if (parts.seg != SEG_DEFAULT) + if (parts.seg != ADDR_SPACE_GENERIC) return false; /* Do not support (%rip). */ @@ -1064,7 +1064,7 @@ if (parts.index) return false; - if (parts.seg != SEG_DEFAULT) + if (parts.seg != ADDR_SPACE_GENERIC) return false; /* Do not support (%rip). */ diff --git a/gcc/config/i386/rdos.h b/gcc/config/i386/rdos.h index f9bfe6d02e4..ccf6b78824a 100644 --- a/gcc/config/i386/rdos.h +++ b/gcc/config/i386/rdos.h @@ -25,7 +25,7 @@ along with GCC; see the file COPYING3. If not see #define TARGET_TLS_DIRECT_SEG_REFS_DEFAULT MASK_TLS_DIRECT_SEG_REFS #undef DEFAULT_TLS_SEG_REG -#define DEFAULT_TLS_SEG_REG SEG_GS +#define DEFAULT_TLS_SEG_REG ADDR_SPACE_SEG_GS #undef TARGET_RDOS #define TARGET_RDOS 1 diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 08d442018eb..aab6bad905c 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1261,8 +1261,8 @@ As an extension, GNU C supports named address spaces as defined in the N1275 draft of ISO/IEC DTR 18037. Support for named address spaces in GCC will evolve as the draft technical report changes. Calling conventions for any target might also change. At -present, only the AVR, SPU, M32C, and RL78 targets support address -spaces other than the generic address space. +present, only the AVR, SPU, M32C, RL78, and x86 targets support +address spaces other than the generic address space. Address space identifiers may be used exactly like any other C type qualifier (e.g., @code{const} or @code{volatile}). See the N1275 @@ -1451,6 +1451,49 @@ It may use runtime library support, or generate special machine instructions to access that address space. +@subsection x86 Named Address Spaces +@cindex x86 named address spaces + +On the x86 target, variables may be declared as being relative +to the @code{%fs} or @code{%gs} segments. + +@table @code +@item __seg_fs +@itemx __seg_gs +@cindex @code{__seg_fs} x86 named address space +@cindex @code{__seg_gs} x86 named address space +The object is accessed with the respective segment override prefix. + +The respective segment base must be set via some method specific to +the operating system. Rather than require an expensive system call +to retrieve the segment base, these address spaces are not considered +to be subspaces of the generic (flat) address space. This means that +explicit casts are required to convert pointers between these address +spaces and the generic address space. In practice the application +should cast to @code{uintptr_t} and apply the segment base offset +that it installed previously. + +The preprocessor symbols @code{__SEG_FS} and @code{__SEG_GS} are +defined when these address spaces are supported. + +@item __seg_tls +@cindex @code{__seg_tls} x86 named address space +Some operating systems define either the @code{%fs} or @code{%gs} +segment as the thread-local storage base for each thread. Objects +within this address space are accessed with the appropriate +segment override prefix. + +The pointer located at address 0 within the segment contains the +offset of the segment within the generic address space. Thus this +address space is considered a subspace of the generic address space, +and the known segment offset is applied when converting addresses +to and from the generic address space. + +The preprocessor symbol @code{__SEG_TLS} is defined when this +address space is supported. + +@end table + @node Zero Length @section Arrays of Length Zero @cindex arrays of length zero diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f8c5d5ab7a3..c6fe2972e2d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-11-09 Richard Henderson + + * gcc.target/i386/addr-space-1.c: New test. + * gcc.target/i386/addr-space-2.c: New test. + * gcc.target/i386/addr-space-3.c: New test. + 2015-11-08 Steven g. Kargl PR fortran/68053 diff --git a/gcc/testsuite/gcc.target/i386/addr-space-1.c b/gcc/testsuite/gcc.target/i386/addr-space-1.c new file mode 100644 index 00000000000..1e1314760e2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/addr-space-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "movl\[ \t\]%gs:\\((%eax|%rax)\\), %eax" } } */ + +extern __seg_gs int *call_me (void); + +int +read_seg_gs (void) +{ + return *call_me(); +} diff --git a/gcc/testsuite/gcc.target/i386/addr-space-2.c b/gcc/testsuite/gcc.target/i386/addr-space-2.c new file mode 100644 index 00000000000..d5c24b61096 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/addr-space-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler "fs:16" } } */ +/* { dg-final { scan-assembler "gs:16" } } */ + +int test(void) +{ + int __seg_fs *f = (int __seg_fs *)16; + int __seg_gs *g = (int __seg_gs *)16; + return *f + *g; +} diff --git a/gcc/testsuite/gcc.target/i386/addr-space-3.c b/gcc/testsuite/gcc.target/i386/addr-space-3.c new file mode 100644 index 00000000000..63f1f031a08 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/addr-space-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler "[fg]s:0" } } */ + +void test(int *y) +{ + int *x = (int __seg_tls *)0; + if (x == y) + asm(""); +} -- 2.30.2