159 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10#include "TargetInfo.h"11 12using namespace clang;13using namespace clang::CodeGen;14 15//===----------------------------------------------------------------------===//16// Lanai ABI Implementation17//===----------------------------------------------------------------------===//18 19namespace {20class LanaiABIInfo : public DefaultABIInfo {21 struct CCState {22 unsigned FreeRegs;23 };24 25public: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 the33 // 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 namespace50 51bool 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 68ABIArgInfo 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 88ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty,89 CCState &State) const {90 // Check with the C++ ABI first.91 const RecordType *RT = Ty->getAsCanonical<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()->getDefinitionOrSelf()->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 *ED = Ty->getAsEnumDecl())128 Ty = ED->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 147namespace {148class LanaiTargetCodeGenInfo : public TargetCodeGenInfo {149public:150 LanaiTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)151 : TargetCodeGenInfo(std::make_unique<LanaiABIInfo>(CGT)) {}152};153}154 155std::unique_ptr<TargetCodeGenInfo>156CodeGen::createLanaiTargetCodeGenInfo(CodeGenModule &CGM) {157 return std::make_unique<LanaiTargetCodeGenInfo>(CGM.getTypes());158}159