Skip to content

Commit

Permalink
[MinGW] [ARM] Add stubs for potential automatic dllimported variables
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mstorsjo committed Aug 31, 2018
1 parent 802fcb4 commit 2dcaa41
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 10 deletions.
22 changes: 19 additions & 3 deletions llvm/lib/Target/ARM/ARMAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"},
Expand Down
11 changes: 8 additions & 3 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
79 changes: 79 additions & 0 deletions llvm/test/CodeGen/ARM/Windows/mingw-refptr.ll
Original file line number Diff line number Diff line change
@@ -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
5 changes: 3 additions & 2 deletions llvm/test/CodeGen/ARM/Windows/pic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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]
5 changes: 3 additions & 2 deletions llvm/test/CodeGen/ARM/emutls_generic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2dcaa41

Please sign in to comment.