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, false); 76 } 77 78 // Compute the byval alignment. 79 const unsigned MinABIStackAlignInBytes = 4; 80 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; 81 return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, 82 /*Realign=*/TypeAlign > 83 MinABIStackAlignInBytes); 84 } 85 86 ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, 87 CCState &State) const { 88 // Check with the C++ ABI first. 89 const RecordType *RT = Ty->getAs<RecordType>(); 90 if (RT) { 91 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); 92 if (RAA == CGCXXABI::RAA_Indirect) { 93 return getIndirectResult(Ty, /*ByVal=*/false, State); 94 } else if (RAA == CGCXXABI::RAA_DirectInMemory) { 95 return getNaturalAlignIndirect(Ty, /*ByVal=*/true); 96 } 97 } 98 99 if (isAggregateTypeForABI(Ty)) { 100 // Structures with flexible arrays are always indirect. 101 if (RT && RT->getDecl()->hasFlexibleArrayMember()) 102 return getIndirectResult(Ty, /*ByVal=*/true, State); 103 104 // Ignore empty structs/unions. 105 if (isEmptyRecord(getContext(), Ty, true)) 106 return ABIArgInfo::getIgnore(); 107 108 llvm::LLVMContext &LLVMContext = getVMContext(); 109 unsigned SizeInRegs = (getContext().getTypeSize(Ty) + 31) / 32; 110 if (SizeInRegs <= State.FreeRegs) { 111 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); 112 SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32); 113 llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); 114 State.FreeRegs -= SizeInRegs; 115 return ABIArgInfo::getDirectInReg(Result); 116 } else { 117 State.FreeRegs = 0; 118 } 119 return getIndirectResult(Ty, true, State); 120 } 121 122 // Treat an enum type as its underlying type. 123 if (const auto *EnumTy = Ty->getAs<EnumType>()) 124 Ty = EnumTy->getDecl()->getIntegerType(); 125 126 bool InReg = shouldUseInReg(Ty, State); 127 128 // Don't pass >64 bit integers in registers. 129 if (const auto *EIT = Ty->getAs<BitIntType>()) 130 if (EIT->getNumBits() > 64) 131 return getIndirectResult(Ty, /*ByVal=*/true, State); 132 133 if (isPromotableIntegerTypeForABI(Ty)) { 134 if (InReg) 135 return ABIArgInfo::getDirectInReg(); 136 return ABIArgInfo::getExtend(Ty); 137 } 138 if (InReg) 139 return ABIArgInfo::getDirectInReg(); 140 return ABIArgInfo::getDirect(); 141 } 142 143 namespace { 144 class LanaiTargetCodeGenInfo : public TargetCodeGenInfo { 145 public: 146 LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT) 147 : TargetCodeGenInfo(std::make_unique<LanaiABIInfo>(CGT)) {} 148 }; 149 } 150 151 std::unique_ptr<TargetCodeGenInfo> 152 CodeGen::createLanaiTargetCodeGenInfo(CodeGenModule &CGM) { 153 return std::make_unique<LanaiTargetCodeGenInfo>(CGM.getTypes()); 154 } 155