1 //===- CSKY.cpp -----------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ABIInfoImpl.h" 10 #include "TargetInfo.h" 11 12 using namespace clang; 13 using namespace clang::CodeGen; 14 15 //===----------------------------------------------------------------------===// 16 // CSKY ABI Implementation 17 //===----------------------------------------------------------------------===// 18 namespace { 19 class CSKYABIInfo : public DefaultABIInfo { 20 static const int NumArgGPRs = 4; 21 static const int NumArgFPRs = 4; 22 23 static const unsigned XLen = 32; 24 unsigned FLen; 25 26 public: 27 CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen) 28 : DefaultABIInfo(CGT), FLen(FLen) {} 29 30 void computeInfo(CGFunctionInfo &FI) const override; 31 ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft, 32 int &ArgFPRsLeft, 33 bool isReturnType = false) const; 34 ABIArgInfo classifyReturnType(QualType RetTy) const; 35 36 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, 37 AggValueSlot Slot) const override; 38 }; 39 40 } // end anonymous namespace 41 42 void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const { 43 QualType RetTy = FI.getReturnType(); 44 if (!getCXXABI().classifyReturnType(FI)) 45 FI.getReturnInfo() = classifyReturnType(RetTy); 46 47 bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect; 48 49 // We must track the number of GPRs used in order to conform to the CSKY 50 // ABI, as integer scalars passed in registers should have signext/zeroext 51 // when promoted. 52 int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs; 53 int ArgFPRsLeft = FLen ? NumArgFPRs : 0; 54 55 for (auto &ArgInfo : FI.arguments()) { 56 ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft); 57 } 58 } 59 60 RValue CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 61 QualType Ty, AggValueSlot Slot) const { 62 CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8); 63 64 // Empty records are ignored for parameter passing purposes. 65 if (isEmptyRecord(getContext(), Ty, true)) 66 return Slot.asRValue(); 67 68 auto TInfo = getContext().getTypeInfoInChars(Ty); 69 70 return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize, 71 /*AllowHigherAlign=*/true, Slot); 72 } 73 74 ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, 75 int &ArgFPRsLeft, 76 bool isReturnType) const { 77 assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); 78 Ty = useFirstFieldIfTransparentUnion(Ty); 79 80 // Structures with either a non-trivial destructor or a non-trivial 81 // copy constructor are always passed indirectly. 82 if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { 83 if (ArgGPRsLeft) 84 ArgGPRsLeft -= 1; 85 return getNaturalAlignIndirect( 86 Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), 87 /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory); 88 } 89 90 // Ignore empty structs/unions. 91 if (isEmptyRecord(getContext(), Ty, true)) 92 return ABIArgInfo::getIgnore(); 93 94 if (!Ty->getAsUnionType()) 95 if (const Type *SeltTy = isSingleElementStruct(Ty, getContext())) 96 return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0))); 97 98 uint64_t Size = getContext().getTypeSize(Ty); 99 // Pass floating point values via FPRs if possible. 100 if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size && 101 ArgFPRsLeft) { 102 ArgFPRsLeft--; 103 return ABIArgInfo::getDirect(); 104 } 105 106 // Complex types for the hard float ABI must be passed direct rather than 107 // using CoerceAndExpand. 108 if (Ty->isComplexType() && FLen && !isReturnType) { 109 QualType EltTy = Ty->castAs<ComplexType>()->getElementType(); 110 if (getContext().getTypeSize(EltTy) <= FLen) { 111 ArgFPRsLeft -= 2; 112 return ABIArgInfo::getDirect(); 113 } 114 } 115 116 if (!isAggregateTypeForABI(Ty)) { 117 // Treat an enum type as its underlying type. 118 if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 119 Ty = EnumTy->getDecl()->getIntegerType(); 120 121 // All integral types are promoted to XLen width, unless passed on the 122 // stack. 123 if (Size < XLen && Ty->isIntegralOrEnumerationType()) 124 return ABIArgInfo::getExtend(Ty); 125 126 if (const auto *EIT = Ty->getAs<BitIntType>()) { 127 if (EIT->getNumBits() < XLen) 128 return ABIArgInfo::getExtend(Ty); 129 } 130 131 return ABIArgInfo::getDirect(); 132 } 133 134 // For argument type, the first 4*XLen parts of aggregate will be passed 135 // in registers, and the rest will be passed in stack. 136 // So we can coerce to integers directly and let backend handle it correctly. 137 // For return type, aggregate which <= 2*XLen will be returned in registers. 138 // Otherwise, aggregate will be returned indirectly. 139 if (!isReturnType || (isReturnType && Size <= 2 * XLen)) { 140 if (Size <= XLen) { 141 return ABIArgInfo::getDirect( 142 llvm::IntegerType::get(getVMContext(), XLen)); 143 } else { 144 return ABIArgInfo::getDirect(llvm::ArrayType::get( 145 llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen)); 146 } 147 } 148 return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), 149 /*ByVal=*/false); 150 } 151 152 ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const { 153 if (RetTy->isVoidType()) 154 return ABIArgInfo::getIgnore(); 155 156 int ArgGPRsLeft = 2; 157 int ArgFPRsLeft = FLen ? 1 : 0; 158 159 // The rules for return and argument types are the same, so defer to 160 // classifyArgumentType. 161 return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true); 162 } 163 164 namespace { 165 class CSKYTargetCodeGenInfo : public TargetCodeGenInfo { 166 public: 167 CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen) 168 : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {} 169 }; 170 } // end anonymous namespace 171 172 std::unique_ptr<TargetCodeGenInfo> 173 CodeGen::createCSKYTargetCodeGenInfo(CodeGenModule &CGM, unsigned FLen) { 174 return std::make_unique<CSKYTargetCodeGenInfo>(CGM.getTypes(), FLen); 175 } 176