diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 | 
| commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
| tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp | |
| parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
| parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp | 158 | 
1 files changed, 158 insertions, 0 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp b/contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp new file mode 100644 index 000000000000..550eb4068f25 --- /dev/null +++ b/contrib/llvm-project/clang/lib/CodeGen/Targets/ARC.cpp @@ -0,0 +1,158 @@ +//===- ARC.cpp ------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ABIInfoImpl.h" +#include "TargetInfo.h" + +using namespace clang; +using namespace clang::CodeGen; + +// ARC ABI implementation. +namespace { + +class ARCABIInfo : public DefaultABIInfo { +  struct CCState { +    unsigned FreeRegs; +  }; + +public: +  using DefaultABIInfo::DefaultABIInfo; + +private: +  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, +                    QualType Ty) const override; + +  void updateState(const ABIArgInfo &Info, QualType Ty, CCState &State) const { +    if (!State.FreeRegs) +      return; +    if (Info.isIndirect() && Info.getInReg()) +      State.FreeRegs--; +    else if (Info.isDirect() && Info.getInReg()) { +      unsigned sz = (getContext().getTypeSize(Ty) + 31) / 32; +      if (sz < State.FreeRegs) +        State.FreeRegs -= sz; +      else +        State.FreeRegs = 0; +    } +  } + +  void computeInfo(CGFunctionInfo &FI) const override { +    CCState State; +    // ARC uses 8 registers to pass arguments. +    State.FreeRegs = 8; + +    if (!getCXXABI().classifyReturnType(FI)) +      FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); +    updateState(FI.getReturnInfo(), FI.getReturnType(), State); +    for (auto &I : FI.arguments()) { +      I.info = classifyArgumentType(I.type, State.FreeRegs); +      updateState(I.info, I.type, State); +    } +  } + +  ABIArgInfo getIndirectByRef(QualType Ty, bool HasFreeRegs) const; +  ABIArgInfo getIndirectByValue(QualType Ty) const; +  ABIArgInfo classifyArgumentType(QualType Ty, uint8_t FreeRegs) const; +  ABIArgInfo classifyReturnType(QualType RetTy) const; +}; + +class ARCTargetCodeGenInfo : public TargetCodeGenInfo { +public: +  ARCTargetCodeGenInfo(CodeGenTypes &CGT) +      : TargetCodeGenInfo(std::make_unique<ARCABIInfo>(CGT)) {} +}; + + +ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const { +  return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) : +                       getNaturalAlignIndirect(Ty, false); +} + +ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const { +  // Compute the byval alignment. +  const unsigned MinABIStackAlignInBytes = 4; +  unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; +  return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, +                                 TypeAlign > MinABIStackAlignInBytes); +} + +Address ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, +                              QualType Ty) const { +  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, /*indirect*/ false, +                          getContext().getTypeInfoInChars(Ty), +                          CharUnits::fromQuantity(4), true); +} + +ABIArgInfo ARCABIInfo::classifyArgumentType(QualType Ty, +                                            uint8_t FreeRegs) const { +  // Handle the generic C++ ABI. +  const RecordType *RT = Ty->getAs<RecordType>(); +  if (RT) { +    CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI()); +    if (RAA == CGCXXABI::RAA_Indirect) +      return getIndirectByRef(Ty, FreeRegs > 0); + +    if (RAA == CGCXXABI::RAA_DirectInMemory) +      return getIndirectByValue(Ty); +  } + +  // Treat an enum type as its underlying type. +  if (const EnumType *EnumTy = Ty->getAs<EnumType>()) +    Ty = EnumTy->getDecl()->getIntegerType(); + +  auto SizeInRegs = llvm::alignTo(getContext().getTypeSize(Ty), 32) / 32; + +  if (isAggregateTypeForABI(Ty)) { +    // Structures with flexible arrays are always indirect. +    if (RT && RT->getDecl()->hasFlexibleArrayMember()) +      return getIndirectByValue(Ty); + +    // Ignore empty structs/unions. +    if (isEmptyRecord(getContext(), Ty, true)) +      return ABIArgInfo::getIgnore(); + +    llvm::LLVMContext &LLVMContext = getVMContext(); + +    llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext); +    SmallVector<llvm::Type *, 3> Elements(SizeInRegs, Int32); +    llvm::Type *Result = llvm::StructType::get(LLVMContext, Elements); + +    return FreeRegs >= SizeInRegs ? +        ABIArgInfo::getDirectInReg(Result) : +        ABIArgInfo::getDirect(Result, 0, nullptr, false); +  } + +  if (const auto *EIT = Ty->getAs<BitIntType>()) +    if (EIT->getNumBits() > 64) +      return getIndirectByValue(Ty); + +  return isPromotableIntegerTypeForABI(Ty) +             ? (FreeRegs >= SizeInRegs ? ABIArgInfo::getExtendInReg(Ty) +                                       : ABIArgInfo::getExtend(Ty)) +             : (FreeRegs >= SizeInRegs ? ABIArgInfo::getDirectInReg() +                                       : ABIArgInfo::getDirect()); +} + +ABIArgInfo ARCABIInfo::classifyReturnType(QualType RetTy) const { +  if (RetTy->isAnyComplexType()) +    return ABIArgInfo::getDirectInReg(); + +  // Arguments of size > 4 registers are indirect. +  auto RetSize = llvm::alignTo(getContext().getTypeSize(RetTy), 32) / 32; +  if (RetSize > 4) +    return getIndirectByRef(RetTy, /*HasFreeRegs*/ true); + +  return DefaultABIInfo::classifyReturnType(RetTy); +} + +} // End anonymous namespace. + +std::unique_ptr<TargetCodeGenInfo> +CodeGen::createARCTargetCodeGenInfo(CodeGenModule &CGM) { +  return std::make_unique<ARCTargetCodeGenInfo>(CGM.getTypes()); +}  | 
