[MinGW] [ARM] Add stubs for potential automatic dllimported variables
authorMartin Storsjo <martin@martin.st>
Fri, 31 Aug 2018 08:00:25 +0000 (08:00 +0000)
committerMartin Storsjo <martin@martin.st>
Fri, 31 Aug 2018 08:00:25 +0000 (08:00 +0000)
The runtime pseudo relocations can't handle the ARM format embedded
addresses in movw/movt pairs. By using stubs, the potentially
dllimported addresses can be touched up by the runtime pseudo relocation
framework.

Differential Revision: https://reviews.llvm.org/D51450

llvm-svn: 341176

llvm/lib/Target/ARM/ARMAsmPrinter.cpp
llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
llvm/lib/Target/ARM/ARMISelLowering.cpp
llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
llvm/test/CodeGen/ARM/Windows/mingw-refptr.ll [new file with mode: 0644]
llvm/test/CodeGen/ARM/Windows/pic.ll
llvm/test/CodeGen/ARM/emutls_generic.ll

index a19584c..17dd7ee 100644 (file)
@@ -827,15 +827,31 @@ MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
     assert(Subtarget->isTargetWindows() &&
            "Windows is the only supported COFF target");
 
-    bool IsIndirect = (TargetFlags & ARMII::MO_DLLIMPORT);
+    bool IsIndirect =
+        (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));
     if (!IsIndirect)
       return getSymbol(GV);
 
     SmallString<128> Name;
-    Name = "__imp_";
+    if (TargetFlags & ARMII::MO_DLLIMPORT)
+      Name = "__imp_";
+    else if (TargetFlags & ARMII::MO_COFFSTUB)
+      Name = ".refptr.";
     getNameWithPrefix(Name, GV);
 
-    return OutContext.getOrCreateSymbol(Name);
+    MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);
+
+    if (TargetFlags & ARMII::MO_COFFSTUB) {
+      MachineModuleInfoCOFF &MMICOFF =
+          MMI->getObjFileInfo<MachineModuleInfoCOFF>();
+      MachineModuleInfoImpl::StubValueTy &StubSym =
+          MMICOFF.getGVStubEntry(MCSym);
+
+      if (!StubSym.getPointer())
+        StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), true);
+    }
+
+    return MCSym;
   } else if (Subtarget->isTargetELF()) {
     return getSymbol(GV);
   }
index 1b626ff..9a4614c 100644 (file)
@@ -5081,6 +5081,7 @@ ARMBaseInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
   using namespace ARMII;
 
   static const std::pair<unsigned, const char *> TargetFlags[] = {
+      {MO_COFFSTUB, "arm-coffstub"},
       {MO_GOT, "arm-got"},
       {MO_SBREL, "arm-sbrel"},
       {MO_DLLIMPORT, "arm-dllimport"},
index a6ce961..26f23c5 100644 (file)
@@ -3318,8 +3318,13 @@ SDValue ARMTargetLowering::LowerGlobalAddressWindows(SDValue Op,
          "ROPI/RWPI not currently supported for Windows");
 
   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
-  const ARMII::TOF TargetFlags =
-    (GV->hasDLLImportStorageClass() ? ARMII::MO_DLLIMPORT : ARMII::MO_NO_FLAG);
+  ARMII::TOF TargetFlags = ARMII::MO_NO_FLAG;
+  if (GV->hasDLLImportStorageClass())
+    TargetFlags = ARMII::MO_DLLIMPORT;
+  else if (Subtarget->getTargetTriple().isWindowsGNUEnvironment() &&
+           !GV->isDSOLocal() && GV->isDeclarationForLinker() &&
+           isa<GlobalVariable>(GV))
+    TargetFlags = ARMII::MO_COFFSTUB;
   EVT PtrVT = getPointerTy(DAG.getDataLayout());
   SDValue Result;
   SDLoc DL(Op);
@@ -3331,7 +3336,7 @@ SDValue ARMTargetLowering::LowerGlobalAddressWindows(SDValue Op,
   Result = DAG.getNode(ARMISD::Wrapper, DL, PtrVT,
                        DAG.getTargetGlobalAddress(GV, DL, PtrVT, /*Offset=*/0,
                                                   TargetFlags));
-  if (GV->hasDLLImportStorageClass())
+  if (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB))
     Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result,
                          MachinePointerInfo::getGOT(DAG.getMachineFunction()));
   return Result;
index b918006..cdadf19 100644 (file)
@@ -246,6 +246,11 @@ namespace ARMII {
     /// just that part of the flag set.
     MO_OPTION_MASK = 0x3,
 
+    /// MO_COFFSTUB - On a symbol operand "FOO", this indicates that the
+    /// reference is actually to the ".refptrp.FOO" symbol.  This is used for
+    /// stub symbols on windows.
+    MO_COFFSTUB = 0x4,
+
     /// MO_GOT - On a symbol operand, this represents a GOT relative relocation.
     MO_GOT = 0x8,
 
diff --git a/llvm/test/CodeGen/ARM/Windows/mingw-refptr.ll b/llvm/test/CodeGen/ARM/Windows/mingw-refptr.ll
new file mode 100644 (file)
index 0000000..06b3536
--- /dev/null
@@ -0,0 +1,79 @@
+; RUN: llc < %s -mtriple=thumbv7-w64-mingw32 | FileCheck %s
+
+@var = external local_unnamed_addr global i32, align 4
+@dsolocalvar = external dso_local local_unnamed_addr global i32, align 4
+@localvar = dso_local local_unnamed_addr global i32 0, align 4
+@localcommon = common dso_local local_unnamed_addr global i32 0, align 4
+@extvar = external dllimport local_unnamed_addr global i32, align 4
+
+define dso_local i32 @getVar() {
+; CHECK-LABEL: getVar:
+; CHECK:    movw r0, :lower16:.refptr.var
+; CHECK:    movt r0, :upper16:.refptr.var
+; CHECK:    ldr  r0, [r0]
+; CHECK:    ldr  r0, [r0]
+; CHECK:    bx   lr
+entry:
+  %0 = load i32, i32* @var, align 4
+  ret i32 %0
+}
+
+define dso_local i32 @getDsoLocalVar() {
+; CHECK-LABEL: getDsoLocalVar:
+; CHECK:    movw r0, :lower16:dsolocalvar
+; CHECK:    movt r0, :upper16:dsolocalvar
+; CHECK:    ldr  r0, [r0]
+; CHECK:    bx   lr
+entry:
+  %0 = load i32, i32* @dsolocalvar, align 4
+  ret i32 %0
+}
+
+define dso_local i32 @getLocalVar() {
+; CHECK-LABEL: getLocalVar:
+; CHECK:    movw r0, :lower16:localvar
+; CHECK:    movt r0, :upper16:localvar
+; CHECK:    ldr  r0, [r0]
+; CHECK:    bx   lr
+entry:
+  %0 = load i32, i32* @localvar, align 4
+  ret i32 %0
+}
+
+define dso_local i32 @getLocalCommon() {
+; CHECK-LABEL: getLocalCommon:
+; CHECK:    movw r0, :lower16:localcommon
+; CHECK:    movt r0, :upper16:localcommon
+; CHECK:    ldr  r0, [r0]
+; CHECK:    bx   lr
+entry:
+  %0 = load i32, i32* @localcommon, align 4
+  ret i32 %0
+}
+
+define dso_local i32 @getExtVar() {
+; CHECK-LABEL: getExtVar:
+; CHECK:    movw r0, :lower16:__imp_extvar
+; CHECK:    movt r0, :upper16:__imp_extvar
+; CHECK:    ldr  r0, [r0]
+; CHECK:    ldr  r0, [r0]
+; CHECK:    bx   lr
+entry:
+  %0 = load i32, i32* @extvar, align 4
+  ret i32 %0
+}
+
+define dso_local void @callFunc() {
+; CHECK-LABEL: callFunc:
+; CHECK:    b otherFunc
+entry:
+  tail call void @otherFunc()
+  ret void
+}
+
+declare dso_local void @otherFunc()
+
+; CHECK:        .section        .rdata$.refptr.var,"dr",discard,.refptr.var
+; CHECK:        .globl  .refptr.var
+; CHECK: .refptr.var:
+; CHECK:        .long   var
index df4c400..958fc26 100644 (file)
@@ -18,6 +18,7 @@ entry:
 ; CHECK-WIN: ldrb r0, [r0]
 
 ; CHECK-GNU-LABEL: return_external
-; CHECK-GNU: movw r0, :lower16:external
-; CHECK-GNU: movt r0, :upper16:external
+; CHECK-GNU: movw r0, :lower16:.refptr.external
+; CHECK-GNU: movt r0, :upper16:.refptr.external
+; CHECK-GNU: ldr  r0, [r0]
 ; CHECK-GNU: ldrb r0, [r0]
index 41a46b4..8bf0ab3 100644 (file)
@@ -78,8 +78,9 @@ entry:
 ; ARM_32-NEXT:   .long 0
 
 ; WIN-LABEL:  get_external_x:
-; WIN:        movw r0, :lower16:__emutls_v.external_x
-; WIN:        movt r0, :upper16:__emutls_v.external_x
+; WIN:        movw r0, :lower16:.refptr.__emutls_v.external_x
+; WIN:        movt r0, :upper16:.refptr.__emutls_v.external_x
+; WIN:        ldr  r0, [r0]
 ; WIN:        bl __emutls_get_address
 ; WIN-LABEL:  get_external_y:
 ; WIN:        movw r0, :lower16:__emutls_v.external_y