[llvm] r316555 - [AArch64] Add support for dllimport of values and functions
Martin Storsjo via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 25 00:25:18 PDT 2017
Author: mstorsjo
Date: Wed Oct 25 00:25:18 2017
New Revision: 316555
URL: http://llvm.org/viewvc/llvm-project?rev=316555&view=rev
Log:
[AArch64] Add support for dllimport of values and functions
Previously, the dllimport attribute did the right thing in terms
of treating it as a pointer to a value, but this makes sure the
names get mangled properly, and calls to such functions load the
function from the __imp_ pointer.
This is based on SVN r212431 and r212430 where the same was
implemented for ARM.
Differential Revision: https://reviews.llvm.org/D38530
Added:
llvm/trunk/test/CodeGen/AArch64/dllimport.ll
Modified:
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h
llvm/trunk/lib/Target/AArch64/AArch64MCInstLower.cpp
llvm/trunk/lib/Target/AArch64/Utils/AArch64BaseInfo.h
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=316555&r1=316554&r2=316555&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Wed Oct 25 00:25:18 2017
@@ -3487,6 +3487,10 @@ AArch64TargetLowering::LowerCall(CallLow
AArch64II::MO_GOT) {
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_GOT);
Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
+ } else if (Subtarget->isTargetCOFF() && GV->hasDLLImportStorageClass()) {
+ assert(Subtarget->isTargetWindows() &&
+ "Windows is the only supported COFF target");
+ Callee = getGOT(G, DAG, AArch64II::MO_DLLIMPORT);
} else {
const GlobalValue *GV = G->getGlobal();
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
@@ -3687,11 +3691,12 @@ SDValue AArch64TargetLowering::getTarget
// (loadGOT sym)
template <class NodeTy>
-SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG) const {
+SDValue AArch64TargetLowering::getGOT(NodeTy *N, SelectionDAG &DAG,
+ unsigned Flags) const {
DEBUG(dbgs() << "AArch64TargetLowering::getGOT\n");
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
- SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT);
+ SDValue GotAddr = getTargetNode(N, Ty, DAG, AArch64II::MO_GOT | Flags);
// FIXME: Once remat is capable of dealing with instructions with register
// operands, expand this into two nodes instead of using a wrapper node.
return DAG.getNode(AArch64ISD::LOADgot, DL, Ty, GotAddr);
@@ -3699,29 +3704,30 @@ SDValue AArch64TargetLowering::getGOT(No
// (wrapper %highest(sym), %higher(sym), %hi(sym), %lo(sym))
template <class NodeTy>
-SDValue AArch64TargetLowering::getAddrLarge(NodeTy *N, SelectionDAG &DAG)
- const {
+SDValue AArch64TargetLowering::getAddrLarge(NodeTy *N, SelectionDAG &DAG,
+ unsigned Flags) const {
DEBUG(dbgs() << "AArch64TargetLowering::getAddrLarge\n");
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
const unsigned char MO_NC = AArch64II::MO_NC;
return DAG.getNode(
- AArch64ISD::WrapperLarge, DL, Ty,
- getTargetNode(N, Ty, DAG, AArch64II::MO_G3),
- getTargetNode(N, Ty, DAG, AArch64II::MO_G2 | MO_NC),
- getTargetNode(N, Ty, DAG, AArch64II::MO_G1 | MO_NC),
- getTargetNode(N, Ty, DAG, AArch64II::MO_G0 | MO_NC));
+ AArch64ISD::WrapperLarge, DL, Ty,
+ getTargetNode(N, Ty, DAG, AArch64II::MO_G3 | Flags),
+ getTargetNode(N, Ty, DAG, AArch64II::MO_G2 | MO_NC | Flags),
+ getTargetNode(N, Ty, DAG, AArch64II::MO_G1 | MO_NC | Flags),
+ getTargetNode(N, Ty, DAG, AArch64II::MO_G0 | MO_NC | Flags));
}
// (addlow (adrp %hi(sym)) %lo(sym))
template <class NodeTy>
-SDValue AArch64TargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG) const {
+SDValue AArch64TargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
+ unsigned Flags) const {
DEBUG(dbgs() << "AArch64TargetLowering::getAddr\n");
SDLoc DL(N);
EVT Ty = getPointerTy(DAG.getDataLayout());
- SDValue Hi = getTargetNode(N, Ty, DAG, AArch64II::MO_PAGE);
+ SDValue Hi = getTargetNode(N, Ty, DAG, AArch64II::MO_PAGE | Flags);
SDValue Lo = getTargetNode(N, Ty, DAG,
- AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
+ AArch64II::MO_PAGEOFF | AArch64II::MO_NC | Flags);
SDValue ADRP = DAG.getNode(AArch64ISD::ADRP, DL, Ty, Hi);
return DAG.getNode(AArch64ISD::ADDlow, DL, Ty, ADRP, Lo);
}
@@ -3730,6 +3736,9 @@ SDValue AArch64TargetLowering::LowerGlob
SelectionDAG &DAG) const {
GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = GN->getGlobal();
+ const AArch64II::TOF TargetFlags =
+ (GV->hasDLLImportStorageClass() ? AArch64II::MO_DLLIMPORT
+ : AArch64II::MO_NO_FLAG);
unsigned char OpFlags =
Subtarget->ClassifyGlobalReference(GV, getTargetMachine());
@@ -3738,14 +3747,21 @@ SDValue AArch64TargetLowering::LowerGlob
// This also catches the large code model case for Darwin.
if ((OpFlags & AArch64II::MO_GOT) != 0) {
- return getGOT(GN, DAG);
+ return getGOT(GN, DAG, TargetFlags);
}
+ SDValue Result;
if (getTargetMachine().getCodeModel() == CodeModel::Large) {
- return getAddrLarge(GN, DAG);
+ Result = getAddrLarge(GN, DAG, TargetFlags);
} else {
- return getAddr(GN, DAG);
+ Result = getAddr(GN, DAG, TargetFlags);
}
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+ SDLoc DL(GN);
+ if (GV->hasDLLImportStorageClass())
+ Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Result,
+ MachinePointerInfo::getGOT(DAG.getMachineFunction()));
+ return Result;
}
/// \brief Convert a TLS address reference into the correct sequence of loads
Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h?rev=316555&r1=316554&r2=316555&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.h Wed Oct 25 00:25:18 2017
@@ -538,10 +538,12 @@ private:
unsigned Flag) const;
SDValue getTargetNode(BlockAddressSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
- template <class NodeTy> SDValue getGOT(NodeTy *N, SelectionDAG &DAG) const;
template <class NodeTy>
- SDValue getAddrLarge(NodeTy *N, SelectionDAG &DAG) const;
- template <class NodeTy> SDValue getAddr(NodeTy *N, SelectionDAG &DAG) const;
+ SDValue getGOT(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
+ template <class NodeTy>
+ SDValue getAddrLarge(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
+ template <class NodeTy>
+ SDValue getAddr(NodeTy *N, SelectionDAG &DAG, unsigned Flags = 0) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDarwinGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
Modified: llvm/trunk/lib/Target/AArch64/AArch64MCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64MCInstLower.cpp?rev=316555&r1=316554&r2=316555&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64MCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64MCInstLower.cpp Wed Oct 25 00:25:18 2017
@@ -19,10 +19,12 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/Mangler.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
@@ -33,7 +35,25 @@ AArch64MCInstLower::AArch64MCInstLower(M
MCSymbol *
AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
- return Printer.getSymbol(MO.getGlobal());
+ const GlobalValue *GV = MO.getGlobal();
+ unsigned TargetFlags = MO.getTargetFlags();
+ const Triple &TheTriple = Printer.TM.getTargetTriple();
+ if (!TheTriple.isOSBinFormatCOFF())
+ return Printer.getSymbol(GV);
+
+ assert(TheTriple.isOSWindows() &&
+ "Windows is the only supported COFF target");
+
+ bool IsIndirect = (TargetFlags & AArch64II::MO_DLLIMPORT);
+ if (!IsIndirect)
+ return Printer.getSymbol(GV);
+
+ SmallString<128> Name;
+ Name = "__imp_";
+ Printer.TM.getNameWithPrefix(Name, GV,
+ Printer.getObjFileLowering().getMangler());
+
+ return Ctx.getOrCreateSymbol(Name);
}
MCSymbol *
Modified: llvm/trunk/lib/Target/AArch64/Utils/AArch64BaseInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/Utils/AArch64BaseInfo.h?rev=316555&r1=316554&r2=316555&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/Utils/AArch64BaseInfo.h (original)
+++ llvm/trunk/lib/Target/AArch64/Utils/AArch64BaseInfo.h Wed Oct 25 00:25:18 2017
@@ -517,7 +517,12 @@ namespace AArch64II {
/// thread-local symbol. On Darwin, only one type of thread-local access
/// exists (pre linker-relaxation), but on ELF the TLSModel used for the
/// referee will affect interpretation.
- MO_TLS = 0x40
+ MO_TLS = 0x40,
+
+ /// MO_DLLIMPORT - On a symbol operand, this represents that the reference
+ /// to the symbol is for an import stub. This is used for DLL import
+ /// storage class indication on Windows.
+ MO_DLLIMPORT = 0x80,
};
} // end namespace AArch64II
Added: llvm/trunk/test/CodeGen/AArch64/dllimport.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/dllimport.ll?rev=316555&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/dllimport.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/dllimport.ll Wed Oct 25 00:25:18 2017
@@ -0,0 +1,54 @@
+; RUN: llc -mtriple aarch64-unknown-windows-msvc -filetype asm -o - %s | FileCheck %s
+
+ at var = external dllimport global i32
+ at ext = external global i32
+declare dllimport i32 @external()
+declare i32 @internal()
+
+define i32 @get_var() {
+ %1 = load i32, i32* @var, align 4
+ ret i32 %1
+}
+
+; CHECK-LABEL: get_var
+; CHECK: adrp x8, __imp_var
+; CHECK: ldr x8, [x8, __imp_var]
+; CHECK: ldr w0, [x8]
+; CHECK: ret
+
+define i32 @get_ext() {
+ %1 = load i32, i32* @ext, align 4
+ ret i32 %1
+}
+
+; CHECK-LABEL: get_ext
+; CHECK: adrp x8, ext
+; CHECK: ldr w0, [x8, ext]
+; CHECK: ret
+
+define i32* @get_var_pointer() {
+ ret i32* @var
+}
+
+; CHECK-LABEL: get_var_pointer
+; CHECK: adrp x0, __imp_var
+; CHECK: ldr x0, [x0, __imp_var]
+; CHECK: ret
+
+define i32 @call_external() {
+ %call = tail call i32 @external()
+ ret i32 %call
+}
+
+; CHECK-LABEL: call_external
+; CHECK: adrp x0, __imp_external
+; CHECK: ldr x0, [x0, __imp_external]
+; CHECK: br x0
+
+define i32 @call_internal() {
+ %call = tail call i32 @internal()
+ ret i32 %call
+}
+
+; CHECK-LABEL: call_internal
+; CHECK: b internal
More information about the llvm-commits
mailing list