brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.8 KiB · e50f06c Raw
553 lines · cpp
1//===- SystemZ.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#include "clang/Basic/Builtins.h"12#include "llvm/IR/IntrinsicsS390.h"13 14using namespace clang;15using namespace clang::CodeGen;16 17//===----------------------------------------------------------------------===//18// SystemZ ABI Implementation19//===----------------------------------------------------------------------===//20 21namespace {22 23class SystemZABIInfo : public ABIInfo {24  bool HasVector;25  bool IsSoftFloatABI;26 27public:28  SystemZABIInfo(CodeGenTypes &CGT, bool HV, bool SF)29      : ABIInfo(CGT), HasVector(HV), IsSoftFloatABI(SF) {}30 31  bool isPromotableIntegerTypeForABI(QualType Ty) const;32  bool isCompoundType(QualType Ty) const;33  bool isVectorArgumentType(QualType Ty) const;34  llvm::Type *getFPArgumentType(QualType Ty, uint64_t Size) const;35  QualType GetSingleElementType(QualType Ty) const;36 37  ABIArgInfo classifyReturnType(QualType RetTy) const;38  ABIArgInfo classifyArgumentType(QualType ArgTy) const;39 40  void computeInfo(CGFunctionInfo &FI) const override;41  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,42                   AggValueSlot Slot) const override;43};44 45class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {46  ASTContext &Ctx;47 48  // These are used for speeding up the search for a visible vector ABI.49  mutable bool HasVisibleVecABIFlag = false;50  mutable std::set<const Type *> SeenTypes;51 52  // Returns true (the first time) if Ty is, or is found to include, a vector53  // type that exposes the vector ABI. This is any vector >=16 bytes which54  // with vector support are aligned to only 8 bytes. When IsParam is true,55  // the type belongs to a value as passed between functions. If it is a56  // vector <=16 bytes it will be passed in a vector register (if supported).57  bool isVectorTypeBased(const Type *Ty, bool IsParam) const;58 59public:60  SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)61      : TargetCodeGenInfo(62            std::make_unique<SystemZABIInfo>(CGT, HasVector, SoftFloatABI)),63            Ctx(CGT.getContext()) {64    SwiftInfo =65        std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);66  }67 68  // The vector ABI is different when the vector facility is present and when69  // a module e.g. defines an externally visible vector variable, a flag70  // indicating a visible vector ABI is added. Eventually this will result in71  // a GNU attribute indicating the vector ABI of the module.  Ty is the type72  // of a variable or function parameter that is globally visible.73  void handleExternallyVisibleObjABI(const Type *Ty, CodeGen::CodeGenModule &M,74                                     bool IsParam) const {75    if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty, IsParam)) {76      M.getModule().addModuleFlag(llvm::Module::Warning,77                                  "s390x-visible-vector-ABI", 1);78      HasVisibleVecABIFlag = true;79    }80  }81 82  void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,83                           CodeGen::CodeGenModule &M) const override {84    if (!D)85      return;86 87    // Check if the vector ABI becomes visible by an externally visible88    // variable or function.89    if (const auto *VD = dyn_cast<VarDecl>(D)) {90      if (VD->isExternallyVisible())91        handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M,92                                      /*IsParam*/false);93    }94    else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {95      if (FD->isExternallyVisible())96        handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M,97                                      /*IsParam*/false);98    }99  }100 101  llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,102                          CGBuilderTy &Builder,103                          CodeGenModule &CGM) const override {104    assert(V->getType()->isFloatingPointTy() && "V should have an FP type.");105    // Only use TDC in constrained FP mode.106    if (!Builder.getIsFPConstrained())107      return nullptr;108 109    llvm::Type *Ty = V->getType();110    if (Ty->isHalfTy() || Ty->isFloatTy() || Ty->isDoubleTy() ||111        Ty->isFP128Ty()) {112      llvm::Module &M = CGM.getModule();113      auto &Ctx = M.getContext();114      llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(115          &M, llvm::Intrinsic::s390_tdc, Ty);116      unsigned TDCBits = 0;117      switch (BuiltinID) {118      case Builtin::BI__builtin_isnan:119        TDCBits = 0xf;120        break;121      case Builtin::BIfinite:122      case Builtin::BI__finite:123      case Builtin::BIfinitef:124      case Builtin::BI__finitef:125      case Builtin::BIfinitel:126      case Builtin::BI__finitel:127      case Builtin::BI__builtin_isfinite:128        TDCBits = 0xfc0;129        break;130      case Builtin::BI__builtin_isinf:131        TDCBits = 0x30;132        break;133      default:134        break;135      }136      if (TDCBits)137        return Builder.CreateCall(138            TDCFunc,139            {V, llvm::ConstantInt::get(llvm::Type::getInt64Ty(Ctx), TDCBits)});140    }141    return nullptr;142  }143};144}145 146bool SystemZABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const {147  // Treat an enum type as its underlying type.148  if (const auto *ED = Ty->getAsEnumDecl())149    Ty = ED->getIntegerType();150 151  // Promotable integer types are required to be promoted by the ABI.152  if (ABIInfo::isPromotableIntegerTypeForABI(Ty))153    return true;154 155  if (const auto *EIT = Ty->getAs<BitIntType>())156    if (EIT->getNumBits() < 64)157      return true;158 159  // 32-bit values must also be promoted.160  if (const BuiltinType *BT = Ty->getAs<BuiltinType>())161    switch (BT->getKind()) {162    case BuiltinType::Int:163    case BuiltinType::UInt:164      return true;165    default:166      return false;167    }168  return false;169}170 171bool SystemZABIInfo::isCompoundType(QualType Ty) const {172  return (Ty->isAnyComplexType() ||173          Ty->isVectorType() ||174          isAggregateTypeForABI(Ty));175}176 177bool SystemZABIInfo::isVectorArgumentType(QualType Ty) const {178  return (HasVector &&179          Ty->isVectorType() &&180          getContext().getTypeSize(Ty) <= 128);181}182 183// The Size argument will in case of af an overaligned single element struct184// reflect the overalignment value. In such a case the argument will be185// passed using the type matching Size.186llvm::Type *SystemZABIInfo::getFPArgumentType(QualType Ty,187                                              uint64_t Size) const {188  if (IsSoftFloatABI)189    return nullptr;190 191  if (const BuiltinType *BT = Ty->getAs<BuiltinType>())192    switch (BT->getKind()) {193    case BuiltinType::Float16:194      if (Size == 16)195        return llvm::Type::getHalfTy(getVMContext());196      [[fallthrough]];197    case BuiltinType::Float:198      if (Size == 32)199        return llvm::Type::getFloatTy(getVMContext());200      [[fallthrough]];201    case BuiltinType::Double:202      return llvm::Type::getDoubleTy(getVMContext());203    default:204      return nullptr;205    }206 207  return nullptr;208}209 210QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const {211  const auto *RD = Ty->getAsRecordDecl();212  if (RD && RD->isStructureOrClass()) {213    QualType Found;214 215    // If this is a C++ record, check the bases first.216    if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))217      if (CXXRD->hasDefinition())218        for (const auto &I : CXXRD->bases()) {219          QualType Base = I.getType();220 221          // Empty bases don't affect things either way.222          if (isEmptyRecord(getContext(), Base, true))223            continue;224 225          if (!Found.isNull())226            return Ty;227          Found = GetSingleElementType(Base);228        }229 230    // Check the fields.231    for (const auto *FD : RD->fields()) {232      // Unlike isSingleElementStruct(), empty structure and array fields233      // do count.  So do anonymous bitfields that aren't zero-sized.234 235      // Like isSingleElementStruct(), ignore C++20 empty data members.236      if (FD->hasAttr<NoUniqueAddressAttr>() &&237          isEmptyRecord(getContext(), FD->getType(), true))238        continue;239 240      // Unlike isSingleElementStruct(), arrays do not count.241      // Nested structures still do though.242      if (!Found.isNull())243        return Ty;244      Found = GetSingleElementType(FD->getType());245    }246 247    // Unlike isSingleElementStruct(), trailing padding is allowed.248    // An 8-byte aligned struct s { float f; } is passed as a double.249    if (!Found.isNull())250      return Found;251  }252 253  return Ty;254}255 256RValue SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,257                                 QualType Ty, AggValueSlot Slot) const {258  // Assume that va_list type is correct; should be pointer to LLVM type:259  // struct {260  //   i64 __gpr;261  //   i64 __fpr;262  //   i8 *__overflow_arg_area;263  //   i8 *__reg_save_area;264  // };265 266  // Every non-vector argument occupies 8 bytes and is passed by preference267  // in either GPRs or FPRs.  Vector arguments occupy 8 or 16 bytes and are268  // always passed on the stack.269  const SystemZTargetCodeGenInfo &SZCGI =270      static_cast<const SystemZTargetCodeGenInfo &>(271          CGT.getCGM().getTargetCodeGenInfo());272  Ty = getContext().getCanonicalType(Ty);273  auto TyInfo = getContext().getTypeInfoInChars(Ty);274  llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);275  llvm::Type *DirectTy = ArgTy;276  ABIArgInfo AI = classifyArgumentType(Ty);277  bool IsIndirect = AI.isIndirect();278  bool InFPRs = false;279  bool IsVector = false;280  CharUnits UnpaddedSize;281  CharUnits DirectAlign;282  SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM(),283                                      /*IsParam*/true);284  if (IsIndirect) {285    DirectTy = llvm::PointerType::getUnqual(DirectTy->getContext());286    UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);287  } else {288    if (AI.getCoerceToType())289      ArgTy = AI.getCoerceToType();290    InFPRs = (!IsSoftFloatABI &&291              (ArgTy->isHalfTy() || ArgTy->isFloatTy() || ArgTy->isDoubleTy()));292    IsVector = ArgTy->isVectorTy();293    UnpaddedSize = TyInfo.Width;294    DirectAlign = TyInfo.Align;295  }296  CharUnits PaddedSize = CharUnits::fromQuantity(8);297  if (IsVector && UnpaddedSize > PaddedSize)298    PaddedSize = CharUnits::fromQuantity(16);299  assert((UnpaddedSize <= PaddedSize) && "Invalid argument size.");300 301  CharUnits Padding = (PaddedSize - UnpaddedSize);302 303  llvm::Type *IndexTy = CGF.Int64Ty;304  llvm::Value *PaddedSizeV =305    llvm::ConstantInt::get(IndexTy, PaddedSize.getQuantity());306 307  if (IsVector) {308    // Work out the address of a vector argument on the stack.309    // Vector arguments are always passed in the high bits of a310    // single (8 byte) or double (16 byte) stack slot.311    Address OverflowArgAreaPtr =312        CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");313    Address OverflowArgArea =314        Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),315                CGF.Int8Ty, TyInfo.Align);316    Address MemAddr = OverflowArgArea.withElementType(DirectTy);317 318    // Update overflow_arg_area_ptr pointer319    llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(320        OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF),321        PaddedSizeV, "overflow_arg_area");322    CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);323 324    return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(MemAddr, Ty), Slot);325  }326 327  assert(PaddedSize.getQuantity() == 8);328 329  unsigned MaxRegs, RegCountField, RegSaveIndex;330  CharUnits RegPadding;331  if (InFPRs) {332    MaxRegs = 4; // Maximum of 4 FPR arguments333    RegCountField = 1; // __fpr334    RegSaveIndex = 16; // save offset for f0335    RegPadding = CharUnits(); // floats are passed in the high bits of an FPR336  } else {337    MaxRegs = 5; // Maximum of 5 GPR arguments338    RegCountField = 0; // __gpr339    RegSaveIndex = 2; // save offset for r2340    RegPadding = Padding; // values are passed in the low bits of a GPR341  }342 343  Address RegCountPtr =344      CGF.Builder.CreateStructGEP(VAListAddr, RegCountField, "reg_count_ptr");345  llvm::Value *RegCount = CGF.Builder.CreateLoad(RegCountPtr, "reg_count");346  llvm::Value *MaxRegsV = llvm::ConstantInt::get(IndexTy, MaxRegs);347  llvm::Value *InRegs = CGF.Builder.CreateICmpULT(RegCount, MaxRegsV,348                                                 "fits_in_regs");349 350  llvm::BasicBlock *InRegBlock = CGF.createBasicBlock("vaarg.in_reg");351  llvm::BasicBlock *InMemBlock = CGF.createBasicBlock("vaarg.in_mem");352  llvm::BasicBlock *ContBlock = CGF.createBasicBlock("vaarg.end");353  CGF.Builder.CreateCondBr(InRegs, InRegBlock, InMemBlock);354 355  // Emit code to load the value if it was passed in registers.356  CGF.EmitBlock(InRegBlock);357 358  // Work out the address of an argument register.359  llvm::Value *ScaledRegCount =360    CGF.Builder.CreateMul(RegCount, PaddedSizeV, "scaled_reg_count");361  llvm::Value *RegBase =362    llvm::ConstantInt::get(IndexTy, RegSaveIndex * PaddedSize.getQuantity()363                                      + RegPadding.getQuantity());364  llvm::Value *RegOffset =365    CGF.Builder.CreateAdd(ScaledRegCount, RegBase, "reg_offset");366  Address RegSaveAreaPtr =367      CGF.Builder.CreateStructGEP(VAListAddr, 3, "reg_save_area_ptr");368  llvm::Value *RegSaveArea =369      CGF.Builder.CreateLoad(RegSaveAreaPtr, "reg_save_area");370  Address RawRegAddr(371      CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, RegOffset, "raw_reg_addr"),372      CGF.Int8Ty, PaddedSize);373  Address RegAddr = RawRegAddr.withElementType(DirectTy);374 375  // Update the register count376  llvm::Value *One = llvm::ConstantInt::get(IndexTy, 1);377  llvm::Value *NewRegCount =378    CGF.Builder.CreateAdd(RegCount, One, "reg_count");379  CGF.Builder.CreateStore(NewRegCount, RegCountPtr);380  CGF.EmitBranch(ContBlock);381 382  // Emit code to load the value if it was passed in memory.383  CGF.EmitBlock(InMemBlock);384 385  // Work out the address of a stack argument.386  Address OverflowArgAreaPtr =387      CGF.Builder.CreateStructGEP(VAListAddr, 2, "overflow_arg_area_ptr");388  Address OverflowArgArea =389      Address(CGF.Builder.CreateLoad(OverflowArgAreaPtr, "overflow_arg_area"),390              CGF.Int8Ty, PaddedSize);391  Address RawMemAddr =392      CGF.Builder.CreateConstByteGEP(OverflowArgArea, Padding, "raw_mem_addr");393  Address MemAddr = RawMemAddr.withElementType(DirectTy);394 395  // Update overflow_arg_area_ptr pointer396  llvm::Value *NewOverflowArgArea = CGF.Builder.CreateGEP(397      OverflowArgArea.getElementType(), OverflowArgArea.emitRawPointer(CGF),398      PaddedSizeV, "overflow_arg_area");399  CGF.Builder.CreateStore(NewOverflowArgArea, OverflowArgAreaPtr);400  CGF.EmitBranch(ContBlock);401 402  // Return the appropriate result.403  CGF.EmitBlock(ContBlock);404  Address ResAddr = emitMergePHI(CGF, RegAddr, InRegBlock, MemAddr, InMemBlock,405                                 "va_arg.addr");406 407  if (IsIndirect)408    ResAddr = Address(CGF.Builder.CreateLoad(ResAddr, "indirect_arg"), ArgTy,409                      TyInfo.Align);410 411  return CGF.EmitLoadOfAnyValue(CGF.MakeAddrLValue(ResAddr, Ty), Slot);412}413 414ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const {415  if (RetTy->isVoidType())416    return ABIArgInfo::getIgnore();417  if (isVectorArgumentType(RetTy))418    return ABIArgInfo::getDirect();419  if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64)420    return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace());421  return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy)422                                               : ABIArgInfo::getDirect());423}424 425ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {426  // Handle transparent union types.427  Ty = useFirstFieldIfTransparentUnion(Ty);428 429  // Handle the generic C++ ABI.430  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))431    return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),432                                   RAA == CGCXXABI::RAA_DirectInMemory);433 434  // Integers and enums are extended to full register width.435  if (isPromotableIntegerTypeForABI(Ty))436    return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty));437 438  // Handle vector types and vector-like structure types.  Note that439  // as opposed to float-like structure types, we do not allow any440  // padding for vector-like structures, so verify the sizes match.441  uint64_t Size = getContext().getTypeSize(Ty);442  QualType SingleElementTy = GetSingleElementType(Ty);443  if (isVectorArgumentType(SingleElementTy) &&444      getContext().getTypeSize(SingleElementTy) == Size)445    return ABIArgInfo::getDirect(CGT.ConvertType(SingleElementTy));446 447  // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly.448  if (Size != 8 && Size != 16 && Size != 32 && Size != 64)449    return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),450                                   /*ByVal=*/false);451 452  // Handle small structures.453  if (const auto *RD = Ty->getAsRecordDecl()) {454    // Structures with flexible arrays have variable length, so really455    // fail the size test above.456    if (RD->hasFlexibleArrayMember())457      return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),458                                     /*ByVal=*/false);459 460    // The structure is passed as an unextended integer, a half, a float,461    // or a double.462    if (llvm::Type *FPArgTy = getFPArgumentType(SingleElementTy, Size)) {463      assert(Size == 16 || Size == 32 || Size == 64);464      return ABIArgInfo::getDirect(FPArgTy);465    } else {466      llvm::IntegerType *PassTy = llvm::IntegerType::get(getVMContext(), Size);467      return Size <= 32 ? ABIArgInfo::getNoExtend(PassTy)468                        : ABIArgInfo::getDirect(PassTy);469    }470  }471 472  // Non-structure compounds are passed indirectly.473  if (isCompoundType(Ty))474    return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),475                                   /*ByVal=*/false);476 477  return ABIArgInfo::getDirect(nullptr);478}479 480void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {481  const SystemZTargetCodeGenInfo &SZCGI =482      static_cast<const SystemZTargetCodeGenInfo &>(483          CGT.getCGM().getTargetCodeGenInfo());484  if (!getCXXABI().classifyReturnType(FI))485    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());486  unsigned Idx = 0;487  for (auto &I : FI.arguments()) {488    I.info = classifyArgumentType(I.type);489    if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs())490      // Check if a vararg vector argument is passed, in which case the491      // vector ABI becomes visible as the va_list could be passed on to492      // other functions.493      SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM(),494                                          /*IsParam*/true);495  }496}497 498bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty,499                                                 bool IsParam) const {500  if (!SeenTypes.insert(Ty).second)501    return false;502 503  if (IsParam) {504    // A narrow (<16 bytes) vector will as a parameter also expose the ABI as505    // it will be passed in a vector register. A wide (>16 bytes) vector will506    // be passed via "hidden" pointer where any extra alignment is not507    // required (per GCC).508    const Type *SingleEltTy = getABIInfo<SystemZABIInfo>()509                                  .GetSingleElementType(QualType(Ty, 0))510                                  .getTypePtr();511    bool SingleVecEltStruct = SingleEltTy != Ty && SingleEltTy->isVectorType() &&512      Ctx.getTypeSize(SingleEltTy) == Ctx.getTypeSize(Ty);513    if (Ty->isVectorType() || SingleVecEltStruct)514      return Ctx.getTypeSize(Ty) / 8 <= 16;515  }516 517  // Assume pointers are dereferenced.518  while (Ty->isPointerType() || Ty->isArrayType())519    Ty = Ty->getPointeeOrArrayElementType();520 521  // Vectors >= 16 bytes expose the ABI through alignment requirements.522  if (Ty->isVectorType() && Ctx.getTypeSize(Ty) / 8 >= 16)523      return true;524 525  if (const auto *RD = Ty->getAsRecordDecl()) {526    if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))527      if (CXXRD->hasDefinition())528        for (const auto &I : CXXRD->bases())529          if (isVectorTypeBased(I.getType().getTypePtr(), /*IsParam*/false))530            return true;531    for (const auto *FD : RD->fields())532      if (isVectorTypeBased(FD->getType().getTypePtr(), /*IsParam*/false))533        return true;534  }535 536  if (const auto *FT = Ty->getAs<FunctionType>())537    if (isVectorTypeBased(FT->getReturnType().getTypePtr(), /*IsParam*/true))538      return true;539  if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())540    for (const auto &ParamType : Proto->getParamTypes())541      if (isVectorTypeBased(ParamType.getTypePtr(), /*IsParam*/true))542        return true;543 544  return false;545}546 547std::unique_ptr<TargetCodeGenInfo>548CodeGen::createSystemZTargetCodeGenInfo(CodeGenModule &CGM, bool HasVector,549                                        bool SoftFloatABI) {550  return std::make_unique<SystemZTargetCodeGenInfo>(CGM.getTypes(), HasVector,551                                                    SoftFloatABI);552}553