brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · b925420 Raw
176 lines · cpp
1//===- CSKY.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// CSKY ABI Implementation17//===----------------------------------------------------------------------===//18namespace {19class CSKYABIInfo : public DefaultABIInfo {20  static const int NumArgGPRs = 4;21  static const int NumArgFPRs = 4;22 23  static const unsigned XLen = 32;24  unsigned FLen;25 26public:27  CSKYABIInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)28      : DefaultABIInfo(CGT), FLen(FLen) {}29 30  void computeInfo(CGFunctionInfo &FI) const override;31  ABIArgInfo classifyArgumentType(QualType Ty, int &ArgGPRsLeft,32                                  int &ArgFPRsLeft,33                                  bool isReturnType = false) const;34  ABIArgInfo classifyReturnType(QualType RetTy) const;35 36  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,37                   AggValueSlot Slot) const override;38};39 40} // end anonymous namespace41 42void CSKYABIInfo::computeInfo(CGFunctionInfo &FI) const {43  QualType RetTy = FI.getReturnType();44  if (!getCXXABI().classifyReturnType(FI))45    FI.getReturnInfo() = classifyReturnType(RetTy);46 47  bool IsRetIndirect = FI.getReturnInfo().getKind() == ABIArgInfo::Indirect;48 49  // We must track the number of GPRs used in order to conform to the CSKY50  // ABI, as integer scalars passed in registers should have signext/zeroext51  // when promoted.52  int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs;53  int ArgFPRsLeft = FLen ? NumArgFPRs : 0;54 55  for (auto &ArgInfo : FI.arguments()) {56    ArgInfo.info = classifyArgumentType(ArgInfo.type, ArgGPRsLeft, ArgFPRsLeft);57  }58}59 60RValue CSKYABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,61                              QualType Ty, AggValueSlot Slot) const {62  CharUnits SlotSize = CharUnits::fromQuantity(XLen / 8);63 64  // Empty records are ignored for parameter passing purposes.65  if (isEmptyRecord(getContext(), Ty, true))66    return Slot.asRValue();67 68  auto TInfo = getContext().getTypeInfoInChars(Ty);69 70  return emitVoidPtrVAArg(CGF, VAListAddr, Ty, false, TInfo, SlotSize,71                          /*AllowHigherAlign=*/true, Slot);72}73 74ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft,75                                             int &ArgFPRsLeft,76                                             bool isReturnType) const {77  assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow");78  Ty = useFirstFieldIfTransparentUnion(Ty);79 80  // Structures with either a non-trivial destructor or a non-trivial81  // copy constructor are always passed indirectly.82  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {83    if (ArgGPRsLeft)84      ArgGPRsLeft -= 1;85    return getNaturalAlignIndirect(86        Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),87        /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory);88  }89 90  // Ignore empty structs/unions.91  if (isEmptyRecord(getContext(), Ty, true))92    return ABIArgInfo::getIgnore();93 94  if (!Ty->isUnionType())95    if (const Type *SeltTy = isSingleElementStruct(Ty, getContext()))96      return ABIArgInfo::getDirect(CGT.ConvertType(QualType(SeltTy, 0)));97 98  uint64_t Size = getContext().getTypeSize(Ty);99  // Pass floating point values via FPRs if possible.100  if (Ty->isFloatingType() && !Ty->isComplexType() && FLen >= Size &&101      ArgFPRsLeft) {102    ArgFPRsLeft--;103    return ABIArgInfo::getDirect();104  }105 106  // Complex types for the hard float ABI must be passed direct rather than107  // using CoerceAndExpand.108  if (Ty->isComplexType() && FLen && !isReturnType) {109    QualType EltTy = Ty->castAs<ComplexType>()->getElementType();110    if (getContext().getTypeSize(EltTy) <= FLen) {111      ArgFPRsLeft -= 2;112      return ABIArgInfo::getDirect();113    }114  }115 116  if (!isAggregateTypeForABI(Ty)) {117    // Treat an enum type as its underlying type.118    if (const auto *ED = Ty->getAsEnumDecl())119      Ty = ED->getIntegerType();120 121    // All integral types are promoted to XLen width, unless passed on the122    // stack.123    if (Size < XLen && Ty->isIntegralOrEnumerationType())124      return ABIArgInfo::getExtend(Ty);125 126    if (const auto *EIT = Ty->getAs<BitIntType>()) {127      if (EIT->getNumBits() < XLen)128        return ABIArgInfo::getExtend(Ty);129    }130 131    return ABIArgInfo::getDirect();132  }133 134  // For argument type, the first 4*XLen parts of aggregate will be passed135  // in registers, and the rest will be passed in stack.136  // So we can coerce to integers directly and let backend handle it correctly.137  // For return type, aggregate which <= 2*XLen will be returned in registers.138  // Otherwise, aggregate will be returned indirectly.139  if (!isReturnType || (isReturnType && Size <= 2 * XLen)) {140    if (Size <= XLen) {141      return ABIArgInfo::getDirect(142          llvm::IntegerType::get(getVMContext(), XLen));143    } else {144      return ABIArgInfo::getDirect(llvm::ArrayType::get(145          llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen));146    }147  }148  return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),149                                 /*ByVal=*/false);150}151 152ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const {153  if (RetTy->isVoidType())154    return ABIArgInfo::getIgnore();155 156  int ArgGPRsLeft = 2;157  int ArgFPRsLeft = FLen ? 1 : 0;158 159  // The rules for return and argument types are the same, so defer to160  // classifyArgumentType.161  return classifyArgumentType(RetTy, ArgGPRsLeft, ArgFPRsLeft, true);162}163 164namespace {165class CSKYTargetCodeGenInfo : public TargetCodeGenInfo {166public:167  CSKYTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned FLen)168      : TargetCodeGenInfo(std::make_unique<CSKYABIInfo>(CGT, FLen)) {}169};170} // end anonymous namespace171 172std::unique_ptr<TargetCodeGenInfo>173CodeGen::createCSKYTargetCodeGenInfo(CodeGenModule &CGM, unsigned FLen) {174  return std::make_unique<CSKYTargetCodeGenInfo>(CGM.getTypes(), FLen);175}176