Skip to content

Commit 26b87aa

Browse files
authored
[Mips] Handle declspec(dllimport) on mipsel-windows-* triples (#120912)
On Windows, imported symbols must be searched with '__imp_' prefix. Support imported global variables and imported functions.
1 parent 7bb363b commit 26b87aa

File tree

7 files changed

+129
-4
lines changed

7 files changed

+129
-4
lines changed

llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,12 @@ namespace MipsII {
9292
MO_CALL_LO16,
9393

9494
/// Helper operand used to generate R_MIPS_JALR
95-
MO_JALR
95+
MO_JALR,
96+
97+
/// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
98+
/// reference is actually to the "__imp_FOO" symbol. This is used for
99+
/// dllimport linkage on windows.
100+
MO_DLLIMPORT = 0x20,
96101
};
97102

98103
enum {

llvm/lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2146,6 +2146,14 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
21462146
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
21472147
const GlobalValue *GV = N->getGlobal();
21482148

2149+
if (GV->hasDLLImportStorageClass()) {
2150+
assert(Subtarget.isTargetWindows() &&
2151+
"Windows is the only supported COFF target");
2152+
return getDllimportVariable(
2153+
N, SDLoc(N), Ty, DAG, DAG.getEntryNode(),
2154+
MachinePointerInfo::getGOT(DAG.getMachineFunction()));
2155+
}
2156+
21492157
if (!isPositionIndependent()) {
21502158
const MipsTargetObjectFile *TLOF =
21512159
static_cast<const MipsTargetObjectFile *>(
@@ -3501,7 +3509,14 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
35013509
}
35023510

35033511
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
3504-
if (IsPIC) {
3512+
if (Subtarget.isTargetCOFF() &&
3513+
G->getGlobal()->hasDLLImportStorageClass()) {
3514+
assert(Subtarget.isTargetWindows() &&
3515+
"Windows is the only supported COFF target");
3516+
auto PtrInfo = MachinePointerInfo();
3517+
Callee = DAG.getLoad(Ty, DL, Chain,
3518+
getDllimportSymbol(G, SDLoc(G), Ty, DAG), PtrInfo);
3519+
} else if (IsPIC) {
35053520
const GlobalValue *Val = G->getGlobal();
35063521
InternalLinkage = Val->hasInternalLinkage();
35073522

llvm/lib/Target/Mips/MipsISelLowering.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,33 @@ class TargetRegisterClass;
489489
DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel));
490490
}
491491

492+
// This method creates the following nodes, which are necessary for
493+
// loading a dllimported symbol:
494+
//
495+
// (lw (add (shl(%high(sym), 16), %low(sym)))
496+
template <class NodeTy>
497+
SDValue getDllimportSymbol(NodeTy *N, const SDLoc &DL, EVT Ty,
498+
SelectionDAG &DAG) const {
499+
SDValue Hi =
500+
getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI | MipsII::MO_DLLIMPORT);
501+
SDValue Lo =
502+
getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO | MipsII::MO_DLLIMPORT);
503+
return DAG.getNode(ISD::ADD, DL, Ty, DAG.getNode(MipsISD::Lo, DL, Ty, Lo),
504+
DAG.getNode(MipsISD::Hi, DL, Ty, Hi));
505+
}
506+
507+
// This method creates the following nodes, which are necessary for
508+
// loading a dllimported global variable:
509+
//
510+
// (lw (lw (add (shl(%high(sym), 16), %low(sym))))
511+
template <class NodeTy>
512+
SDValue getDllimportVariable(NodeTy *N, const SDLoc &DL, EVT Ty,
513+
SelectionDAG &DAG, SDValue Chain,
514+
const MachinePointerInfo &PtrInfo) const {
515+
return DAG.getLoad(Ty, DL, Chain, getDllimportSymbol(N, DL, Ty, DAG),
516+
PtrInfo);
517+
}
518+
492519
/// This function fills Ops, which is the list of operands that will later
493520
/// be used when a function call node is created. It also generates
494521
/// copyToReg nodes to set up argument registers.

llvm/lib/Target/Mips/MipsMCInstLower.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/CodeGen/MachineBasicBlock.h"
1919
#include "llvm/CodeGen/MachineInstr.h"
2020
#include "llvm/CodeGen/MachineOperand.h"
21+
#include "llvm/MC/MCContext.h"
2122
#include "llvm/MC/MCExpr.h"
2223
#include "llvm/MC/MCInst.h"
2324
#include "llvm/Support/ErrorHandling.h"
@@ -38,8 +39,16 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
3839
MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
3940
bool IsGpOff = false;
4041
const MCSymbol *Symbol;
42+
SmallString<128> Name;
43+
unsigned TargetFlags = MO.getTargetFlags();
4144

42-
switch(MO.getTargetFlags()) {
45+
if (TargetFlags & MipsII::MO_DLLIMPORT) {
46+
// Handle dllimport linkage
47+
Name += "__imp_";
48+
TargetFlags &= ~MipsII::MO_DLLIMPORT;
49+
}
50+
51+
switch (TargetFlags) {
4352
default:
4453
llvm_unreachable("Invalid target flag!");
4554
case MipsII::MO_NO_FLAG:
@@ -125,7 +134,8 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
125134
break;
126135

127136
case MachineOperand::MO_GlobalAddress:
128-
Symbol = AsmPrinter.getSymbol(MO.getGlobal());
137+
AsmPrinter.getNameWithPrefix(Name, MO.getGlobal());
138+
Symbol = Ctx->getOrCreateSymbol(Name);
129139
Offset += MO.getOffset();
130140
break;
131141

llvm/lib/Target/Mips/MipsSubtarget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
301301
return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32();
302302
}
303303
bool isSingleFloat() const { return IsSingleFloat; }
304+
bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
304305
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
305306
bool hasVFPU() const { return HasVFPU; }
306307
bool inMips16Mode() const { return InMips16Mode; }
@@ -356,6 +357,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
356357
bool os16() const { return Os16; }
357358

358359
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
360+
bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
359361

360362
bool isXRaySupported() const override { return true; }
361363

llvm/test/CodeGen/Mips/dllimport.ll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: llc -mtriple mipsel-windows < %s | FileCheck %s
2+
3+
@Var1 = external dllimport global i32
4+
@Var2 = available_externally dllimport unnamed_addr constant i32 1
5+
6+
declare dllimport void @fun()
7+
8+
define available_externally dllimport void @inline1() {
9+
ret void
10+
}
11+
12+
define available_externally dllimport void @inline2() alwaysinline {
13+
ret void
14+
}
15+
16+
declare void @dummy(...)
17+
18+
define void @use() nounwind {
19+
; CHECK: lui $1, %hi(__imp_fun)
20+
; CHECK: addiu $1, $1, %lo(__imp_fun)
21+
; CHECK: lw $25, 0($1)
22+
; CHECK: jalr $25
23+
call void @fun()
24+
25+
; CHECK: lui $1, %hi(__imp_inline1)
26+
; CHECK: addiu $1, $1, %lo(__imp_inline1)
27+
; CHECK: lw $25, 0($1)
28+
; CHECK: jalr $25
29+
call void @inline1()
30+
31+
; CHECK: lui $1, %hi(__imp_inline2)
32+
; CHECK: addiu $1, $1, %lo(__imp_inline2)
33+
; CHECK: lw $25, 0($1)
34+
; CHECK: jalr $25
35+
call void @inline2()
36+
37+
; CHECK: lui $1, %hi(__imp_Var2)
38+
; CHECK: addiu $1, $1, %lo(__imp_Var2)
39+
; CHECK: lw $1, 0($1)
40+
; CHECK: lw $5, 0($1)
41+
; CHECK: lui $1, %hi(__imp_Var1)
42+
; CHECK: addiu $1, $1, %lo(__imp_Var1)
43+
; CHECK: lw $1, 0($1)
44+
; CHECK: lw $4, 0($1)
45+
%1 = load i32, ptr @Var1
46+
%2 = load i32, ptr @Var2
47+
call void(...) @dummy(i32 %1, i32 %2)
48+
49+
ret void
50+
}
51+
52+
; CHECK: fp:
53+
; CHECK-NEXT: .long fun
54+
@fp = constant ptr @fun
55+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: llc -mtriple mipsel-windows -filetype obj < %s | llvm-objdump --reloc - | FileCheck %s
2+
3+
declare dllimport void @fun()
4+
5+
define void @use() nounwind {
6+
; CHECK: 00000008 IMAGE_REL_MIPS_REFHI __imp_fun
7+
; CHECK: 0000000c IMAGE_REL_MIPS_REFLO __imp_fun
8+
call void() @fun()
9+
10+
ret void
11+
}

0 commit comments

Comments
 (0)