Attached patch generates memory reference to a stack protector guard value in a TLS block, using the correct address space. This reduces number of stack protector patterns, since universal patterns are now able to handle all memory references to stack protector guard value (global or from TLS block).
2017-08-06 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.c (ix86_stack_protect_guard): Generate memory reference to a SSP offset in TLS address space. (ix86_print_operand) <case '@'>: Remove. (ix86_print_operand_punct_valid_p): Remove '@' code. * config/i386/i386.md (stack_tls_protect_set_<mode>): Remove. (stack_protect_set): Do not call gen_stack_tls_protect_set_<mode>. (stack_tls_protect_test_<mode>): Remove. (stack_protect_test): Do not call gen_stack_tls_protect_test_<mode>. I'll leave patch here for a couple of days for eventual comments. Hopefully, the memory reference is constructed in the right way. A follow-up patch will add something like rs6000's -mstack-protector-guard-offset= option to resolve PR 81708 [1]. [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81708 Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 250900) +++ config/i386/i386.c (working copy) @@ -18624,7 +18624,6 @@ print_reg (rtx x, int code, FILE *file) + -- print a branch hint as 'cs' or 'ds' prefix ; -- print a semicolon (after prefixes due to bug in older gas). ~ -- print "i" if TARGET_AVX2, "f" otherwise. - @ -- print a segment register of thread base pointer load ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode ! -- print MPX prefix for jxx/call/ret instructions if required. */ @@ -19168,19 +19167,6 @@ ix86_print_operand (FILE *file, rtx x, int code) #endif return; - case '@': - if (ASSEMBLER_DIALECT == ASM_ATT) - putc ('%', file); - - /* The kernel uses a different segment register for performance - reasons; a system call would not have to trash the userspace - segment register, which would be expensive. */ - if (TARGET_64BIT && ix86_cmodel != CM_KERNEL) - fputs ("fs", file); - else - fputs ("gs", file); - return; - case '~': putc (TARGET_AVX2 ? 'i' : 'f', file); return; @@ -19339,8 +19325,8 @@ ix86_print_operand (FILE *file, rtx x, int code) static bool ix86_print_operand_punct_valid_p (unsigned char code) { - return (code == '@' || code == '*' || code == '+' || code == '&' - || code == ';' || code == '~' || code == '^' || code == '!'); + return (code == '*' || code == '+' || code == '&' || code == ';' + || code == '~' || code == '^' || code == '!'); } /* Print a memory operand whose address is ADDR. */ @@ -45805,13 +45791,31 @@ ix86_mangle_type (const_tree type) } #ifdef TARGET_THREAD_SSP_OFFSET -/* If using TLS guards, don't waste time creating and expanding - __stack_chk_guard decl and MEM as we are going to ignore it. */ static tree ix86_stack_protect_guard (void) { if (TARGET_SSP_TLS_GUARD) - return NULL_TREE; + { + tree type_node = lang_hooks.types.type_for_mode (ptr_mode, 1); + addr_space_t as = DEFAULT_TLS_SEG_REG; + + /* The kernel uses a different segment register for performance + reasons; a system call would not have to trash the userspace + segment register, which would be expensive. */ + if (ix86_cmodel == CM_KERNEL) + as = ADDR_SPACE_SEG_GS; + + int qual = ENCODE_QUAL_ADDR_SPACE (as); + + tree type = build_qualified_type (type_node, qual); + tree asptrtype = build_pointer_type (type); + tree sspoff = build_int_cst (asptrtype, TARGET_THREAD_SSP_OFFSET); + + tree t = build2 (MEM_REF, asptrtype, sspoff, + build_int_cst (asptrtype, 0)); + return t; + } + return default_stack_protect_guard (); } #endif Index: config/i386/i386.md =================================================================== --- config/i386/i386.md (revision 250900) +++ config/i386/i386.md (working copy) @@ -61,7 +61,6 @@ ;; + -- print a branch hint as 'cs' or 'ds' prefix ;; ; -- print a semicolon (after prefixes due to bug in older gas). ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise. -;; @ -- print a segment register of thread base pointer load ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode ;; ! -- print MPX prefix for jxx/call/ret instructions if required. @@ -18718,16 +18717,9 @@ { rtx (*insn)(rtx, rtx); -#ifdef TARGET_THREAD_SSP_OFFSET - operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); insn = (TARGET_LP64 - ? gen_stack_tls_protect_set_di - : gen_stack_tls_protect_set_si); -#else - insn = (TARGET_LP64 ? gen_stack_protect_set_di : gen_stack_protect_set_si); -#endif emit_insn (insn (operands[0], operands[1])); DONE; @@ -18743,16 +18735,6 @@ "mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_set_<mode>" - [(set (match_operand:PTR 0 "memory_operand" "=m") - (unspec:PTR [(match_operand:PTR 1 "const_int_operand" "i")] - UNSPEC_SP_TLS_SET)) - (set (match_scratch:PTR 2 "=&r") (const_int 0)) - (clobber (reg:CC FLAGS_REG))] - "" - "mov{<imodesuffix>}\t{%@:%P1, %2|%2, <iptrsize> PTR %@:%P1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" - [(set_attr "type" "multi")]) - (define_expand "stack_protect_test" [(match_operand 0 "memory_operand") (match_operand 1 "memory_operand") @@ -18763,16 +18745,9 @@ rtx (*insn)(rtx, rtx, rtx); -#ifdef TARGET_THREAD_SSP_OFFSET - operands[1] = GEN_INT (TARGET_THREAD_SSP_OFFSET); insn = (TARGET_LP64 - ? gen_stack_tls_protect_test_di - : gen_stack_tls_protect_test_si); -#else - insn = (TARGET_LP64 ? gen_stack_protect_test_di : gen_stack_protect_test_si); -#endif emit_insn (insn (flags, operands[0], operands[1])); @@ -18791,16 +18766,6 @@ "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%2, %3|%3, %2}" [(set_attr "type" "multi")]) -(define_insn "stack_tls_protect_test_<mode>" - [(set (match_operand:CCZ 0 "flags_reg_operand") - (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m") - (match_operand:PTR 2 "const_int_operand" "i")] - UNSPEC_SP_TLS_TEST)) - (clobber (match_scratch:PTR 3 "=r"))] - "" - "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;xor{<imodesuffix>}\t{%@:%P2, %3|%3, <iptrsize> PTR %@:%P2}" - [(set_attr "type" "multi")]) - (define_insn "sse4_2_crc32<mode>" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI