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