[llvm] [Xtensa] Implement base CallConvention. (PR #83280)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 28 09:25:06 PST 2024
================
@@ -41,10 +41,273 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
setMinFunctionAlignment(Align(4));
+ setBooleanContents(ZeroOrOneBooleanContent);
+
+ // No sign extend instructions for i1
+ for (MVT VT : MVT::integer_valuetypes()) {
+ setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
+ setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
+ setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
+ }
+
// Compute derived properties from the register classes
computeRegisterProperties(STI.getRegisterInfo());
}
+//===----------------------------------------------------------------------===//
+// Calling conventions
+//===----------------------------------------------------------------------===//
+
+#include "XtensaGenCallingConv.inc"
+
+static bool CC_Xtensa_Custom(unsigned ValNo, MVT ValVT, MVT LocVT,
+ CCValAssign::LocInfo LocInfo,
+ ISD::ArgFlagsTy ArgFlags, CCState &State) {
+ static const MCPhysReg IntRegs[] = {Xtensa::A2, Xtensa::A3, Xtensa::A4,
+ Xtensa::A5, Xtensa::A6, Xtensa::A7};
+
+ if (ArgFlags.isByVal()) {
+ Align ByValAlign = ArgFlags.getNonZeroByValAlign();
+ unsigned ByValSize = ArgFlags.getByValSize();
+ if (ByValSize < 4) {
+ ByValSize = 4;
+ }
+ if (ByValAlign < Align(4)) {
+ ByValAlign = Align(4);
+ }
+ unsigned Offset = State.AllocateStack(ByValSize, ByValAlign);
+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
+ // Mark all unused registers as allocated to avoid misuse
+ // of such registers.
+ while (State.AllocateReg(IntRegs))
+ ;
+ return false;
+ }
+
+ // Promote i8 and i16
+ if (LocVT == MVT::i8 || LocVT == MVT::i16) {
+ LocVT = MVT::i32;
+ if (ArgFlags.isSExt())
+ LocInfo = CCValAssign::SExt;
+ else if (ArgFlags.isZExt())
+ LocInfo = CCValAssign::ZExt;
+ else
+ LocInfo = CCValAssign::AExt;
+ }
+
+ unsigned Reg;
+
+ Align OrigAlign = ArgFlags.getNonZeroOrigAlign();
+ bool needs64BitAlign = (ValVT == MVT::i32 && OrigAlign == Align(8));
+ bool needs128BitAlign = (ValVT == MVT::i32 && OrigAlign == Align(16));
+
+ if (ValVT == MVT::i32 || ValVT == MVT::f32) {
+ Reg = State.AllocateReg(IntRegs);
+ // If this is the first part of an i64 arg,
+ // the allocated register must be either A2, A4 or A6.
+ if (needs64BitAlign &&
+ (Reg == Xtensa::A3 || Reg == Xtensa::A5 || Reg == Xtensa::A7))
+ Reg = State.AllocateReg(IntRegs);
+ // arguments with 16byte alignment must be passed in the first register or
+ // passed via stack
+ if (needs128BitAlign && Reg != Xtensa::A2)
+ while ((Reg = State.AllocateReg(IntRegs)))
+ ;
+ LocVT = MVT::i32;
+ } else if (ValVT == MVT::f64) {
+ // Allocate int register and shadow next int register.
+ Reg = State.AllocateReg(IntRegs);
+ if (Reg == Xtensa::A3 || Reg == Xtensa::A5 || Reg == Xtensa::A7)
+ Reg = State.AllocateReg(IntRegs);
+ State.AllocateReg(IntRegs);
+ LocVT = MVT::i32;
+ } else {
+ report_fatal_error("Cannot handle this ValVT.");
+ }
+
+ if (!Reg) {
+ unsigned Offset = State.AllocateStack(ValVT.getStoreSize(), OrigAlign);
+ State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
+ } else {
+ State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+ }
+
+ return false;
+}
+
+CCAssignFn *XtensaTargetLowering::CCAssignFnForCall(CallingConv::ID CC,
+ bool IsVarArg) const {
+ return CC_Xtensa_Custom;
+}
+
+// Value is a value of type VA.getValVT() that we need to copy into
+// the location described by VA. Return a copy of Value converted to
+// VA.getValVT(). The caller is responsible for handling indirect values.
+static SDValue convertValVTToLocVT(SelectionDAG &DAG, SDLoc DL, CCValAssign &VA,
+ SDValue Value) {
+ switch (VA.getLocInfo()) {
----------------
s-barannikov wrote:
It looks like the only possible case here is `CCValAssign::Full`.
https://github.com/llvm/llvm-project/pull/83280
More information about the llvm-commits
mailing list