Skip to content

[Mips] Handle declspec(dllimport) on mipsel-windows-* triples #120912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion llvm/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
17 changes: 16 additions & 1 deletion llvm/lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *>(
Expand Down Expand Up @@ -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();

Expand Down
27 changes: 27 additions & 0 deletions llvm/lib/Target/Mips/MipsISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
14 changes: 12 additions & 2 deletions llvm/lib/Target/Mips/MipsMCInstLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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:
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Mips/MipsSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -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; }

Expand Down
55 changes: 55 additions & 0 deletions llvm/test/CodeGen/Mips/dllimport.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
; RUN: llc -mtriple mipsel-windows < %s | FileCheck %s

@Var1 = external dllimport global i32
@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
@fp = constant ptr @fun

11 changes: 11 additions & 0 deletions llvm/test/MC/Mips/coff-relocs-dllimport.ll
Original file line number Diff line number Diff line change
@@ -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
}
Loading