Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -1462,9 +1462,28 @@ // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't // split it and then direct call can be matched by PseudoCALL. if (GlobalAddressSDNode *S = dyn_cast(Callee)) { - Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); + const GlobalValue *GV = S->getGlobal(); + unsigned OpFlags = Subtarget + .classifyFunctionReference(*GV->getParent(), GV); + + Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags); + + if (OpFlags == RISCVII::MO_GOT_HI) { + Callee = DAG.getNode(RISCVISD::WRAPPER_PCREL, DL, PtrVT, Callee); + Callee = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Callee, + MachinePointerInfo()); + } } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, 0); + unsigned OpFlags = Subtarget + .classifyFunctionReference(*MF.getFunction().getParent(), nullptr); + + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, OpFlags); + + if (OpFlags == RISCVII::MO_GOT_HI) { + Callee = DAG.getNode(RISCVISD::WRAPPER_PCREL, DL, PtrVT, Callee); + Callee = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Callee, + MachinePointerInfo()); + } } // The first call operand is the chain and the second is the target address. Index: lib/Target/RISCV/RISCVMCInstLower.cpp =================================================================== --- lib/Target/RISCV/RISCVMCInstLower.cpp +++ lib/Target/RISCV/RISCVMCInstLower.cpp @@ -52,6 +52,9 @@ case RISCVII::MO_GOT_HI: Kind = RISCVMCExpr::VK_RISCV_GOT_HI; break; + case RISCVII::MO_PLT: + Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; + break; } const MCExpr *ME = Index: lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- lib/Target/RISCV/RISCVSubtarget.h +++ lib/Target/RISCV/RISCVSubtarget.h @@ -44,6 +44,7 @@ RISCVRegisterInfo RegInfo; RISCVTargetLowering TLInfo; SelectionDAGTargetInfo TSInfo; + const TargetMachine &TM; /// Initializes using the passed in CPU and feature strings so that we can /// use initializer lists for subtarget initialization. @@ -81,6 +82,9 @@ bool enableLinkerRelax() const { return EnableLinkerRelax; } MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } + + unsigned classifyFunctionReference(const Module &M, + const GlobalValue *GV) const; }; } // End llvm namespace Index: lib/Target/RISCV/RISCVSubtarget.cpp =================================================================== --- lib/Target/RISCV/RISCVSubtarget.cpp +++ lib/Target/RISCV/RISCVSubtarget.cpp @@ -45,4 +45,16 @@ const std::string &FS, const TargetMachine &TM) : RISCVGenSubtargetInfo(TT, CPU, FS), FrameLowering(initializeSubtargetDependencies(CPU, FS, TT.isArch64Bit())), - InstrInfo(), RegInfo(getHwMode()), TLInfo(TM, *this) {} + InstrInfo(), RegInfo(getHwMode()), TLInfo(TM, *this), TM(TM) {} + +unsigned +RISCVSubtarget::classifyFunctionReference(const Module &M, + const GlobalValue *GV) const { + if (TM.shouldAssumeDSOLocal(M, GV)) + return 0u; + + if (M.getRtLibUseGOT()) + return RISCVII::MO_GOT_HI; + + return RISCVII::MO_PLT; +} \ No newline at end of file Index: lib/Target/RISCV/Utils/RISCVBaseInfo.h =================================================================== --- lib/Target/RISCV/Utils/RISCVBaseInfo.h +++ lib/Target/RISCV/Utils/RISCVBaseInfo.h @@ -54,6 +54,7 @@ MO_PCREL_LO, MO_PCREL_HI, MO_GOT_HI, + MO_PLT, }; } // namespace RISCVII