forked from OSchip/llvm-project
[MinGW] [ARM] Add stubs for potential automatic dllimported variables
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
This commit is contained in:
parent
802fcb4167
commit
2dcaa41e1e
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue