@@ -9642,10 +9642,8 @@ class RISCVTargetCodeGenInfo : public TargetCodeGenInfo {
9642
9642
namespace {
9643
9643
class XtensaABIInfo : public DefaultABIInfo {
9644
9644
private:
9645
- static const int NumArgGPRs = 6 ;
9646
- static const int MAX_ARG_IN_REGS_SIZE = 4 * 32 ;
9647
- static const int MAX_ARG_DIRECT_SIZE = MAX_ARG_IN_REGS_SIZE;
9648
- static const int MAX_RET_IN_REGS_SIZE = 2 * 32 ;
9645
+ static const int MaxNumArgGPRs = 6 ;
9646
+ static const int MaxNumRetGPRs = 4 ;
9649
9647
9650
9648
public:
9651
9649
XtensaABIInfo (CodeGen::CodeGenTypes &CGT) : DefaultABIInfo(CGT) {}
@@ -9654,8 +9652,8 @@ class XtensaABIInfo : public DefaultABIInfo {
9654
9652
// non-virtual, but computeInfo is virtual, so we overload it.
9655
9653
void computeInfo (CGFunctionInfo &FI) const override ;
9656
9654
9657
- ABIArgInfo classifyArgumentType (QualType Ty, bool IsFixed,
9658
- int &ArgGPRsLeft) const ;
9655
+ ABIArgInfo classifyArgumentType (QualType Ty, int &ArgGPRsLeft) const ;
9656
+
9659
9657
ABIArgInfo classifyReturnType (QualType RetTy) const ;
9660
9658
9661
9659
Address EmitVAArg (CodeGenFunction &CGF, Address VAListAddr,
@@ -9669,31 +9667,16 @@ void XtensaABIInfo::computeInfo(CGFunctionInfo &FI) const {
9669
9667
QualType RetTy = FI.getReturnType ();
9670
9668
if (!getCXXABI ().classifyReturnType (FI))
9671
9669
FI.getReturnInfo () = classifyReturnType (RetTy);
9672
- // IsRetIndirect is true if classifyArgumentType indicated the value should
9673
- // be passed indirect or if the type size is greater than 2*32.
9674
- // is passed direct in LLVM IR, relying on the backend lowering code to
9675
- // rewrite the argument list and pass indirectly on RV32.
9676
- bool IsRetIndirect = FI.getReturnInfo ().getKind () == ABIArgInfo::Indirect ||
9677
- getContext ().getTypeSize (RetTy) > MAX_RET_IN_REGS_SIZE;
9678
- // We must track the number of GPRs used in order to conform to the Xtensa
9679
- // ABI, as integer scalars passed in registers should have signext/zeroext
9680
- // when promoted, but are anyext if passed on the stack. As GPR usage is
9681
- // different for variadic arguments, we must also track whether we are
9682
- // examining a vararg or not.
9683
- int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;
9684
- int NumFixedArgs = FI.getNumRequiredArgs ();
9685
- int ArgNum = 0 ;
9670
+
9671
+ int ArgGPRsLeft = MaxNumArgGPRs;
9686
9672
for (auto &ArgInfo : FI.arguments ()) {
9687
- bool IsFixed = ArgNum < NumFixedArgs;
9688
- ArgInfo.info = classifyArgumentType (ArgInfo.type , IsFixed, ArgGPRsLeft);
9689
- ArgNum++;
9673
+ ArgInfo.info = classifyArgumentType (ArgInfo.type , ArgGPRsLeft);
9690
9674
}
9691
9675
}
9692
9676
9693
- ABIArgInfo XtensaABIInfo::classifyArgumentType (QualType Ty, bool IsFixed,
9677
+ ABIArgInfo XtensaABIInfo::classifyArgumentType (QualType Ty,
9694
9678
int &ArgGPRsLeft) const {
9695
- assert (ArgGPRsLeft <= NumArgGPRs && " Arg GPR tracking underflow" );
9696
-
9679
+ assert (ArgGPRsLeft <= MaxNumArgGPRs && " Arg GPR tracking underflow" );
9697
9680
Ty = useFirstFieldIfTransparentUnion (Ty);
9698
9681
// Structures with either a non-trivial destructor or a non-trivial
9699
9682
// copy constructor are always passed indirectly.
@@ -9703,26 +9686,26 @@ ABIArgInfo XtensaABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
9703
9686
return getNaturalAlignIndirect (Ty, /* ByVal=*/ RAA ==
9704
9687
CGCXXABI::RAA_DirectInMemory);
9705
9688
}
9689
+
9706
9690
// Ignore empty structs/unions.
9707
9691
if (isEmptyRecord (getContext (), Ty, true ))
9708
9692
return ABIArgInfo::getIgnore ();
9693
+
9709
9694
uint64_t Size = getContext ().getTypeSize (Ty);
9710
9695
uint64_t NeededAlign = getContext ().getTypeAlign (Ty);
9711
9696
bool MustUseStack = false ;
9712
- // Determine the number of GPRs needed to pass the current argument
9713
- // according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
9714
- // register pairs, so may consume 3 registers.
9715
- int NeededArgGPRs = 1 ;
9716
- if (!IsFixed && NeededAlign == 2 * 32 )
9717
- NeededArgGPRs = 2 + (ArgGPRsLeft % 2 );
9718
- else if (Size > 32 && Size <= MAX_ARG_IN_REGS_SIZE)
9719
- NeededArgGPRs = (Size + 31 ) / 32 ;
9720
- if (NeededArgGPRs > ArgGPRsLeft) {
9697
+ int NeededArgGPRs = (Size + 31 ) / 32 ;
9698
+
9699
+ if (NeededAlign == 2 * 32 )
9700
+ NeededArgGPRs += (ArgGPRsLeft % 2 );
9701
+
9702
+ if ((NeededArgGPRs > ArgGPRsLeft) || (NeededAlign > 2 * 32 )) {
9721
9703
MustUseStack = true ;
9722
9704
NeededArgGPRs = ArgGPRsLeft;
9723
9705
}
9724
9706
ArgGPRsLeft -= NeededArgGPRs;
9725
- if (!isAggregateTypeForABI (Ty) && !Ty->isVectorType ()) {
9707
+
9708
+ if (!isAggregateTypeForABI (Ty) && !Ty->isVectorType () && !MustUseStack) {
9726
9709
// Treat an enum type as its underlying type.
9727
9710
if (const EnumType *EnumTy = Ty->getAs <EnumType>())
9728
9711
Ty = EnumTy->getDecl ()->getIntegerType ();
@@ -9731,76 +9714,127 @@ ABIArgInfo XtensaABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
9731
9714
if (Size < 32 && Ty->isIntegralOrEnumerationType () && !MustUseStack) {
9732
9715
return extendType (Ty);
9733
9716
}
9734
- return ABIArgInfo::getDirect ();
9717
+ if (Size == 64 )
9718
+ return ABIArgInfo::getDirect (llvm::IntegerType::get (getVMContext (), 64 ));
9719
+ return ABIArgInfo::getDirect (llvm::IntegerType::get (getVMContext (), 32 ));
9735
9720
}
9736
9721
9737
- // Aggregates which are <= 4 *32 will be passed in registers if possible,
9722
+ // Aggregates which are <= 6 *32 will be passed in registers if possible,
9738
9723
// so coerce to integers.
9739
- if (Size <= MAX_ARG_IN_REGS_SIZE) {
9740
- unsigned Alignment = getContext ().getTypeAlign (Ty);
9741
- // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is
9742
- // required, and a 2-element XLen array if only XLen alignment is
9743
- // required.
9724
+ if ((Size <= (MaxNumArgGPRs * 32 )) && (!MustUseStack)) {
9744
9725
if (Size <= 32 ) {
9745
9726
return ABIArgInfo::getDirect (llvm::IntegerType::get (getVMContext (), 32 ));
9746
- }
9747
-
9748
- else if (Alignment == 2 * 32 ) {
9749
- return ABIArgInfo::getDirect (
9750
- llvm::IntegerType::get (getVMContext (), 2 * 32 ));
9751
9727
} else {
9752
9728
return ABIArgInfo::getDirect (llvm::ArrayType::get (
9753
- llvm::IntegerType::get (getVMContext (), 32 ), (Size + 31 ) / 32 ));
9729
+ llvm::IntegerType::get (getVMContext (), 32 ), NeededArgGPRs ));
9754
9730
}
9755
9731
}
9756
9732
#undef MAX_STRUCT_IN_REGS_SIZE
9757
- return getNaturalAlignIndirect (Ty, /* ByVal=*/ false );
9733
+ return getNaturalAlignIndirect (Ty, /* ByVal=*/ true );
9758
9734
}
9759
9735
9760
9736
ABIArgInfo XtensaABIInfo::classifyReturnType (QualType RetTy) const {
9761
9737
if (RetTy->isVoidType ())
9762
9738
return ABIArgInfo::getIgnore ();
9763
- int ArgGPRsLeft = 2 ;
9739
+ int ArgGPRsLeft = MaxNumRetGPRs ;
9764
9740
// The rules for return and argument types are the same, so defer to
9765
9741
// classifyArgumentType.
9766
- return classifyArgumentType (RetTy, /* IsFixed= */ true , ArgGPRsLeft);
9742
+ return classifyArgumentType (RetTy, ArgGPRsLeft);
9767
9743
}
9768
9744
9769
9745
Address XtensaABIInfo::EmitVAArg (CodeGenFunction &CGF, Address VAListAddr,
9770
9746
QualType Ty) const {
9771
- CharUnits SlotSize = CharUnits::fromQuantity (32 / 8 );
9772
- // Empty records are ignored for parameter passing purposes.
9773
- if (isEmptyRecord (getContext (), Ty, true )) {
9774
- // We try to return some dummy value which will be
9775
- // removed by backend
9747
+ // The va_list structure memory layout:
9748
+ // struct __va_list_tag {
9749
+ // int32_t *va_stk;
9750
+ // int32_t *va_reg;
9751
+ // int32_t va_ndx;
9752
+ // };
9753
+ CGBuilderTy &Builder = CGF.Builder ;
9754
+
9755
+ Address OverflowAreaPtr = Builder.CreateStructGEP (VAListAddr, 0 , " __va_stk" );
9756
+ Address OverflowArea = Address (Builder.CreateLoad (OverflowAreaPtr, " " ),
9757
+ CharUnits::fromQuantity (4 ));
9758
+ Address RegSaveAreaPtr = Builder.CreateStructGEP (VAListAddr, 1 , " __va_reg" );
9759
+ Address RegSaveArea = Address (Builder.CreateLoad (RegSaveAreaPtr, " " ),
9760
+ CharUnits::fromQuantity (4 ));
9761
+ Address ARAreaPtr = Builder.CreateStructGEP (VAListAddr, 2 , " __va_ndx" );
9762
+ llvm::Value *ARIndex = Builder.CreateLoad (ARAreaPtr, " " );
9763
+
9764
+ ARIndex = Builder.CreateLShr (ARIndex, Builder.getInt32 (2 ));
9776
9765
9777
- auto TypeInfo = getContext ().getTypeInfoInChars (Ty);
9778
- return emitVoidPtrVAArg (CGF, VAListAddr, Ty, false , TypeInfo, SlotSize,
9779
- /* AllowHigherAlign=*/ false );
9766
+ unsigned Align = getContext ().getTypeAlign (Ty) / 32 ;
9767
+ unsigned Size = (getContext ().getTypeSize (Ty) + 31 ) / 32 ;
9768
+
9769
+ if (Align > 1 ) {
9770
+ ARIndex = Builder.CreateAdd (ARIndex, Builder.getInt32 (Align - 1 ));
9771
+ ARIndex =
9772
+ Builder.CreateAnd (ARIndex, Builder.getInt32 ((uint32_t ) ~(Align - 1 )));
9780
9773
}
9781
9774
9782
- std::pair<CharUnits, CharUnits> SizeAndAlign =
9783
- getContext ().getTypeInfoInChars (Ty);
9784
- // Arguments bigger than MAX_STRUCT_DIRECT_SIZE indirectly.
9785
- CharUnits DirectSize = CharUnits::fromQuantity (MAX_ARG_DIRECT_SIZE / 8 );
9786
- bool IsIndirect = SizeAndAlign.first > DirectSize;
9775
+ llvm::Value *ARIndexNext = Builder.CreateAdd (ARIndex, Builder.getInt32 (Size));
9776
+ Builder.CreateStore (Builder.CreateShl (ARIndexNext, Builder.getInt32 (2 )),
9777
+ ARAreaPtr);
9787
9778
9788
- if (IsIndirect) {
9789
- auto TyInfo = CGF. getContext (). getTypeInfoInChars (Ty);
9790
- CharUnits TyAlignForABI = TyInfo. second ;
9779
+ const unsigned OverflowLimit = 6 ;
9780
+ llvm::Value *CC = Builder. CreateICmpULE (
9781
+ ARIndexNext, Builder. getInt32 (OverflowLimit), " cond " ) ;
9791
9782
9792
- llvm::Type *BaseTy =
9793
- llvm::PointerType::getUnqual (CGF.ConvertTypeForMem (Ty));
9794
- llvm::Value *Addr =
9795
- CGF.Builder .CreateVAArg (VAListAddr.getPointer (), BaseTy);
9796
- return Address (Addr, TyAlignForABI);
9797
- } else {
9798
- Address Temp = CGF.CreateMemTemp (Ty, " varet" );
9799
- llvm::Value *Val =
9800
- CGF.Builder .CreateVAArg (VAListAddr.getPointer (), CGF.ConvertType (Ty));
9801
- CGF.Builder .CreateStore (Val, Temp);
9802
- return Temp;
9783
+ llvm::BasicBlock *UsingRegSaveArea =
9784
+ CGF.createBasicBlock (" using_regsavearea" );
9785
+ llvm::BasicBlock *UsingOverflow = CGF.createBasicBlock (" using_overflow" );
9786
+ llvm::BasicBlock *Cont = CGF.createBasicBlock (" cont" );
9787
+
9788
+ Builder.CreateCondBr (CC, UsingRegSaveArea, UsingOverflow);
9789
+
9790
+ llvm::Type *DirectTy = CGF.ConvertType (Ty);
9791
+
9792
+ // Case 1: consume registers.
9793
+ Address RegAddr = Address::invalid ();
9794
+ {
9795
+ CGF.EmitBlock (UsingRegSaveArea);
9796
+
9797
+ CharUnits RegSize = CharUnits::fromQuantity (4 );
9798
+ RegSaveArea =
9799
+ Address (Builder.CreateInBoundsGEP (CGF.Int32Ty , RegSaveArea.getPointer (),
9800
+ ARIndex),
9801
+ RegSaveArea.getAlignment ().alignmentOfArrayElement (RegSize));
9802
+ RegAddr = Builder.CreateElementBitCast (RegSaveArea, DirectTy);
9803
+ CGF.EmitBranch (Cont);
9803
9804
}
9805
+
9806
+ // Case 2: consume space in the overflow area.
9807
+ Address MemAddr = Address::invalid ();
9808
+ {
9809
+ CGF.EmitBlock (UsingOverflow);
9810
+ llvm::Value *CC1 = Builder.CreateICmpULE (
9811
+ ARIndex, Builder.getInt32 (OverflowLimit), " cond_overflow" );
9812
+
9813
+ llvm::Value *ARIndexOff = Builder.CreateSelect (
9814
+ CC1, Builder.CreateSub (Builder.getInt32 (8 ), ARIndex),
9815
+ Builder.getInt32 (0 ));
9816
+
9817
+ llvm::Value *ARIndexCorr = Builder.CreateAdd (ARIndex, ARIndexOff);
9818
+ llvm::Value *ARIndexNextCorr = Builder.CreateAdd (ARIndexNext, ARIndexOff);
9819
+ Builder.CreateStore (Builder.CreateShl (ARIndexNextCorr, Builder.getInt32 (2 )),
9820
+ ARAreaPtr);
9821
+
9822
+ CharUnits RegSize = CharUnits::fromQuantity (4 );
9823
+ OverflowArea =
9824
+ Address (Builder.CreateInBoundsGEP (
9825
+ CGF.Int32Ty , OverflowArea.getPointer (), ARIndexCorr),
9826
+ OverflowArea.getAlignment ().alignmentOfArrayElement (RegSize));
9827
+ MemAddr = Builder.CreateElementBitCast (OverflowArea, DirectTy);
9828
+ CGF.EmitBranch (Cont);
9829
+ }
9830
+
9831
+ CGF.EmitBlock (Cont);
9832
+
9833
+ // Merge the cases with a phi.
9834
+ Address Result =
9835
+ emitMergePHI (CGF, RegAddr, UsingRegSaveArea, MemAddr, UsingOverflow, " " );
9836
+
9837
+ return Result;
9804
9838
}
9805
9839
9806
9840
ABIArgInfo XtensaABIInfo::extendType (QualType Ty) const {
0 commit comments