]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Support weak references
authorEvgeny Karpov <evgeny.karpov@microsoft.com>
Wed, 14 Aug 2024 15:56:38 +0000 (17:56 +0200)
committerEvgeny Karpov <eukarpov@gmail.com>
Tue, 19 Nov 2024 13:27:32 +0000 (14:27 +0100)
The patch adds support for weak references. The original MinGW
implementation targets ix86, which handles weak symbols differently
compared to AArch64. In AArch64, the weak symbols are replaced by
other symbols which reference the original weak symbols, and the
compiler does not track the original symbol names.
This patch resolves this and declares the original symbols.

Here is an explanation of why this change is needed and what the
difference is between x86_64-w64-mingw32 and aarch64-w64-mingw32.

The way x86_64 calls a weak function:
call  weak_fn2

GCC emits the call and creates the required definitions at the end
of the assembly:

.weak weak_fn2
.def  weak_fn2;   .scl  2;    .type 32;   .endef

This is different from aarch64:

weak_fn2 will be legitimized and replaced by .refptr.weak_fn2,
and there will be no other references to weak_fn2 in the code.

adrp  x0, .refptr.weak_fn2
add   x0, x0, :lo12:.refptr.weak_fn2
ldr   x0, [x0]
blr   x0

GCC does not emit the required definitions at the end of the assembly,
and weak_fn2 is tracked only by the mingw stub sybmol.

Without the change, the stub definition will emit:

    .section      .rdata$.refptr.weak_fn2, "dr"
    .globl  .refptr.weak_fn2
    .linkonce     discard
.refptr.weak_fn2:
    .quad   weak_fn2

which is not enough. This fix will emit the required definitions:

    .weak   weak_fn2
    .def    weak_fn2;   .scl  2;    .type 32;   .endef
    .section      .rdata$.refptr.weak_fn2, "dr"
    .globl  .refptr.weak_fn2
    .linkonce     discard
.refptr.weak_fn2:
    .quad   weak_fn2

This is the first commit in the third patch series with SMALL code
model fixes, optimization fixes, LTO, and minimal C++ enablement.

Prepared, refactored and validated by
Radek Barton <radek.barton@microsoft.com> and
Evgeny Karpov <evgeny.karpov@microsoft.com>

Contributor: Zac Walker <zacwalker@microsoft.com>

gcc/ChangeLog:

* config/aarch64/cygming.h (SUB_TARGET_RECORD_STUB): Request
declaration for weak symbols.
(PE_COFF_LEGITIMIZE_EXTERN_DECL): Legitimize external
declaration for weak symbols.
* config/i386/cygming.h (SUB_TARGET_RECORD_STUB): Update
declarations in ix86 with the same functionality.
(PE_COFF_LEGITIMIZE_EXTERN_DECL): Likewise.
* config/mingw/winnt-dll.cc (legitimize_pe_coff_symbol):
Support declaration for weak symbols if requested.
* config/mingw/winnt.cc (struct stub_list): Likewise.
(mingw_pe_record_stub): Likewise.
(mingw_pe_file_end): Likewise.
* config/mingw/winnt.h (mingw_pe_record_stub): Likewise.

gcc/config/aarch64/cygming.h
gcc/config/i386/cygming.h
gcc/config/mingw/winnt-dll.cc
gcc/config/mingw/winnt.cc
gcc/config/mingw/winnt.h

index 9ce140a356f811c01a1497cd356ea26dedede77f..bd6078023e368811df007f986f608397e4110846 100644 (file)
@@ -171,7 +171,8 @@ still needed for compilation.  */
     mingw_handle_selectany_attribute, NULL }
 
 #undef SUB_TARGET_RECORD_STUB
-#define SUB_TARGET_RECORD_STUB mingw_pe_record_stub
+#define SUB_TARGET_RECORD_STUB(NAME, DECL) mingw_pe_record_stub((NAME), \
+  DECL_WEAK ((DECL)))
 
 #define SUPPORTS_ONE_ONLY 1
 
@@ -186,7 +187,8 @@ still needed for compilation.  */
 #undef GOT_ALIAS_SET
 #define GOT_ALIAS_SET mingw_GOT_alias_set ()
 
-#define PE_COFF_LEGITIMIZE_EXTERN_DECL 1
+#define PE_COFF_LEGITIMIZE_EXTERN_DECL(RTX) \
+  (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_WEAK (RTX))
 
 #define HAVE_64BIT_POINTERS 1
 
index bd1259fb4d899d24c20c3a182ba85f8162f2ae88..67bfb8d641b9392293b6ffbbea70d3b77f359a14 100644 (file)
@@ -461,7 +461,7 @@ do {                                                \
 #define TARGET_ASM_ASSEMBLE_VISIBILITY i386_pe_assemble_visibility
 
 #undef SUB_TARGET_RECORD_STUB
-#define SUB_TARGET_RECORD_STUB mingw_pe_record_stub
+#define SUB_TARGET_RECORD_STUB(NAME, DECL) mingw_pe_record_stub((NAME), 0)
 
 /* Static stack checking is supported by means of probes.  */
 #define STACK_CHECK_STATIC_BUILTIN 1
@@ -470,7 +470,7 @@ do {                                                \
 # define HAVE_GAS_ALIGNED_COMM 0
 #endif
 
-#define PE_COFF_LEGITIMIZE_EXTERN_DECL \
+#define PE_COFF_LEGITIMIZE_EXTERN_DECL(RTX) \
   (ix86_cmodel == CM_LARGE_PIC || ix86_cmodel == CM_MEDIUM_PIC)
 
 #define HAVE_64BIT_POINTERS TARGET_64BIT_DEFAULT
index f74495b7fda956e0d5afc7907c7a08f25a70fc52..eb7cff7a593ef16b17fb8c56fbc366820bfef174 100644 (file)
@@ -134,7 +134,7 @@ get_dllimport_decl (tree decl, bool beimport)
     {
       SYMBOL_REF_FLAGS (rtl) |= SYMBOL_FLAG_EXTERNAL;
 #ifdef SUB_TARGET_RECORD_STUB
-      SUB_TARGET_RECORD_STUB (name);
+      SUB_TARGET_RECORD_STUB (name, decl);
 #endif
     }
 
@@ -206,7 +206,7 @@ legitimize_pe_coff_symbol (rtx addr, bool inreg)
        }
     }
 
-  if (!PE_COFF_LEGITIMIZE_EXTERN_DECL)
+  if (!PE_COFF_LEGITIMIZE_EXTERN_DECL (addr))
     return NULL_RTX;
 
   if (GET_CODE (addr) == SYMBOL_REF
index 9d433daaf5a6b49e20da517c87bf0e9434e14c21..61e360b287c42106157f66a973b8cb4d95792975 100644 (file)
@@ -636,6 +636,7 @@ struct GTY(()) stub_list
 {
   struct stub_list *next;
   const char *name;
+  bool is_weak_decl_needed;
 };
 
 static GTY(()) struct export_list *export_head;
@@ -673,7 +674,7 @@ mingw_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
 }
 
 void
-mingw_pe_record_stub (const char *name)
+mingw_pe_record_stub (const char *name, bool is_weak_decl_needed)
 {
   struct stub_list *p;
 
@@ -692,6 +693,7 @@ mingw_pe_record_stub (const char *name)
   p = ggc_alloc<stub_list> ();
   p->next = stub_head;
   p->name = name;
+  p->is_weak_decl_needed = is_weak_decl_needed;
   stub_head = p;
 }
 
@@ -808,6 +810,15 @@ mingw_pe_file_end (void)
          if (!startswith (name, "refptr."))
            continue;
          name += 7;
+
+         if (q->is_weak_decl_needed)
+           {
+#ifdef ASM_WEAKEN_LABEL
+             ASM_WEAKEN_LABEL (asm_out_file, name);
+#endif
+             mingw_pe_declare_function_type (asm_out_file, name, 1);
+           }
+
          fprintf (asm_out_file, "\t.section\t.rdata$%s, \"dr\"\n"
                           "\t.globl\t%s\n"
                           "\t.linkonce\tdiscard\n", oname, oname);
index 97fefbcebca5d3a2c1e7e7f978ce446a4d81aba1..a21a36b7e5d502afbfdb28b643b71114f7936779 100644 (file)
@@ -28,7 +28,7 @@ extern void mingw_pe_declare_function_type (FILE *file, const char *name,
 extern void mingw_pe_encode_section_info (tree, rtx, int);
 extern void mingw_pe_file_end (void);
 extern void mingw_pe_maybe_record_exported_symbol (tree, const char *, int);
-extern void mingw_pe_record_stub (const char *);
+extern void mingw_pe_record_stub (const char *, bool);
 extern unsigned int mingw_pe_section_type_flags (tree, const char *, int);
 extern void mingw_pe_unique_section (tree, int);
 extern bool mingw_pe_valid_dllimport_attribute_p (const_tree);