Skip to content

Commit

Permalink
[RISCV][GlobalISel] Add lowerFormalArguments for calling convention
Browse files Browse the repository at this point in the history
This patch adds an IncomingValueHandler and IncomingValueAssigner, and implements minimal support for lowering formal arguments according to the RISC-V calling convention. Simple non-aggregate integer and pointer types are supported.

In the future, we must correctly handle byval and sret pointer arguments, and instances where the number of arguments exceeds the number of registers.

Coauthored By: lewis-revill

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D74977
  • Loading branch information
nitinjohnraj committed May 30, 2023
1 parent f46638b commit af8e386
Show file tree
Hide file tree
Showing 2 changed files with 391 additions and 2 deletions.
96 changes: 94 additions & 2 deletions llvm/lib/Target/RISCV/GISel/RISCVCallLowering.cpp
Expand Up @@ -79,6 +79,60 @@ struct RISCVOutgoingValueHandler : public CallLowering::OutgoingValueHandler {
}
};

struct RISCVIncomingValueAssigner : public CallLowering::IncomingValueAssigner {
private:
// The function used internally to assign args - we ignore the AssignFn stored
// by IncomingValueAssigner since RISC-V implements its CC using a custom
// function with a different signature.
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn;

// Whether this is assigning args from a return.
bool IsRet;

public:
RISCVIncomingValueAssigner(
RISCVTargetLowering::RISCVCCAssignFn *RISCVAssignFn_, bool IsRet)
: CallLowering::IncomingValueAssigner(nullptr),
RISCVAssignFn(RISCVAssignFn_), IsRet(IsRet) {}

bool assignArg(unsigned ValNo, EVT OrigVT, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo,
const CallLowering::ArgInfo &Info, ISD::ArgFlagsTy Flags,
CCState &State) override {
MachineFunction &MF = State.getMachineFunction();
const DataLayout &DL = MF.getDataLayout();
const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();

return RISCVAssignFn(DL, Subtarget.getTargetABI(), ValNo, ValVT, LocVT,
LocInfo, Flags, State, /*IsFixed=*/true, IsRet,
Info.Ty, *Subtarget.getTargetLowering(),
/*FirstMaskArgument=*/std::nullopt);
}
};

struct RISCVIncomingValueHandler : public CallLowering::IncomingValueHandler {
RISCVIncomingValueHandler(MachineIRBuilder &B, MachineRegisterInfo &MRI)
: IncomingValueHandler(B, MRI) {}

Register getStackAddress(uint64_t MemSize, int64_t Offset,
MachinePointerInfo &MPO,
ISD::ArgFlagsTy Flags) override {
llvm_unreachable("not implemented");
}

void assignValueToAddress(Register ValVReg, Register Addr, LLT MemTy,
MachinePointerInfo &MPO, CCValAssign &VA) override {
llvm_unreachable("not implemented");
}

void assignValueToReg(Register ValVReg, Register PhysReg,
CCValAssign VA) override {
// Copy argument received in physical register to desired VReg.
MIRBuilder.getMBB().addLiveIn(PhysReg);
MIRBuilder.buildCopy(ValVReg, PhysReg);
}
};

} // namespace

RISCVCallLowering::RISCVCallLowering(const RISCVTargetLowering &TLI)
Expand Down Expand Up @@ -131,11 +185,49 @@ bool RISCVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
const Function &F,
ArrayRef<ArrayRef<Register>> VRegs,
FunctionLoweringInfo &FLI) const {

// Early exit if there are no arguments.
if (F.arg_empty())
return true;

return false;
// TODO: Support vararg functions.
if (F.isVarArg())
return false;

// TODO: Support all argument types.
for (auto &Arg : F.args()) {
if (Arg.getType()->isIntegerTy())
continue;
if (Arg.getType()->isPointerTy())
continue;
return false;
}

MachineFunction &MF = MIRBuilder.getMF();
const DataLayout &DL = MF.getDataLayout();
CallingConv::ID CC = F.getCallingConv();

SmallVector<ArgInfo, 32> SplitArgInfos;
unsigned Index = 0;
for (auto &Arg : F.args()) {
// Construct the ArgInfo object from destination register and argument type.
ArgInfo AInfo(VRegs[Index], Arg.getType(), Index);
setArgFlags(AInfo, Index + AttributeList::FirstArgIndex, DL, F);

// Handle any required merging from split value types from physical
// registers into the desired VReg. ArgInfo objects are constructed
// correspondingly and appended to SplitArgInfos.
splitToValueTypes(AInfo, SplitArgInfos, DL, CC);

++Index;
}

RISCVIncomingValueAssigner Assigner(
CC == CallingConv::Fast ? RISCV::CC_RISCV_FastCC : RISCV::CC_RISCV,
/*IsRet=*/false);
RISCVIncomingValueHandler Handler(MIRBuilder, MF.getRegInfo());

return determineAndHandleAssignments(Handler, Assigner, SplitArgInfos,
MIRBuilder, CC, F.isVarArg());
}

bool RISCVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
Expand Down

0 comments on commit af8e386

Please sign in to comment.