brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.4 KiB · 6c9444d Raw
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