1 //===- ARC.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 // ARC ABI implementation. 16 namespace { 17 18 class ARCABIInfo : public DefaultABIInfo { 19 struct CCState { 20 unsigned FreeRegs; 21 }; 22 23 public: 24 using DefaultABIInfo::DefaultABIInfo; 25 26 private: 27 Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 28 QualType Ty) const override; 29 30 void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const { 31 if (!State.FreeRegs) 32 return; 33 if (Info.isIndirect() && Info.getInReg()) 34 State.FreeRegs--; 35 else if (Info.isDirect() && Info.getInReg()) { 36 unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32; 37 if (sz < State.FreeRegs) 38 State.FreeRegs -= sz; 39 else 40 State.FreeRegs = 0; 41 } 42 } 43 44 void computeInfo(CGFunctionInfo &FI) const override { 45 CCState State; 46 // ARC uses 8 registers to pass arguments. 47 State.FreeRegs = 8; 48 49 if (!getCXXABI().classifyReturnType(FI)) 50 FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); 51 updateState(FI.getReturnInfo(), FI.getReturnType(), State); 52 for (auto &I : FI.arguments()) { 53 I.info = classifyArgumentType(I.type, State.FreeRegs); 54 updateState(I.info, I.type, State); 55 } 56 } 57 58 ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const; 59 ABIArgInfo getIndirectByValue(QualType Ty) const; 60 ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const; 61 ABIArgInfo classifyReturnType(QualType RetTy) const; 62 }; 63 64 class ARCTargetCodeGenInfo : public TargetCodeGenInfo { 65 public: 66 ARCTargetCodeGenInfo(CodeGenTypes &CGT) 67 : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {} 68 }; 69 70 71 ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const { 72 return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) : 73 getNaturalAlignIndirect(Ty, false); 74 } 75 76 ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const { 77 // Compute the byval alignment. 78 const unsigned MinABIStackAlignInBytes = 4; 79 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; 80 return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, 81 TypeAlign > MinABIStackAlignInBytes); 82 } 83 84 Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, 85 QualType Ty) const { 86 return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, 87 getContext().getTypeInfoInChars(Ty), 88 CharUnits::fromQuantity(4), true); 89 } 90 91 ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, 92 uint8_t FreeRegs) const { 93 // Handle the generic C++ ABI. 94 const RecordType *RT = Ty->getAs<RecordType>(); 95 if (RT) { 96 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); 97 if (RAA == CGCXXABI::RAA_Indirect) 98 return getIndirectByRef(Ty, FreeRegs > 0); 99 100 if (RAA == CGCXXABI::RAA_DirectInMemory) 101 return getIndirectByValue(Ty); 102 } 103 104 // Treat an enum type as its underlying type. 105 if (const EnumType *EnumTy = Ty->getAs<EnumType>()) 106 Ty = EnumTy->getDecl()->getIntegerType(); 107 108 auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32; 109 110 if (isAggregateTypeForABI(Ty)) { 111 // Structures with flexible arrays are always indirect. 112 if (RT && RT->getDecl()->hasFlexibleArrayMember()) 113 return getIndirectByValue(Ty); 114 115 // Ignore empty structs/unions. 116 if (isEmptyRecord(getContext(), Ty, true)) 117 return ABIArgInfo::getIgnore(); 118 119 llvm::LLVMContext &LLVMContext = getVMContext(); 120 121 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); 122 SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32); 123 llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); 124 125 return FreeRegs >= SizeInRegs ? 126 ABIArgInfo::getDirectInReg(Result) : 127 ABIArgInfo::getDirect(Result, 0, nullptr, false); 128 } 129 130 if (const auto *EIT = Ty->getAs<BitIntType>()) 131 if (EIT->getNumBits() > 64) 132 return getIndirectByValue(Ty); 133 134 return isPromotableIntegerTypeForABI(Ty) 135 ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) 136 : ABIArgInfo::getExtend(Ty)) 137 : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() 138 : ABIArgInfo::getDirect()); 139 } 140 141 ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const { 142 if (RetTy->isAnyComplexType()) 143 return ABIArgInfo::getDirectInReg(); 144 145 // Arguments of size > 4 registers are indirect. 146 auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32; 147 if (RetSize > 4) 148 return getIndirectByRef(RetTy, /*HasFreeRegs*/ true); 149 150 return DefaultABIInfo::classifyReturnType(RetTy); 151 } 152 153 } // End anonymous namespace. 154 155 std::unique_ptr<TargetCodeGenInfo> 156 CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) { 157 return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes()); 158 } 159