[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