[llvm] [Mips] Handle declspec(dllimport) on mipsel-windows-* triples (PR #120912)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 22 09:46:40 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
Author: Hervé Poussineau (hpoussin)
<details>
<summary>Changes</summary>
On Windows, imported symbols must be searched with '__imp_' prefix.
Support imported global variables and imported functions.
---
Full diff: https://github.com/llvm/llvm-project/pull/120912.diff
7 Files Affected:
- (modified) llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h (+6-1)
- (modified) llvm/lib/Target/Mips/MipsISelLowering.cpp (+16-1)
- (modified) llvm/lib/Target/Mips/MipsISelLowering.h (+27)
- (modified) llvm/lib/Target/Mips/MipsMCInstLower.cpp (+12-2)
- (modified) llvm/lib/Target/Mips/MipsSubtarget.h (+2)
- (added) llvm/test/CodeGen/Mips/dllimport.ll (+55)
- (added) llvm/test/MC/Mips/coff-relocs-dllimport.ll (+11)
``````````diff
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index aa35e7db6bda444..b9a2af3341236a5 100644
--- a/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -92,7 +92,12 @@ namespace MipsII {
MO_CALL_LO16,
/// Helper operand used to generate R_MIPS_JALR
- MO_JALR
+ MO_JALR,
+
+ /// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
+ /// reference is actually to the "__imp_FOO" symbol. This is used for
+ /// dllimport linkage on windows.
+ MO_DLLIMPORT = 0x20,
};
enum {
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index d5f38c414e703d2..469b7a566cea25c 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -2146,6 +2146,14 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = N->getGlobal();
+ if (GV->hasDLLImportStorageClass()) {
+ assert(Subtarget.isTargetWindows() &&
+ "Windows is the only supported COFF target");
+ return getDllimportVariable(
+ N, SDLoc(N), Ty, DAG, DAG.getEntryNode(),
+ MachinePointerInfo::getGOT(DAG.getMachineFunction()));
+ }
+
if (!isPositionIndependent()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
@@ -3501,7 +3509,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
}
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- if (IsPIC) {
+ if (Subtarget.isTargetCOFF() &&
+ G->getGlobal()->hasDLLImportStorageClass()) {
+ assert(Subtarget.isTargetWindows() &&
+ "Windows is the only supported COFF target");
+ auto PtrInfo = MachinePointerInfo();
+ Callee = DAG.getLoad(Ty, DL, Chain,
+ getDllimportSymbol(G, SDLoc(G), Ty, DAG), PtrInfo);
+ } else if (IsPIC) {
const GlobalValue *Val = G->getGlobal();
InternalLinkage = Val->hasInternalLinkage();
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h
index e245c056de6491e..efd0acef961f616 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.h
+++ b/llvm/lib/Target/Mips/MipsISelLowering.h
@@ -487,6 +487,33 @@ class TargetRegisterClass;
DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel));
}
+ // This method creates the following nodes, which are necessary for
+ // loading a dllimported symbol:
+ //
+ // (lw (add (shl(%high(sym), 16), %low(sym)))
+ template <class NodeTy>
+ SDValue getDllimportSymbol(NodeTy *N, const SDLoc &DL, EVT Ty,
+ SelectionDAG &DAG) const {
+ SDValue Hi =
+ getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI | MipsII::MO_DLLIMPORT);
+ SDValue Lo =
+ getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO | MipsII::MO_DLLIMPORT);
+ return DAG.getNode(ISD::ADD, DL, Ty, DAG.getNode(MipsISD::Lo, DL, Ty, Lo),
+ DAG.getNode(MipsISD::Hi, DL, Ty, Hi));
+ }
+
+ // This method creates the following nodes, which are necessary for
+ // loading a dllimported global variable:
+ //
+ // (lw (lw (add (shl(%high(sym), 16), %low(sym))))
+ template <class NodeTy>
+ SDValue getDllimportVariable(NodeTy *N, const SDLoc &DL, EVT Ty,
+ SelectionDAG &DAG, SDValue Chain,
+ const MachinePointerInfo &PtrInfo) const {
+ return DAG.getLoad(Ty, DL, Chain, getDllimportSymbol(N, DL, Ty, DAG),
+ PtrInfo);
+ }
+
/// This function fills Ops, which is the list of operands that will later
/// be used when a function call node is created. It also generates
/// copyToReg nodes to set up argument registers.
diff --git a/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/llvm/lib/Target/Mips/MipsMCInstLower.cpp
index b0642f3d1ff283a..e01d0d1e65cf7e9 100644
--- a/llvm/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/llvm/lib/Target/Mips/MipsMCInstLower.cpp
@@ -18,6 +18,7 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/ErrorHandling.h"
@@ -38,8 +39,16 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
bool IsGpOff = false;
const MCSymbol *Symbol;
+ SmallString<128> Name;
+ unsigned TargetFlags = MO.getTargetFlags();
- switch(MO.getTargetFlags()) {
+ if (TargetFlags & MipsII::MO_DLLIMPORT) {
+ // Handle dllimport linkage
+ Name += "__imp_";
+ TargetFlags &= ~MipsII::MO_DLLIMPORT;
+ }
+
+ switch (TargetFlags) {
default:
llvm_unreachable("Invalid target flag!");
case MipsII::MO_NO_FLAG:
@@ -125,7 +134,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
break;
case MachineOperand::MO_GlobalAddress:
- Symbol = AsmPrinter.getSymbol(MO.getGlobal());
+ AsmPrinter.getNameWithPrefix(Name, MO.getGlobal());
+ Symbol = Ctx->getOrCreateSymbol(Name);
Offset += MO.getOffset();
break;
diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h
index c048ab29d5f9b2e..85cf45d4702ae81 100644
--- a/llvm/lib/Target/Mips/MipsSubtarget.h
+++ b/llvm/lib/Target/Mips/MipsSubtarget.h
@@ -301,6 +301,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32();
}
bool isSingleFloat() const { return IsSingleFloat; }
+ bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool hasVFPU() const { return HasVFPU; }
bool inMips16Mode() const { return InMips16Mode; }
@@ -356,6 +357,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
bool os16() const { return Os16; }
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
+ bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
bool isXRaySupported() const override { return true; }
diff --git a/llvm/test/CodeGen/Mips/dllimport.ll b/llvm/test/CodeGen/Mips/dllimport.ll
new file mode 100644
index 000000000000000..385199892821e7d
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/dllimport.ll
@@ -0,0 +1,55 @@
+; RUN: llc -mtriple mipsel-windows < %s | FileCheck %s
+
+ at Var1 = external dllimport global i32
+ at Var2 = available_externally dllimport unnamed_addr constant i32 1
+
+declare dllimport void @fun()
+
+define available_externally dllimport void @inline1() {
+ ret void
+}
+
+define available_externally dllimport void @inline2() alwaysinline {
+ ret void
+}
+
+declare void @dummy(...)
+
+define void @use() nounwind {
+; CHECK: lui $1, %hi(__imp_fun)
+; CHECK: addiu $1, $1, %lo(__imp_fun)
+; CHECK: lw $25, 0($1)
+; CHECK: jalr $25
+ call void @fun()
+
+; CHECK: lui $1, %hi(__imp_inline1)
+; CHECK: addiu $1, $1, %lo(__imp_inline1)
+; CHECK: lw $25, 0($1)
+; CHECK: jalr $25
+ call void @inline1()
+
+; CHECK: lui $1, %hi(__imp_inline2)
+; CHECK: addiu $1, $1, %lo(__imp_inline2)
+; CHECK: lw $25, 0($1)
+; CHECK: jalr $25
+ call void @inline2()
+
+; CHECK: lui $1, %hi(__imp_Var2)
+; CHECK: addiu $1, $1, %lo(__imp_Var2)
+; CHECK: lw $1, 0($1)
+; CHECK: lw $5, 0($1)
+; CHECK: lui $1, %hi(__imp_Var1)
+; CHECK: addiu $1, $1, %lo(__imp_Var1)
+; CHECK: lw $1, 0($1)
+; CHECK: lw $4, 0($1)
+ %1 = load i32, ptr @Var1
+ %2 = load i32, ptr @Var2
+ call void(...) @dummy(i32 %1, i32 %2)
+
+ ret void
+}
+
+; CHECK: fp:
+; CHECK-NEXT: .long fun
+ at fp = constant ptr @fun
+
diff --git a/llvm/test/MC/Mips/coff-relocs-dllimport.ll b/llvm/test/MC/Mips/coff-relocs-dllimport.ll
new file mode 100644
index 000000000000000..a4d189faefdbcbb
--- /dev/null
+++ b/llvm/test/MC/Mips/coff-relocs-dllimport.ll
@@ -0,0 +1,11 @@
+; RUN: llc -mtriple mipsel-windows -filetype obj < %s | llvm-objdump --reloc - | FileCheck %s
+
+declare dllimport void @fun()
+
+define void @use() nounwind {
+; CHECK: 00000008 IMAGE_REL_MIPS_REFHI __imp_fun
+; CHECK: 0000000c IMAGE_REL_MIPS_REFLO __imp_fun
+ call void() @fun()
+
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/120912
More information about the llvm-commits
mailing list