Skip to content

Commit

Permalink
[H2BLB][SDISel] Call lowering with stack arguments
Browse files Browse the repository at this point in the history
This commit implements the lowering of calls when these have stack arguments.
The change consists in mainly three things:
1. Populate the CALLSEQ_START/END instructions with the amount of stack space
   required to hold the outgoing arguments.
2. Issue the stores that populate the stack space with the arguments
3. Assert that the frame lowering used the reserved call mode. This mode
   allocate the stack space required for all the calls within the current
   function in the prologue. Without this mode, we would need to adjust
   the stack pointer before and after each call.
  • Loading branch information
qcolombet committed Oct 20, 2024
1 parent 7e50b0c commit 8d16571
Show file tree
Hide file tree
Showing 4 changed files with 388 additions and 22 deletions.
7 changes: 4 additions & 3 deletions llvm/lib/Target/H2BLB/H2BLBFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ MachineBasicBlock::iterator H2BLBFrameLowering::eliminateCallFramePseudoInstr(
const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
unsigned Opc = MI->getOpcode();

// The call frame should always be included in the stack frame in the
// prologue.
assert(hasReservedCallFrame(MF) && "H2BLB doesn't have a FP register");

if (Opc != TII->getCallFrameSetupOpcode() &&
Opc != TII->getCallFrameDestroyOpcode())
report_fatal_error("Unexpected frame pseudo instruction");

if (MI->getOperand(0).getImm() != 0)
report_fatal_error("Proper frame lowering not yet implemented");

if (MI->getOperand(1).getImm() != 0)
report_fatal_error("Callee pop count not supported");

Expand Down
41 changes: 29 additions & 12 deletions llvm/lib/Target/H2BLB/H2BLBISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ SDValue H2BLBTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
SDValue Callee = CLI.Callee;
CallingConv::ID CallConv = CLI.CallConv;
MachineFunction &MF = DAG.getMachineFunction();
SDLoc &DL = CLI.DL;

// H2BLB target does not support tail call optimization.
CLI.IsTailCall = false;
Expand Down Expand Up @@ -205,8 +206,15 @@ SDValue H2BLBTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
}

SDValue InGlue;
// Now that we collected all the registers, start the call sequence.
auto PtrVT = getPointerTy(MF.getDataLayout());
Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);

SDValue StackPtr = DAG.getCopyFromReg(Chain, DL, H2BLB::SP,
getPointerTy(DAG.getDataLayout()));

SmallVector<std::pair<Register, SDValue>> RegsToPass;
SmallVector<SDValue, 8> MemOpChains;

// Walk arg assignments
for (size_t i = 0, e = ArgLocs.size(); i != e; ++i) {
Expand All @@ -223,28 +231,38 @@ SDValue H2BLBTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
continue;
}
assert(VA.isMemLoc() && "Expected stack argument");
report_fatal_error("stack arguments not yet implemented");
SDValue DstAddr;
MachinePointerInfo DstInfo;

unsigned OpSize = VA.getValVT().getSizeInBits();
OpSize = (OpSize + 7) / 8;
unsigned LocMemOffset = VA.getLocMemOffset();
SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset, DL);
DstAddr = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
DstInfo = MachinePointerInfo::getStack(MF, LocMemOffset);

SDValue Store = DAG.getStore(Chain, DL, Arg, DstAddr, DstInfo);
MemOpChains.push_back(Store);
}

// Now that we collected all the registers, start the call sequence.
auto PtrVT = getPointerTy(MF.getDataLayout());
Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
if (!MemOpChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);

// Build a sequence of copy-to-reg nodes chained together with token chain
// and flag operands which copy the outgoing args into the appropriate regs.
// We do this and not in the previous loop to chain the registers as close
// as possible to the actual call.
for (auto &RegToPass : RegsToPass) {
Chain = DAG.getCopyToReg(Chain, CLI.DL, RegToPass.first, RegToPass.second,
InGlue);
Chain =
DAG.getCopyToReg(Chain, DL, RegToPass.first, RegToPass.second, InGlue);
InGlue = Chain.getValue(1);
}

// If the callee is a GlobalAddress node (quite common, every direct call is)
// turn it into a TargetGlobalAddress node so that all the generic code cannot
// mess with it.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT,
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT,
G->getOffset(), 0);
else
report_fatal_error("non-direct calls not implemented");
Expand All @@ -269,14 +287,14 @@ SDValue H2BLBTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,

// The call will return a chain & a flag for retval copies to use.
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Chain = DAG.getNode(H2BLBISD::CALL, CLI.DL, NodeTys, Ops);
Chain = DAG.getNode(H2BLBISD::CALL, DL, NodeTys, Ops);
InGlue = Chain.getValue(1);

// Propagate any NoMerge attribute that we may have.
DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);

// Finish the call sequence.
Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, CLI.DL);
Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
InGlue = Chain.getValue(1);

// Assign locations to each value returned by this call.
Expand All @@ -292,9 +310,8 @@ SDValue H2BLBTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
assert(VA.getLocInfo() == CCValAssign::Full &&
"extension/truncation of any sort, not yet implemented");

Chain =
DAG.getCopyFromReg(Chain, CLI.DL, VA.getLocReg(), VA.getValVT(), InGlue)
.getValue(1);
Chain = DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getValVT(), InGlue)
.getValue(1);

// Guarantee that all emitted copies are stuck together,
// avoiding something bad.
Expand Down
Loading

0 comments on commit 8d16571

Please sign in to comment.