106c3fb27SDimitry Andric //===- CSKY.cpp -----------------------------------------------------------===// 206c3fb27SDimitry Andric // 306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606c3fb27SDimitry Andric // 706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 806c3fb27SDimitry Andric 906c3fb27SDimitry Andric #include "ABIInfoImpl.h" 1006c3fb27SDimitry Andric #include "TargetInfo.h" 1106c3fb27SDimitry Andric 1206c3fb27SDimitry Andric using namespace clang; 1306c3fb27SDimitry Andric using namespace clang::CodeGen; 1406c3fb27SDimitry Andric 1506c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1606c3fb27SDimitry Andric // CSKY ABI Implementation 1706c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 1806c3fb27SDimitry Andric namespace { 1906c3fb27SDimitry Andric class CSKYABIInfo : public DefaultABIInfo { 2006c3fb27SDimitry Andric static const int NumArgGPRs = 4; 2106c3fb27SDimitry Andric static const int NumArgFPRs = 4; 2206c3fb27SDimitry Andric 2306c3fb27SDimitry Andric static const unsigned XLen = 32; 2406c3fb27SDimitry Andric unsigned FLen; 2506c3fb27SDimitry Andric 2606c3fb27SDimitry Andric public: 2706c3fb27SDimitry Andric CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen) 2806c3fb27SDimitry Andric : DefaultABIInfo(CGT), FLen(FLen) {} 2906c3fb27SDimitry Andric 3006c3fb27SDimitry Andric void computeInfo(CGFunctionInfo &FI) const override; 3106c3fb27SDimitry Andric ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft, 3206c3fb27SDimitry Andric int &ArgFPRsLeft, 3306c3fb27SDimitry Andric bool isReturnType = false) const; 3406c3fb27SDimitry Andric ABIArgInfo classifyReturnType(QualType RetTy) const; 3506c3fb27SDimitry Andric 36*0fca6ea1SDimitry Andric RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 37*0fca6ea1SDimitry Andric AggValueSlot Slot) const override; 3806c3fb27SDimitry Andric }; 3906c3fb27SDimitry Andric 4006c3fb27SDimitry Andric } // end anonymous namespace 4106c3fb27SDimitry Andric 4206c3fb27SDimitry Andric void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const { 4306c3fb27SDimitry Andric QualType RetTy = FI.getReturnType(); 4406c3fb27SDimitry Andric if (!getCXXABI().classifyReturnType(FI)) 4506c3fb27SDimitry Andric FI.getReturnInfo() = classifyReturnType(RetTy); 4606c3fb27SDimitry Andric 4706c3fb27SDimitry Andric bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect; 4806c3fb27SDimitry Andric 4906c3fb27SDimitry Andric // We must track the number of GPRs used in order to conform to the CSKY 5006c3fb27SDimitry Andric // ABI, as integer scalars passed in registers should have signext/zeroext 5106c3fb27SDimitry Andric // when promoted. 5206c3fb27SDimitry Andric int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs; 5306c3fb27SDimitry Andric int ArgFPRsLeft = FLen ? NumArgFPRs : 0; 5406c3fb27SDimitry Andric 5506c3fb27SDimitry Andric for (auto &ArgInfo : FI.arguments()) { 5606c3fb27SDimitry Andric ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft); 5706c3fb27SDimitry Andric } 5806c3fb27SDimitry Andric } 5906c3fb27SDimitry Andric 60*0fca6ea1SDimitry Andric RValue CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 61*0fca6ea1SDimitry Andric QualType Ty, AggValueSlot Slot) const { 6206c3fb27SDimitry Andric CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8); 6306c3fb27SDimitry Andric 6406c3fb27SDimitry Andric // Empty records are ignored for parameter passing purposes. 65*0fca6ea1SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 66*0fca6ea1SDimitry Andric return Slot.asRValue(); 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric auto TInfo = getContext().getTypeInfoInChars(Ty); 6906c3fb27SDimitry Andric 7006c3fb27SDimitry Andric return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize, 71*0fca6ea1SDimitry Andric /*AllowHigherAlign=*/true, Slot); 7206c3fb27SDimitry Andric } 7306c3fb27SDimitry Andric 7406c3fb27SDimitry Andric ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, 7506c3fb27SDimitry Andric int &ArgFPRsLeft, 7606c3fb27SDimitry Andric bool isReturnType) const { 7706c3fb27SDimitry Andric assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); 7806c3fb27SDimitry Andric Ty = useFirstFieldIfTransparentUnion(Ty); 7906c3fb27SDimitry Andric 8006c3fb27SDimitry Andric // Structures with either a non-trivial destructor or a non-trivial 8106c3fb27SDimitry Andric // copy constructor are always passed indirectly. 8206c3fb27SDimitry Andric if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 8306c3fb27SDimitry Andric if (ArgGPRsLeft) 8406c3fb27SDimitry Andric ArgGPRsLeft -= 1; 8506c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == 8606c3fb27SDimitry Andric CGCXXABI::RAA_DirectInMemory); 8706c3fb27SDimitry Andric } 8806c3fb27SDimitry Andric 8906c3fb27SDimitry Andric // Ignore empty structs/unions. 9006c3fb27SDimitry Andric if (isEmptyRecord(getContext(), Ty, true)) 9106c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 9206c3fb27SDimitry Andric 9306c3fb27SDimitry Andric if (!Ty->getAsUnionType()) 9406c3fb27SDimitry Andric if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) 9506c3fb27SDimitry Andric return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); 9606c3fb27SDimitry Andric 9706c3fb27SDimitry Andric uint64_t Size = getContext().getTypeSize(Ty); 9806c3fb27SDimitry Andric // Pass floating point values via FPRs if possible. 9906c3fb27SDimitry Andric if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size && 10006c3fb27SDimitry Andric ArgFPRsLeft) { 10106c3fb27SDimitry Andric ArgFPRsLeft--; 10206c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 10306c3fb27SDimitry Andric } 10406c3fb27SDimitry Andric 10506c3fb27SDimitry Andric // Complex types for the hard float ABI must be passed direct rather than 10606c3fb27SDimitry Andric // using CoerceAndExpand. 10706c3fb27SDimitry Andric if (Ty->isComplexType() && FLen && !isReturnType) { 10806c3fb27SDimitry Andric QualType EltTy = Ty->castAs<ComplexType>()->getElementType(); 10906c3fb27SDimitry Andric if (getContext().getTypeSize(EltTy) <= FLen) { 11006c3fb27SDimitry Andric ArgFPRsLeft -= 2; 11106c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 11206c3fb27SDimitry Andric } 11306c3fb27SDimitry Andric } 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric if (!isAggregateTypeForABI(Ty)) { 11606c3fb27SDimitry Andric // Treat an enum type as its underlying type. 11706c3fb27SDimitry Andric if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 11806c3fb27SDimitry Andric Ty = EnumTy->getDecl()->getIntegerType(); 11906c3fb27SDimitry Andric 12006c3fb27SDimitry Andric // All integral types are promoted to XLen width, unless passed on the 12106c3fb27SDimitry Andric // stack. 12206c3fb27SDimitry Andric if (Size < XLen && Ty->isIntegralOrEnumerationType()) 12306c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 12406c3fb27SDimitry Andric 12506c3fb27SDimitry Andric if (const auto *EIT = Ty->getAs<BitIntType>()) { 12606c3fb27SDimitry Andric if (EIT->getNumBits() < XLen) 12706c3fb27SDimitry Andric return ABIArgInfo::getExtend(Ty); 12806c3fb27SDimitry Andric } 12906c3fb27SDimitry Andric 13006c3fb27SDimitry Andric return ABIArgInfo::getDirect(); 13106c3fb27SDimitry Andric } 13206c3fb27SDimitry Andric 13306c3fb27SDimitry Andric // For argument type, the first 4*XLen parts of aggregate will be passed 13406c3fb27SDimitry Andric // in registers, and the rest will be passed in stack. 13506c3fb27SDimitry Andric // So we can coerce to integers directly and let backend handle it correctly. 13606c3fb27SDimitry Andric // For return type, aggregate which <= 2*XLen will be returned in registers. 13706c3fb27SDimitry Andric // Otherwise, aggregate will be returned indirectly. 13806c3fb27SDimitry Andric if (!isReturnType || (isReturnType && Size <= 2 * XLen)) { 13906c3fb27SDimitry Andric if (Size <= XLen) { 14006c3fb27SDimitry Andric return ABIArgInfo::getDirect( 14106c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), XLen)); 14206c3fb27SDimitry Andric } else { 14306c3fb27SDimitry Andric return ABIArgInfo::getDirect(llvm::ArrayType::get( 14406c3fb27SDimitry Andric llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen)); 14506c3fb27SDimitry Andric } 14606c3fb27SDimitry Andric } 14706c3fb27SDimitry Andric return getNaturalAlignIndirect(Ty, /*ByVal=*/false); 14806c3fb27SDimitry Andric } 14906c3fb27SDimitry Andric 15006c3fb27SDimitry Andric ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const { 15106c3fb27SDimitry Andric if (RetTy->isVoidType()) 15206c3fb27SDimitry Andric return ABIArgInfo::getIgnore(); 15306c3fb27SDimitry Andric 15406c3fb27SDimitry Andric int ArgGPRsLeft = 2; 15506c3fb27SDimitry Andric int ArgFPRsLeft = FLen ? 1 : 0; 15606c3fb27SDimitry Andric 15706c3fb27SDimitry Andric // The rules for return and argument types are the same, so defer to 15806c3fb27SDimitry Andric // classifyArgumentType. 15906c3fb27SDimitry Andric return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true); 16006c3fb27SDimitry Andric } 16106c3fb27SDimitry Andric 16206c3fb27SDimitry Andric namespace { 16306c3fb27SDimitry Andric class CSKYTargetCodeGenInfo : public TargetCodeGenInfo { 16406c3fb27SDimitry Andric public: 16506c3fb27SDimitry Andric CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen) 16606c3fb27SDimitry Andric : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {} 16706c3fb27SDimitry Andric }; 16806c3fb27SDimitry Andric } // end anonymous namespace 16906c3fb27SDimitry Andric 17006c3fb27SDimitry Andric std::unique_ptr<TargetCodeGenInfo> 17106c3fb27SDimitry Andric CodeGen::createCSKYTargetCodeGenInfo(CodeGenModule &CGM, unsigned FLen) { 17206c3fb27SDimitry Andric return std::make_unique<CSKYTargetCodeGenInfo>(CGM.getTypes(), FLen); 17306c3fb27SDimitry Andric } 174