Skip to content

Commit

Permalink
[GlobalISel] add helper function to create arbitrary libcalls
Browse files Browse the repository at this point in the history
Summary:
The existing helper function can only create a libcall to functions available in
RTLIB. Add a helper function that can create a libcall to a given function name
using the provided calling convention.

Reviewers: aditya_nandakumar, t.p.northover, rovka, arsenm, dsanders

Reviewed By: arsenm

Subscribers: wdng, hiraditya, volkan, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D76845
  • Loading branch information
gargaroff committed Mar 26, 2020
1 parent 0bd1276 commit 9fedb69
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
7 changes: 7 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
Expand Up @@ -304,6 +304,13 @@ class LegalizerHelper {
GISelChangeObserver &Observer;
};

/// Helper function that creates a libcall to the given \p Name using the given
/// calling convention \p CC.
LegalizerHelper::LegalizeResult
createLibcall(MachineIRBuilder &MIRBuilder, const char *Name,
const CallLowering::ArgInfo &Result,
ArrayRef<CallLowering::ArgInfo> Args, CallingConv::ID CC);

/// Helper function that creates the given libcall.
LegalizerHelper::LegalizeResult
createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
Expand Down
19 changes: 14 additions & 5 deletions llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
Expand Up @@ -489,15 +489,14 @@ static bool isLibCallInTailPosition(MachineInstr &MI) {
}

LegalizerHelper::LegalizeResult
llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
llvm::createLibcall(MachineIRBuilder &MIRBuilder, const char *Name,
const CallLowering::ArgInfo &Result,
ArrayRef<CallLowering::ArgInfo> Args) {
ArrayRef<CallLowering::ArgInfo> Args,
const CallingConv::ID CC) {
auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
const char *Name = TLI.getLibcallName(Libcall);

CallLowering::CallLoweringInfo Info;
Info.CallConv = TLI.getLibcallCallingConv(Libcall);
Info.CallConv = CC;
Info.Callee = MachineOperand::CreateES(Name);
Info.OrigRet = Result;
std::copy(Args.begin(), Args.end(), std::back_inserter(Info.OrigArgs));
Expand All @@ -507,6 +506,16 @@ llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
return LegalizerHelper::Legalized;
}

LegalizerHelper::LegalizeResult
llvm::createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
const CallLowering::ArgInfo &Result,
ArrayRef<CallLowering::ArgInfo> Args) {
auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
const char *Name = TLI.getLibcallName(Libcall);
const CallingConv::ID CC = TLI.getLibcallCallingConv(Libcall);
return createLibcall(MIRBuilder, Name, Result, Args, CC);
}

// Useful for libcalls where all operands have the same type.
static LegalizerHelper::LegalizeResult
simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
Expand Down
26 changes: 26 additions & 0 deletions llvm/unittests/CodeGen/GlobalISel/LegalizerHelperTest.cpp
Expand Up @@ -2722,4 +2722,30 @@ TEST_F(AArch64GISelMITest, BitcastBitOps) {
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
}

TEST_F(AArch64GISelMITest, CreateLibcall) {
setUp();
if (!TM)
return;

DefineLegalizerInfo(A, {});

AInfo Info(MF->getSubtarget());
DummyGISelObserver Observer;

LLVMContext &Ctx = MF->getFunction().getContext();
auto *RetTy = Type::getVoidTy(Ctx);

EXPECT_EQ(LegalizerHelper::LegalizeResult::Legalized,
createLibcall(B, "abort", {{}, RetTy}, {}, CallingConv::C));

auto CheckStr = R"(
CHECK: ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
CHECK: BL &abort
CHECK: ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
)";

// Check
EXPECT_TRUE(CheckMachineFunction(*MF, CheckStr)) << *MF;
}

} // namespace

0 comments on commit 9fedb69

Please sign in to comment.