x86: Add -m[no-]direct-extern-access
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 19 Jun 2021 12:12:48 +0000 (05:12 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 9 Feb 2022 12:38:54 +0000 (04:38 -0800)
Add -m[no-]direct-extern-access and nodirect_extern_access attribute.
-mdirect-extern-access is the default.  With nodirect_extern_access
attribute, GOT is always used to access undefined data and function
symbols with nodirect_extern_access attribute, including in PIE and
non-PIE.  With -mno-direct-extern-access:

1. Always use GOT to access undefined data and function symbols,
   including in PIE and non-PIE.  These will avoid copy relocations
   in executables.  This is compatible with existing executables and
   shared libraries.
2. In executable and shared library, bind symbols with the STV_PROTECTED
   visibility locally:
   a. The address of data symbol is the address of data body.
   b. For systems without function descriptor, the function pointer is
      the address of function body.
   c. The resulting shared libraries may not be incompatible with
      executables which have copy relocations on protected symbols or
      use executable PLT entries as function addresses for protected
      functions in shared libraries.
3. Update asm_preferred_eh_data_format to select PC relative EH encoding
format with -mno-direct-extern-access to avoid copy relocation.
4. Add ix86_reloc_rw_mask for TARGET_ASM_RELOC_RW_MASK to avoid copy
relocation with -mno-direct-extern-access.

gcc/

PR target/35513
PR target/100593
* config/i386/gnu-property.cc: Include "i386-protos.h".
(file_end_indicate_exec_stack_and_gnu_property): Generate
a GNU_PROPERTY_1_NEEDED note for -mno-direct-extern-access or
nodirect_extern_access attribute.
* config/i386/i386-options.cc
(handle_nodirect_extern_access_attribute): New function.
(ix86_attribute_table): Add nodirect_extern_access attribute.
* config/i386/i386-protos.h (ix86_force_load_from_GOT_p): Add a
bool argument.
(ix86_has_no_direct_extern_access): New.
* config/i386/i386.cc (ix86_has_no_direct_extern_access): New.
(ix86_force_load_from_GOT_p): Add a bool argument to indicate
call operand.  Force non-call load from GOT for
-mno-direct-extern-access or nodirect_extern_access attribute.
(legitimate_pic_address_disp_p): Avoid copy relocation in PIE
for -mno-direct-extern-access or nodirect_extern_access attribute.
(ix86_print_operand): Pass true to ix86_force_load_from_GOT_p
for call operand.
(asm_preferred_eh_data_format): Use PC-relative format for
-mno-direct-extern-access to avoid copy relocation.  Check
ptr_mode instead of TARGET_64BIT when selecting DW_EH_PE_sdata4.
(ix86_binds_local_p): Set ix86_has_no_direct_extern_access to
true for -mno-direct-extern-access or nodirect_extern_access
attribute.  Don't treat protected data as extern and avoid copy
relocation on common symbol with -mno-direct-extern-access or
nodirect_extern_access attribute.
(ix86_reloc_rw_mask): New to avoid copy relocation for
-mno-direct-extern-access.
(TARGET_ASM_RELOC_RW_MASK): New.
* config/i386/i386.opt: Add -mdirect-extern-access.
* doc/extend.texi: Document nodirect_extern_access attribute.
* doc/invoke.texi: Document -m[no-]direct-extern-access.

gcc/testsuite/

PR target/35513
PR target/100593
* g++.target/i386/pr35513-1.C: New file.
* g++.target/i386/pr35513-2.C: Likewise.
* gcc.target/i386/pr35513-1a.c: Likewise.
* gcc.target/i386/pr35513-1b.c: Likewise.
* gcc.target/i386/pr35513-2a.c: Likewise.
* gcc.target/i386/pr35513-2b.c: Likewise.
* gcc.target/i386/pr35513-3a.c: Likewise.
* gcc.target/i386/pr35513-3b.c: Likewise.
* gcc.target/i386/pr35513-4a.c: Likewise.
* gcc.target/i386/pr35513-4b.c: Likewise.
* gcc.target/i386/pr35513-5a.c: Likewise.
* gcc.target/i386/pr35513-5b.c: Likewise.
* gcc.target/i386/pr35513-6a.c: Likewise.
* gcc.target/i386/pr35513-6b.c: Likewise.
* gcc.target/i386/pr35513-7a.c: Likewise.
* gcc.target/i386/pr35513-7b.c: Likewise.
* gcc.target/i386/pr35513-8.c: Likewise.
* gcc.target/i386/pr35513-9a.c: Likewise.
* gcc.target/i386/pr35513-9b.c: Likewise.
* gcc.target/i386/pr35513-10a.c: Likewise.
* gcc.target/i386/pr35513-10b.c: Likewise.
* gcc.target/i386/pr35513-11a.c: Likewise.
* gcc.target/i386/pr35513-11b.c: Likewise.
* gcc.target/i386/pr35513-12a.c: Likewise.
* gcc.target/i386/pr35513-12b.c: Likewise.

32 files changed:
gcc/config/i386/gnu-property.cc
gcc/config/i386/i386-options.cc
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.cc
gcc/config/i386/i386.opt
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/g++.target/i386/pr35513-1.C [new file with mode: 0644]
gcc/testsuite/g++.target/i386/pr35513-2.C [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-10a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-10b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-11a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-11b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-12a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-12b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-1a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-1b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-2a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-2b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-3a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-3b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-4a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-4b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-5a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-5b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-6a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-6b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-7a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-7b.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-9a.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr35513-9b.c [new file with mode: 0644]

index f08984f32a10ecd17802cb53f30c0b679de55e68..ea63c1ec58c19bfb5f189ad7687a2c92c800c3ad 100644 (file)
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "output.h"
 #include "linux-common.h"
+#include "i386-protos.h"
 
 static void
 emit_gnu_property (unsigned int type, unsigned int data)
@@ -60,7 +61,9 @@ file_end_indicate_exec_stack_and_gnu_property (void)
 {
   file_end_indicate_exec_stack ();
 
-  if (flag_cf_protection == CF_NONE && !ix86_needed)
+  if (flag_cf_protection == CF_NONE
+      && !ix86_needed
+      && !ix86_has_no_direct_extern_access)
     return;
 
   unsigned int feature_1 = 0;
@@ -121,4 +124,9 @@ file_end_indicate_exec_stack_and_gnu_property (void)
   /* Generate GNU_PROPERTY_X86_ISA_1_NEEDED.  */
   if (isa_1)
     emit_gnu_property (0xc0008002, isa_1);
+
+  if (ix86_has_no_direct_extern_access)
+    /* Emite a GNU_PROPERTY_1_NEEDED note with
+       GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.  */
+    emit_gnu_property (0xb0008000, (1U << 0));
 }
index 082abd2c948cc873e520cae032851a1f0cd162f6..805539364108eee07f5bda527acd6f39f3f7bf95 100644 (file)
@@ -3775,6 +3775,36 @@ ix86_handle_fentry_name (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 
+/* Handle a "nodirect_extern_access" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_nodirect_extern_access_attribute (tree *pnode, tree name,
+                                        tree ARG_UNUSED (args),
+                                        int ARG_UNUSED (flags),
+                                        bool *no_add_attrs)
+{
+  tree node = *pnode;
+
+  if (VAR_OR_FUNCTION_DECL_P (node))
+    {
+      if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
+          && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
+       {
+         warning (OPT_Wattributes,
+                  "%qE attribute have effect only on public objects", name);
+         *no_add_attrs = true;
+       }
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Table of valid machine attributes.  */
 const struct attribute_spec ix86_attribute_table[] =
 {
@@ -3855,6 +3885,8 @@ const struct attribute_spec ix86_attribute_table[] =
     ix86_handle_fentry_name, NULL },
   { "cf_check", 0, 0, true, false, false, false,
     ix86_handle_fndecl_attribute, NULL },
+  { "nodirect_extern_access", 0, 0, true, false, false, false,
+    handle_nodirect_extern_access_attribute, NULL },
 
   /* End element.  */
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
index 6b3c9516a7f44b0e416fefad567791f19304ae14..b7e9aa75d25421063b53bac73fa236de1ac7e9ec 100644 (file)
@@ -79,7 +79,7 @@ extern bool ix86_expand_cmpstrn_or_cmpmem (rtx, rtx, rtx, rtx, rtx, bool);
 extern bool constant_address_p (rtx);
 extern bool legitimate_pic_operand_p (rtx);
 extern bool legitimate_pic_address_disp_p (rtx);
-extern bool ix86_force_load_from_GOT_p (rtx);
+extern bool ix86_force_load_from_GOT_p (rtx, bool = false);
 extern void print_reg (rtx, int, FILE*);
 extern void ix86_print_operand (FILE *, rtx, int);
 
@@ -401,3 +401,5 @@ extern rtl_opt_pass *make_pass_insert_endbr_and_patchable_area
   (gcc::context *);
 extern rtl_opt_pass *make_pass_remove_partial_avx_dependency
   (gcc::context *);
+
+extern bool ix86_has_no_direct_extern_access;
index db5e1681e980ca936d5240f2ffef406c3acd6778..6b97a2b0e5026af1d7e3adb7768ce801a00bdf81 100644 (file)
@@ -363,6 +363,9 @@ unsigned int ix86_default_incoming_stack_boundary;
 /* Alignment for incoming stack boundary in bits.  */
 unsigned int ix86_incoming_stack_boundary;
 
+/* True if there is no direct access to extern symbols.  */
+bool ix86_has_no_direct_extern_access;
+
 /* Calling abi specific va_list type nodes.  */
 tree sysv_va_list_type_node;
 tree ms_va_list_type_node;
@@ -10514,13 +10517,17 @@ darwin_local_data_pic (rtx disp)
 }
 
 /* True if the function symbol operand X should be loaded from GOT.
+   If CALL_P is true, X is a call operand.
+
+   NB: -mno-direct-extern-access doesn't force load from GOT for
+   call.
 
    NB: In 32-bit mode, only non-PIC is allowed in inline assembly
    statements, since a PIC register could not be available at the
    call site.  */
 
 bool
-ix86_force_load_from_GOT_p (rtx x)
+ix86_force_load_from_GOT_p (rtx x, bool call_p)
 {
   return ((TARGET_64BIT || (!flag_pic && HAVE_AS_IX86_GOT32X))
          && !TARGET_PECOFF && !TARGET_MACHO
@@ -10528,11 +10535,16 @@ ix86_force_load_from_GOT_p (rtx x)
          && ix86_cmodel != CM_LARGE
          && ix86_cmodel != CM_LARGE_PIC
          && GET_CODE (x) == SYMBOL_REF
-         && SYMBOL_REF_FUNCTION_P (x)
-         && (!flag_plt
-             || (SYMBOL_REF_DECL (x)
-                 && lookup_attribute ("noplt",
-                                      DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))
+         && ((!call_p
+              && (!ix86_direct_extern_access
+                  || (SYMBOL_REF_DECL (x)
+                      && lookup_attribute ("nodirect_extern_access",
+                                           DECL_ATTRIBUTES (SYMBOL_REF_DECL (x))))))
+             || (SYMBOL_REF_FUNCTION_P (x)
+                 && (!flag_plt
+                     || (SYMBOL_REF_DECL (x)
+                         && lookup_attribute ("noplt",
+                                              DECL_ATTRIBUTES (SYMBOL_REF_DECL (x)))))))
          && !SYMBOL_REF_LOCAL_P (x));
 }
 
@@ -10799,7 +10811,11 @@ legitimate_pic_address_disp_p (rtx disp)
            }
          else if (!SYMBOL_REF_FAR_ADDR_P (op0)
                   && (SYMBOL_REF_LOCAL_P (op0)
-                      || (HAVE_LD_PIE_COPYRELOC
+                      || ((ix86_direct_extern_access
+                           && !(SYMBOL_REF_DECL (op0)
+                                && lookup_attribute ("nodirect_extern_access",
+                                                     DECL_ATTRIBUTES (SYMBOL_REF_DECL (op0)))))
+                          && HAVE_LD_PIE_COPYRELOC
                           && flag_pie
                           && !SYMBOL_REF_WEAK (op0)
                           && !SYMBOL_REF_FUNCTION_P (op0)))
@@ -13755,7 +13771,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
 
       if (code == 'P')
        {
-         if (ix86_force_load_from_GOT_p (x))
+         if (ix86_force_load_from_GOT_p (x, true))
            {
              /* For inline assembly statement, load function address
                 from GOT with 'P' operand modifier to avoid PLT.  */
@@ -22536,10 +22552,10 @@ int
 asm_preferred_eh_data_format (int code, int global)
 {
   /* PE-COFF is effectively always -fPIC because of the .reloc section.  */
-  if (flag_pic || TARGET_PECOFF)
+  if (flag_pic || TARGET_PECOFF || !ix86_direct_extern_access)
     {
       int type = DW_EH_PE_sdata8;
-      if (!TARGET_64BIT
+      if (ptr_mode == SImode
          || ix86_cmodel == CM_SMALL_PIC
          || (ix86_cmodel == CM_MEDIUM_PIC && (global || code)))
        type = DW_EH_PE_sdata4;
@@ -23629,10 +23645,28 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
 static bool
 ix86_binds_local_p (const_tree exp)
 {
-  return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
-                                 (!flag_pic
-                                  || (TARGET_64BIT
-                                      && HAVE_LD_PIE_COPYRELOC != 0)));
+  bool direct_extern_access
+    = (ix86_direct_extern_access
+       && !(VAR_OR_FUNCTION_DECL_P (exp)
+           && lookup_attribute ("nodirect_extern_access",
+                                DECL_ATTRIBUTES (exp))));
+  if (!direct_extern_access)
+    ix86_has_no_direct_extern_access = true;
+  return default_binds_local_p_3 (exp, flag_shlib != 0, true,
+                                 direct_extern_access,
+                                 (direct_extern_access
+                                  && (!flag_pic
+                                      || (TARGET_64BIT
+                                          && HAVE_LD_PIE_COPYRELOC != 0))));
+}
+
+/* If flag_pic or ix86_direct_extern_access is false, then neither
+   local nor global relocs should be placed in readonly memory.  */
+
+static int
+ix86_reloc_rw_mask (void)
+{
+  return (flag_pic || !ix86_direct_extern_access) ? 3 : 0;
 }
 #endif
 
@@ -24697,6 +24731,11 @@ ix86_libgcc_floating_mode_supported_p
 #undef TARGET_IFUNC_REF_LOCAL_OK
 #define TARGET_IFUNC_REF_LOCAL_OK hook_bool_void_true
 
+#if !TARGET_MACHO && !TARGET_DLLIMPORT_DECL_ATTRIBUTES
+# undef TARGET_ASM_RELOC_RW_MASK
+# define TARGET_ASM_RELOC_RW_MASK ix86_reloc_rw_mask
+#endif
+
 static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED)
 {
 #ifdef OPTION_GLIBC
index eb829d13d407dd85908eb5e81d797175d8badd04..d8e8656a8ab85ae384570cd006d7150a89194fe6 100644 (file)
@@ -1206,3 +1206,7 @@ Support MWAIT and MONITOR built-in functions and code generation.
 mavx512fp16
 Target Mask(ISA2_AVX512FP16) Var(ix86_isa_flags2) Save
 Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and AVX512FP16 built-in functions and code generation.
+
+mdirect-extern-access
+Target Var(ix86_direct_extern_access) Init(1)
+Do not use GOT to access external symbols.
index cb1b2b98ca8524fd826bcc185dec74920ec5f66c..0dc752e8aadd526f4b5f1c34be97d6af441f52f7 100644 (file)
@@ -7220,6 +7220,12 @@ On x86 targets, the @code{fentry_section} attribute sets the name
 of the section to record function entry instrumentation calls in when
 enabled with @option{-pg -mrecord-mcount}
 
+@item nodirect_extern_access
+@cindex @code{nodirect_extern_access} function attribute
+@opindex mno-direct-extern-access
+This attribute, attached to a global variable or function, is the
+counterpart to option @option{-mno-direct-extern-access}.
+
 @end table
 
 @node Xstormy16 Function Attributes
index ac97247c2baca4fe00a4e93b0fbcd086a78daefe..b49ba22df89e49fd244bdc3695d2d29fdbbb90c3 100644 (file)
@@ -1437,7 +1437,7 @@ See RS/6000 and PowerPC Options.
 -mgeneral-regs-only  -mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop @gol
 -mindirect-branch=@var{choice}  -mfunction-return=@var{choice} @gol
 -mindirect-branch-register -mharden-sls=@var{choice} @gol
--mindirect-branch-cs-prefix -mneeded}
+-mindirect-branch-cs-prefix -mneeded -mno-direct-extern-access}
 
 @emph{x86 Windows Options}
 @gccoptlist{-mconsole  -mcygwin  -mno-cygwin  -mdll @gol
@@ -32809,6 +32809,19 @@ x32 environments.
 @opindex mneeded
 Emit GNU_PROPERTY_X86_ISA_1_NEEDED GNU property for Linux target to
 indicate the micro-architecture ISA level required to execute the binary.
+
+@item -mno-direct-extern-access
+@opindex mno-direct-extern-access
+@opindex mdirect-extern-access
+Without @option{-fpic} nor @option{-fPIC}, always use the GOT pointer
+to access external symbols.  With @option{-fpic} or @option{-fPIC},
+treat access to protected symbols as local symbols.  The default is
+@option{-mdirect-extern-access}.
+
+@strong{Warning:} shared libraries compiled with
+@option{-mno-direct-extern-access} and executable compiled with
+@option{-mdirect-extern-access} may not be binary compatible if
+protected symbols are used in shared libraries and executable.
 @end table
 
 @node x86 Windows Options
diff --git a/gcc/testsuite/g++.target/i386/pr35513-1.C b/gcc/testsuite/g++.target/i386/pr35513-1.C
new file mode 100644 (file)
index 0000000..6f8db37
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do run }
+// { dg-options "-O2 -mno-direct-extern-access" }
+
+#include <iostream>
+
+class Bug
+{
+};
+
+int throw_bug()
+{
+  throw Bug();
+
+  return 0;
+}
+
+int main()
+{
+  try {
+      std::cout << throw_bug();
+  } catch (Bug bug) {
+  };
+
+  return 0;
+}
diff --git a/gcc/testsuite/g++.target/i386/pr35513-2.C b/gcc/testsuite/g++.target/i386/pr35513-2.C
new file mode 100644 (file)
index 0000000..9143ff3
--- /dev/null
@@ -0,0 +1,53 @@
+// { dg-do run  }
+// { dg-options "-O2 -mno-direct-extern-access" }
+
+class Foo 
+{
+public:
+  Foo(int n) : n_(n) { }
+  int f() { return n_; }
+
+  int badTest();
+  int goodTest();
+
+private:
+
+  int n_;
+};
+
+int Foo::badTest()
+{
+  try {
+      throw int(99);
+  }
+
+  catch (int &i) {
+      n_ = 16;
+  }
+
+  return n_;
+}
+
+
+int Foo::goodTest()
+{
+  int  n;
+
+  try {
+      throw int(99);
+  }
+
+  catch (int &i) {
+      n = 16;
+  }
+
+  return n_;
+}
+
+int main() 
+{
+  Foo foo(5);
+  foo.goodTest();
+  foo.badTest();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-10a.c b/gcc/testsuite/gcc.target/i386/pr35513-10a.c
new file mode 100644 (file)
index 0000000..d7b5c98
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
+
+/* Weak common symbol with -fpic.  */
+__attribute__((weak, visibility("protected")))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-10b.c b/gcc/testsuite/gcc.target/i386/pr35513-10b.c
new file mode 100644 (file)
index 0000000..a40692e
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
+
+/* Weak common symbol with -fpic.  */
+__attribute__((weak, visibility("protected"),nodirect_extern_access))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-11a.c b/gcc/testsuite/gcc.target/i386/pr35513-11a.c
new file mode 100644 (file)
index 0000000..5489f1e
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
+
+/* Initialized symbol with -fpic.  */
+__attribute__((visibility("protected")))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-11b.c b/gcc/testsuite/gcc.target/i386/pr35513-11b.c
new file mode 100644 (file)
index 0000000..2704900
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
+
+/* Initialized symbol with -fpic.  */
+__attribute__((visibility("protected"), nodirect_extern_access))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-12a.c b/gcc/testsuite/gcc.target/i386/pr35513-12a.c
new file mode 100644 (file)
index 0000000..8b3123f
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
+
+/* Weak initialized symbol with -fpic.  */
+__attribute__((weak, visibility("protected")))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-12b.c b/gcc/testsuite/gcc.target/i386/pr35513-12b.c
new file mode 100644 (file)
index 0000000..a1b6b9e
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
+
+/* Weak initialized symbol with -fpic.  */
+__attribute__((weak, visibility("protected"), nodirect_extern_access))
+int xxx = -1;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-1a.c b/gcc/testsuite/gcc.target/i386/pr35513-1a.c
new file mode 100644 (file)
index 0000000..9725424
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -mno-direct-extern-access" } */
+
+extern void bar (void);
+extern void *p;
+
+void
+foo (void)
+{
+  p = &bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-1b.c b/gcc/testsuite/gcc.target/i386/pr35513-1b.c
new file mode 100644 (file)
index 0000000..54a579a
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -mdirect-extern-access" } */
+
+extern void bar (void) __attribute__ ((nodirect_extern_access));
+extern void *p;
+
+void
+foo (void)
+{
+  p = &bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-2a.c b/gcc/testsuite/gcc.target/i386/pr35513-2a.c
new file mode 100644 (file)
index 0000000..74fa8fc
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -mno-direct-extern-access" } */
+
+extern int bar;
+
+int
+foo (void)
+{
+  return bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-2b.c b/gcc/testsuite/gcc.target/i386/pr35513-2b.c
new file mode 100644 (file)
index 0000000..ae2edff
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fno-pic -mdirect-extern-access" } */
+
+extern int bar __attribute__ ((nodirect_extern_access));
+
+int
+foo (void)
+{
+  return bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-3a.c b/gcc/testsuite/gcc.target/i386/pr35513-3a.c
new file mode 100644 (file)
index 0000000..4ca4332
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie -mno-direct-extern-access" } */
+
+extern int bar;
+
+int
+foo (void)
+{
+  return bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-3b.c b/gcc/testsuite/gcc.target/i386/pr35513-3b.c
new file mode 100644 (file)
index 0000000..c388803
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpie -mdirect-extern-access" } */
+
+extern int bar __attribute__ ((nodirect_extern_access));
+
+int
+foo (void)
+{
+  return bar;
+}
+
+/* { dg-final { scan-assembler "mov\(l|q\)\[ \t\]*bar@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]*bar@GOT" { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "mov\(l|q\)\[ \t\]*\\\$bar," { target { ia32 && got32x_reloc } } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-4a.c b/gcc/testsuite/gcc.target/i386/pr35513-4a.c
new file mode 100644 (file)
index 0000000..9c3a199
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fno-pic -mno-direct-extern-access" } */
+
+extern void foo (void);
+
+int
+bar (void)
+{
+  foo ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*foo" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-4b.c b/gcc/testsuite/gcc.target/i386/pr35513-4b.c
new file mode 100644 (file)
index 0000000..e1a5078
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fno-pic -mdirect-extern-access" } */
+
+extern void foo (void) __attribute__ ((nodirect_extern_access));
+
+int
+bar (void)
+{
+  foo ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*foo" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-5a.c b/gcc/testsuite/gcc.target/i386/pr35513-5a.c
new file mode 100644 (file)
index 0000000..4d2e173
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fpic -mno-direct-extern-access" } */
+
+extern void foo (void);
+
+int
+bar (void)
+{
+  foo ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-5b.c b/gcc/testsuite/gcc.target/i386/pr35513-5b.c
new file mode 100644 (file)
index 0000000..81e98ed
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fpic -mdirect-extern-access" } */
+
+extern void foo (void) __attribute__ ((nodirect_extern_access));
+
+int
+bar (void)
+{
+  foo ();
+  return 0;
+}
+
+/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-6a.c b/gcc/testsuite/gcc.target/i386/pr35513-6a.c
new file mode 100644 (file)
index 0000000..ece878e
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fno-pic -mno-direct-extern-access" } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+  foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*foo" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-6b.c b/gcc/testsuite/gcc.target/i386/pr35513-6b.c
new file mode 100644 (file)
index 0000000..3f679de
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fno-pic -mdirect-extern-access" } */
+
+extern void foo (void) __attribute__ ((nodirect_extern_access));
+
+void
+bar (void)
+{
+  foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*foo" } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-7a.c b/gcc/testsuite/gcc.target/i386/pr35513-7a.c
new file mode 100644 (file)
index 0000000..1de014d
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fpic -mno-direct-extern-access" } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+  foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*foo@PLT" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-7b.c b/gcc/testsuite/gcc.target/i386/pr35513-7b.c
new file mode 100644 (file)
index 0000000..984e2dc
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fplt -fpic -mdirect-extern-access" } */
+
+extern void foo (void) __attribute__ ((nodirect_extern_access));
+
+void
+bar (void)
+{
+  foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]*foo@PLT" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "call\[ \t\]*foo@PLT" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "foo@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "foo@GOT" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-8.c b/gcc/testsuite/gcc.target/i386/pr35513-8.c
new file mode 100644 (file)
index 0000000..7ba67de
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do assemble { target { *-*-linux* && { ! ia32 } } } } */
+/* { dg-require-effective-target maybe_x32 } */
+/* { dg-options "-mx32 -O2 -fno-pic -fexceptions -fasynchronous-unwind-tables -mno-direct-extern-access" } */
+
+extern int foo (int);
+extern void exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));
+struct __pthread_cleanup_frame
+{
+  void (*__cancel_routine) (void *);
+  void *__cancel_arg;
+  int __do_it;
+  int __cancel_type;
+};
+extern __inline void
+__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
+{
+  if (__frame->__do_it)
+    __frame->__cancel_routine (__frame->__cancel_arg);
+}
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+void *
+tf_usleep (void *arg)
+{
+
+  do { struct __pthread_cleanup_frame __clframe __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) = { .__cancel_routine = (cl), .__cancel_arg = (
+                                                                                                                                                        ((void *)0)), .__do_it = 1 };;
+
+    foo (arg == ((void *)0) ? (0x7fffffffL * 2UL + 1UL) : 0);
+
+    __clframe.__do_it = (0); } while (0);
+
+  exit (1);
+}
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-9a.c b/gcc/testsuite/gcc.target/i386/pr35513-9a.c
new file mode 100644 (file)
index 0000000..533f1d2
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mno-direct-extern-access" } */
+
+/* Common symbol with -fpic.  */
+__attribute__((visibility("protected")))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr35513-9b.c b/gcc/testsuite/gcc.target/i386/pr35513-9b.c
new file mode 100644 (file)
index 0000000..b6c66f4
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fpic -mdirect-extern-access" } */
+
+/* Common symbol with -fpic.  */
+__attribute__((visibility("protected"), nodirect_extern_access))
+int xxx;
+
+int
+foo ()
+{
+  return xxx;
+}
+
+/* { dg-final { scan-assembler "xxx\\(%rip\\)" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler-not "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* { dg-final { scan-assembler "xxx@GOTOFF" { target ia32 } } } */
+/* { dg-final { scan-assembler-not "xxx@GOT\\(" { target ia32 } } } */
+/* { dg-final { scan-assembler "\.section\[ \t]+.note.gnu.property," } } */
+/* { dg-final { scan-assembler "\.long\[ \t]+0xb0008000" } } */
+