Fix PR c++/64697 at -O1 or above
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 1 Oct 2021 08:49:34 +0000 (10:49 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Fri, 1 Oct 2021 08:56:24 +0000 (10:56 +0200)
The BFD fix eliminates the link failure and working code is generated at
-O0, but _not_ when optimization is enabled because the optimizer changes:

        movq    .refptr._ZTH1s(%rip), %rax
        testq   %rax, %rax
        je      .L2
        call    _ZTH1s

into:

        leaq    _ZTH1s(%rip), %rax
        testq   %rax, %rax
        je      .L2
        call    _ZTH1s

and the leaq now also gets the relocation overflow.  So the fix is to
teach legitimate_pic_address_disp_p to reject the transformation when
the symbol is an external weak function, which yields:

        cmpq    $0, .refptr._ZTH1s(%rip)
        je      .L2
        call    _ZTH1s

and the cmpq keeps a relocation that does not overflow.

gcc/
PR c++/64697
* config/i386/i386.c (legitimate_pic_address_disp_p): For PE-COFF do
not return true for external weak function symbols in medium model.

gcc/config/i386/i386.c

index 5aeb44c..a566d84 100644 (file)
@@ -10708,24 +10708,19 @@ legitimate_pic_address_disp_p (rtx disp)
              if (is_imported_p (op0))
                return true;
 
-             if (SYMBOL_REF_FAR_ADDR_P (op0)
-                 || !SYMBOL_REF_LOCAL_P (op0))
+             if (SYMBOL_REF_FAR_ADDR_P (op0) || !SYMBOL_REF_LOCAL_P (op0))
                break;
 
-             /* Function-symbols need to be resolved only for
-                large-model.
-                For the small-model we don't need to resolve anything
-                here.  */
+             /* Non-external-weak function symbols need to be resolved only
+                for the large model.  Non-external symbols don't need to be
+                resolved for large and medium models.  For the small model,
+                we don't need to resolve anything here.  */
              if ((ix86_cmodel != CM_LARGE_PIC
-                  && SYMBOL_REF_FUNCTION_P (op0))
+                  && SYMBOL_REF_FUNCTION_P (op0)
+                  && !(SYMBOL_REF_EXTERNAL_P (op0) && SYMBOL_REF_WEAK (op0)))
+                 || !SYMBOL_REF_EXTERNAL_P (op0)
                  || ix86_cmodel == CM_SMALL_PIC)
                return true;
-             /* Non-external symbols don't need to be resolved for
-                large, and medium-model.  */
-             if ((ix86_cmodel == CM_LARGE_PIC
-                  || ix86_cmodel == CM_MEDIUM_PIC)
-                 && !SYMBOL_REF_EXTERNAL_P (op0))
-               return true;
            }
          else if (!SYMBOL_REF_FAR_ADDR_P (op0)
                   && (SYMBOL_REF_LOCAL_P (op0)