Index: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp +++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp @@ -827,15 +827,31 @@ 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(); + 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: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -5081,6 +5081,7 @@ using namespace ARMII; static const std::pair TargetFlags[] = { + {MO_COFFSTUB, "arm-coffstub"}, {MO_GOT, "arm-got"}, {MO_SBREL, "arm-sbrel"}, {MO_DLLIMPORT, "arm-dllimport"}, Index: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp @@ -3318,8 +3318,13 @@ "ROPI/RWPI not currently supported for Windows"); const GlobalValue *GV = cast(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(GV)) + TargetFlags = ARMII::MO_COFFSTUB; EVT PtrVT = getPointerTy(DAG.getDataLayout()); SDValue Result; SDLoc DL(Op); @@ -3331,7 +3336,7 @@ 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: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h =================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -246,6 +246,11 @@ /// 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, Index: llvm/trunk/test/CodeGen/ARM/Windows/mingw-refptr.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/Windows/mingw-refptr.ll +++ llvm/trunk/test/CodeGen/ARM/Windows/mingw-refptr.ll @@ -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: llvm/trunk/test/CodeGen/ARM/Windows/pic.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/Windows/pic.ll +++ llvm/trunk/test/CodeGen/ARM/Windows/pic.ll @@ -18,6 +18,7 @@ ; 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: llvm/trunk/test/CodeGen/ARM/emutls_generic.ll =================================================================== --- llvm/trunk/test/CodeGen/ARM/emutls_generic.ll +++ llvm/trunk/test/CodeGen/ARM/emutls_generic.ll @@ -78,8 +78,9 @@ ; 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