For the target have f64 registers, but have calling convention passing the f64 type by i32 registers, legalizer will not split the argument.
The target has to define custom calling convention functions to assign f64 type to two location record by CCValAssign structure.
LowerFormalArgument has to generate SDNode to describe how to get input parameters and store in InVals array. Normally, one InputArg assigns to one location, but for the above case, the target has to add custom code to generate SDNode for two locations. Lowercall will need similar effort to deal with it.
If we could split the argument to i32 type during analyzing arguments, we could eliminate the effort and handle it as normal i32 type arguments.
The idea is to add CCAssignToRegWithType interface
which could describe as
CCIfType<[f64], CCAssignToRegWithType<i32, [I0, I1, I2, I3, I4, I5]>>,
The semantic will be: if the first part of i32 type could assign to a register, split the argument into two i32 arguments.
The tablegen result will be:
if (LocVT == MVT::f64) { LocVT = MVT::i32; static const MCPhysReg RegList2[] = { SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5 }; if (unsigned Reg = State.AllocateReg(RegList2)) { State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); State.setCCSplitType(MVT::i32); State.setCCSplit(); return false; }
If State.isCCSplit() is true, call CCState::SplitInputArg and CCState::SplitOutputArg functions to split the argument.
The patch use sparc32 to apply the interface and pass the codegen test cases in llvm/test/Codegen/SPARC.
Any suggestion would be helpful.
If f64 has to be passed with even/odd register pair (i.e., r0 + r1, but not r1 + r2), can CCAssignToRegWithType handle such case?