162 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "ABIInfoImpl.h"10#include "TargetInfo.h"11 12using namespace clang;13using namespace clang::CodeGen;14 15// ARC ABI implementation.16namespace {17 18class ARCABIInfo : public DefaultABIInfo {19 struct CCState {20 unsigned FreeRegs;21 };22 23public:24 using DefaultABIInfo::DefaultABIInfo;25 26private:27 RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,28 AggValueSlot Slot) 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 else40 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 64class ARCTargetCodeGenInfo : public TargetCodeGenInfo {65public:66 ARCTargetCodeGenInfo(CodeGenTypes &CGT)67 : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {}68};69 70 71ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const {72 return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty)73 : getNaturalAlignIndirect(74 Ty, getDataLayout().getAllocaAddrSpace(), false);75}76 77ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const {78 // Compute the byval alignment.79 const unsigned MinABIStackAlignInBytes = 4;80 unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8;81 return ABIArgInfo::getIndirect(82 CharUnits::fromQuantity(4),83 /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),84 /*ByVal=*/true, TypeAlign > MinABIStackAlignInBytes);85}86 87RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,88 QualType Ty, AggValueSlot Slot) const {89 return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false,90 getContext().getTypeInfoInChars(Ty),91 CharUnits::fromQuantity(4), true, Slot);92}93 94ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty,95 uint8_t FreeRegs) const {96 // Handle the generic C++ ABI.97 const RecordType *RT = Ty->getAsCanonical<RecordType>();98 if (RT) {99 CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI());100 if (RAA == CGCXXABI::RAA_Indirect)101 return getIndirectByRef(Ty, FreeRegs > 0);102 103 if (RAA == CGCXXABI::RAA_DirectInMemory)104 return getIndirectByValue(Ty);105 }106 107 // Treat an enum type as its underlying type.108 if (const auto *ED = Ty->getAsEnumDecl())109 Ty = ED->getIntegerType();110 111 auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32;112 113 if (isAggregateTypeForABI(Ty)) {114 // Structures with flexible arrays are always indirect.115 if (RT && RT->getDecl()->getDefinitionOrSelf()->hasFlexibleArrayMember())116 return getIndirectByValue(Ty);117 118 // Ignore empty structs/unions.119 if (isEmptyRecord(getContext(), Ty, true))120 return ABIArgInfo::getIgnore();121 122 llvm::LLVMContext &LLVMContext = getVMContext();123 124 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);125 SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32);126 llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements);127 128 return FreeRegs >= SizeInRegs ?129 ABIArgInfo::getDirectInReg(Result) :130 ABIArgInfo::getDirect(Result, 0, nullptr, false);131 }132 133 if (const auto *EIT = Ty->getAs<BitIntType>())134 if (EIT->getNumBits() > 64)135 return getIndirectByValue(Ty);136 137 return isPromotableIntegerTypeForABI(Ty)138 ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty)139 : ABIArgInfo::getExtend(Ty))140 : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg()141 : ABIArgInfo::getDirect());142}143 144ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const {145 if (RetTy->isAnyComplexType())146 return ABIArgInfo::getDirectInReg();147 148 // Arguments of size > 4 registers are indirect.149 auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32;150 if (RetSize > 4)151 return getIndirectByRef(RetTy, /*HasFreeRegs*/ true);152 153 return DefaultABIInfo::classifyReturnType(RetTy);154}155 156} // End anonymous namespace.157 158std::unique_ptr<TargetCodeGenInfo>159CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) {160 return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes());161}162