brintos

brintos / llvm-project-archived public Read only

0
0
Text · 86.3 KiB · 7e145f2 Raw
2269 lines · cpp
1//===----------------------------------------------------------------------===//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// This provides C++ code generation targeting the Itanium C++ ABI.  The class10// in this file generates structures that follow the Itanium C++ ABI, which is11// documented at:12//  https://itanium-cxx-abi.github.io/cxx-abi/abi.html13//  https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html14//15// It also supports the closely-related ARM ABI, documented at:16// https://developer.arm.com/documentation/ihi0041/g/17//18//===----------------------------------------------------------------------===//19 20#include "CIRGenCXXABI.h"21#include "CIRGenFunction.h"22 23#include "clang/AST/ExprCXX.h"24#include "clang/AST/GlobalDecl.h"25#include "clang/AST/VTableBuilder.h"26#include "clang/CIR/MissingFeatures.h"27#include "llvm/Support/ErrorHandling.h"28 29using namespace clang;30using namespace clang::CIRGen;31 32namespace {33 34class CIRGenItaniumCXXABI : public CIRGenCXXABI {35protected:36  /// All the vtables which have been defined.37  llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;38 39public:40  CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {41    assert(!cir::MissingFeatures::cxxabiUseARMMethodPtrABI());42    assert(!cir::MissingFeatures::cxxabiUseARMGuardVarABI());43  }44 45  AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,46                                               const CXXConstructorDecl *d,47                                               CXXCtorType type,48                                               bool forVirtualBase,49                                               bool delegating) override;50 51  bool needsVTTParameter(clang::GlobalDecl gd) override;52 53  AddedStructorArgCounts54  buildStructorSignature(GlobalDecl gd,55                         llvm::SmallVectorImpl<CanQualType> &argTys) override;56 57  void emitInstanceFunctionProlog(SourceLocation loc,58                                  CIRGenFunction &cgf) override;59 60  void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,61                                 FunctionArgList &params) override;62  mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,63                                            const CXXDestructorDecl *dd,64                                            CXXDtorType type,65                                            bool forVirtualBase,66                                            bool delegating) override;67  void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;68  void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;69  void emitCXXStructor(clang::GlobalDecl gd) override;70 71  void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,72                          CXXDtorType type, bool forVirtualBase,73                          bool delegating, Address thisAddr,74                          QualType thisTy) override;75  void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,76                          mlir::Value addr) override;77  void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,78                               Address ptr, QualType elementType,79                               const CXXDestructorDecl *dtor) override;80 81  void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;82  void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;83 84  bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,85                              CXXDtorType dt) const override {86    // Itanium does not emit any destructor variant as an inline thunk.87    // Delegating may occur as an optimization, but all variants are either88    // emitted with external linkage or as linkonce if they are inline and used.89    return false;90  }91 92  bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,93                                           CIRGenFunction::VPtr vptr) override;94 95  cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,96                                CharUnits vptrOffset) override;97  CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,98                                         clang::GlobalDecl gd, Address thisAddr,99                                         mlir::Type ty,100                                         SourceLocation loc) override;101  mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,102                                        const CXXDestructorDecl *dtor,103                                        CXXDtorType dtorType, Address thisAddr,104                                        DeleteOrMemberCallExpr e) override;105  mlir::Value getVTableAddressPoint(BaseSubobject base,106                                    const CXXRecordDecl *vtableClass) override;107  mlir::Value getVTableAddressPointInStructorWithVTT(108      CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,109      const CXXRecordDecl *nearestVBase);110 111  mlir::Value getVTableAddressPointInStructor(112      CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,113      clang::BaseSubobject base,114      const clang::CXXRecordDecl *nearestVBase) override;115  void emitVTableDefinitions(CIRGenVTables &cgvt,116                             const CXXRecordDecl *rd) override;117  void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;118 119  mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,120                                          QualType ty) override;121 122  bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {123    return true;124  }125 126  size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,127                              FunctionArgList &args) const override {128    assert(!args.empty() && "expected the arglist to not be empty!");129    return args.size() - 1;130  }131 132  void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;133 134  mlir::Value135  getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,136                            Address thisAddr, const CXXRecordDecl *classDecl,137                            const CXXRecordDecl *baseClassDecl) override;138 139  // The traditional clang CodeGen emits calls to `__dynamic_cast` directly into140  // LLVM in the `emitDynamicCastCall` function. In CIR, `dynamic_cast`141  // expressions are lowered to `cir.dyn_cast` ops instead of calls to runtime142  // functions. So during CIRGen we don't need the `emitDynamicCastCall`143  // function that clang CodeGen has.144  mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,145                              QualType srcRecordTy, QualType destRecordTy,146                              cir::PointerType destCIRTy, bool isRefCast,147                              Address src) override;148 149  Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,150                                mlir::Value numElements, const CXXNewExpr *e,151                                QualType elementType) override;152 153protected:154  CharUnits getArrayCookieSizeImpl(QualType elementType) override;155 156  /**************************** RTTI Uniqueness ******************************/157  /// Returns true if the ABI requires RTTI type_info objects to be unique158  /// across a program.159  virtual bool shouldRTTIBeUnique() const { return true; }160 161public:162  /// What sort of unique-RTTI behavior should we use?163  enum RTTIUniquenessKind {164    /// We are guaranteeing, or need to guarantee, that the RTTI string165    /// is unique.166    RUK_Unique,167 168    /// We are not guaranteeing uniqueness for the RTTI string, so we169    /// can demote to hidden visibility but must use string comparisons.170    RUK_NonUniqueHidden,171 172    /// We are not guaranteeing uniqueness for the RTTI string, so we173    /// have to use string comparisons, but we also have to emit it with174    /// non-hidden visibility.175    RUK_NonUniqueVisible176  };177 178  /// Return the required visibility status for the given type and linkage in179  /// the current ABI.180  RTTIUniquenessKind181  classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;182};183 184} // namespace185 186void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,187                                                     CIRGenFunction &cgf) {188  // Naked functions have no prolog.189  if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {190    cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(),191                     "emitInstanceFunctionProlog: Naked");192  }193 194  /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue195  /// adjustments are required, because they are all handled by thunks.196  setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));197 198  /// Initialize the 'vtt' slot if needed.199  if (getStructorImplicitParamDecl(cgf)) {200    cir::LoadOp val = cgf.getBuilder().createLoad(201        cgf.getLoc(loc),202        cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf)));203    setStructorImplicitParamValue(cgf, val);204  }205 206  /// If this is a function that the ABI specifies returns 'this', initialize207  /// the return slot to this' at the start of the function.208  ///209  /// Unlike the setting of return types, this is done within the ABI210  /// implementation instead of by clients of CIRGenCXXBI because:211  /// 1) getThisValue is currently protected212  /// 2) in theory, an ABI could implement 'this' returns some other way;213  ///    HasThisReturn only specifies a contract, not the implementation214  if (hasThisReturn(cgf.curGD)) {215    cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(),216                     "emitInstanceFunctionProlog: hasThisReturn");217  }218}219 220CIRGenCXXABI::AddedStructorArgCounts221CIRGenItaniumCXXABI::buildStructorSignature(222    GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {223  clang::ASTContext &astContext = cgm.getASTContext();224 225  // All parameters are already in place except VTT, which goes after 'this'.226  // These are clang types, so we don't need to worry about sret yet.227 228  // Check if we need to add a VTT parameter (which has type void **).229  if ((isa<CXXConstructorDecl>(gd.getDecl()) ? gd.getCtorType() == Ctor_Base230                                             : gd.getDtorType() == Dtor_Base) &&231      cast<CXXMethodDecl>(gd.getDecl())->getParent()->getNumVBases() != 0) {232    assert(!cir::MissingFeatures::addressSpace());233    argTys.insert(argTys.begin() + 1,234                  astContext.getPointerType(235                      CanQualType::CreateUnsafe(astContext.VoidPtrTy)));236    return AddedStructorArgCounts::withPrefix(1);237  }238 239  return AddedStructorArgCounts{};240}241 242// Find out how to cirgen the complete destructor and constructor243namespace {244enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };245}246 247static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,248                                     const CXXMethodDecl *md) {249  if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)250    return StructorCIRGen::Emit;251 252  // The complete and base structors are not equivalent if there are any virtual253  // bases, so emit separate functions.254  if (md->getParent()->getNumVBases())255    return StructorCIRGen::Emit;256 257  GlobalDecl aliasDecl;258  if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {259    aliasDecl = GlobalDecl(dd, Dtor_Complete);260  } else {261    const auto *cd = cast<CXXConstructorDecl>(md);262    aliasDecl = GlobalDecl(cd, Ctor_Complete);263  }264 265  cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);266 267  if (cir::isDiscardableIfUnused(linkage))268    return StructorCIRGen::RAUW;269 270  // FIXME: Should we allow available_externally aliases?271  if (!cir::isValidLinkage(linkage))272    return StructorCIRGen::RAUW;273 274  if (cir::isWeakForLinker(linkage)) {275    // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).276    if (cgm.getTarget().getTriple().isOSBinFormatELF() ||277        cgm.getTarget().getTriple().isOSBinFormatWasm())278      return StructorCIRGen::COMDAT;279    return StructorCIRGen::Emit;280  }281 282  return StructorCIRGen::Alias;283}284 285static void emitConstructorDestructorAlias(CIRGenModule &cgm,286                                           GlobalDecl aliasDecl,287                                           GlobalDecl targetDecl) {288  cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);289 290  // Does this function alias already exists?291  StringRef mangledName = cgm.getMangledName(aliasDecl);292  auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(293      cgm.getGlobalValue(mangledName));294  if (globalValue && !globalValue.isDeclaration())295    return;296 297  auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));298 299  // Retrieve aliasee info.300  auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));301 302  // Populate actual alias.303  cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);304}305 306void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {307  auto *md = cast<CXXMethodDecl>(gd.getDecl());308  StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);309  const auto *cd = dyn_cast<CXXConstructorDecl>(md);310 311  if (cd ? gd.getCtorType() == Ctor_Complete312         : gd.getDtorType() == Dtor_Complete) {313    GlobalDecl baseDecl =314        cd ? gd.getWithCtorType(Ctor_Base) : gd.getWithDtorType(Dtor_Base);315    ;316 317    if (cirGenType == StructorCIRGen::Alias ||318        cirGenType == StructorCIRGen::COMDAT) {319      emitConstructorDestructorAlias(cgm, gd, baseDecl);320      return;321    }322 323    if (cirGenType == StructorCIRGen::RAUW) {324      StringRef mangledName = cgm.getMangledName(gd);325      mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);326      cgm.addReplacement(mangledName, aliasee);327      return;328    }329  }330 331  auto fn = cgm.codegenCXXStructor(gd);332 333  cgm.maybeSetTrivialComdat(*md, fn);334}335 336void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,337                                                    QualType &resTy,338                                                    FunctionArgList &params) {339  const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());340  assert(isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md));341 342  // Check if we need a VTT parameter as well.343  if (needsVTTParameter(cgf.curGD)) {344    ASTContext &astContext = cgm.getASTContext();345 346    // FIXME: avoid the fake decl347    assert(!cir::MissingFeatures::addressSpace());348    QualType t = astContext.getPointerType(astContext.VoidPtrTy);349    auto *vttDecl = ImplicitParamDecl::Create(350        astContext, /*DC=*/nullptr, md->getLocation(),351        &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);352    params.insert(params.begin() + 1, vttDecl);353    getStructorImplicitParamDecl(cgf) = vttDecl;354  }355}356 357void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {358  // Just make sure we're in sync with TargetCXXABI.359  assert(cgm.getTarget().getCXXABI().hasConstructorVariants());360 361  // The constructor used for constructing this as a base class;362  // ignores virtual bases.363  cgm.emitGlobal(GlobalDecl(d, Ctor_Base));364 365  // The constructor used for constructing this as a complete class;366  // constructs the virtual bases, then calls the base constructor.367  if (!d->getParent()->isAbstract()) {368    // We don't need to emit the complete ctro if the class is abstract.369    cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));370  }371}372 373void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {374  // The destructor used for destructing this as a base class; ignores375  // virtual bases.376  cgm.emitGlobal(GlobalDecl(d, Dtor_Base));377 378  // The destructor used for destructing this as a most-derived class;379  // call the base destructor and then destructs any virtual bases.380  cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));381 382  // The destructor in a virtual table is always a 'deleting'383  // destructor, which calls the complete destructor and then uses the384  // appropriate operator delete.385  if (d->isVirtual())386    cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));387}388 389CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(390    CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,391    bool forVirtualBase, bool delegating) {392  if (!needsVTTParameter(GlobalDecl(d, type)))393    return AddedStructorArgs{};394 395  // Insert the implicit 'vtt' argument as the second argument. Make sure to396  // correctly reflect its address space, which can differ from generic on397  // some targets.398  mlir::Value vtt =399      cgf.getVTTParameter(GlobalDecl(d, type), forVirtualBase, delegating);400  QualType vttTy =401      cgm.getASTContext().getPointerType(cgm.getASTContext().VoidPtrTy);402  assert(!cir::MissingFeatures::addressSpace());403  return AddedStructorArgs::withPrefix({{vtt, vttTy}});404}405 406/// Return whether the given global decl needs a VTT (virtual table table)407/// parameter, which it does if it's a base constructor or destructor with408/// virtual bases.409bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {410  auto *md = cast<CXXMethodDecl>(gd.getDecl());411 412  // We don't have any virtual bases, just return early.413  if (!md->getParent()->getNumVBases())414    return false;415 416  // Check if we have a base constructor.417  if (isa<CXXConstructorDecl>(md) && gd.getCtorType() == Ctor_Base)418    return true;419 420  // Check if we have a base destructor.421  if (isa<CXXDestructorDecl>(md) && gd.getDtorType() == Dtor_Base)422    return true;423 424  return false;425}426 427void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,428                                                const CXXRecordDecl *rd) {429  cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());430  if (vtable.hasInitializer())431    return;432 433  ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();434  const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);435  cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);436  mlir::Attribute rtti =437      cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),438                                  cgm.getASTContext().getCanonicalTagType(rd));439 440  // Classic codegen uses ConstantInitBuilder here, which is a very general441  // and feature-rich class to generate initializers for global values.442  // For now, this is using a simpler approach to create the initializer in CIR.443  cgvt.createVTableInitializer(vtable, vtLayout, rtti,444                               cir::isLocalLinkage(linkage));445 446  // Set the correct linkage.447  vtable.setLinkage(linkage);448 449  if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))450    vtable.setComdat(true);451 452  // Set the right visibility.453  cgm.setGVProperties(vtable, rd);454 455  // If this is the magic class __cxxabiv1::__fundamental_type_info,456  // we will emit the typeinfo for the fundamental types. This is the457  // same behaviour as GCC.458  const DeclContext *DC = rd->getDeclContext();459  if (rd->getIdentifier() &&460      rd->getIdentifier()->isStr("__fundamental_type_info") &&461      isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&462      cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&463      DC->getParent()->isTranslationUnit()) {464    cgm.errorNYI(rd->getSourceRange(),465                 "emitVTableDefinitions: __fundamental_type_info");466  }467 468  [[maybe_unused]] auto vtableAsGlobalValue =469      dyn_cast<cir::CIRGlobalValueInterface>(*vtable);470  assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");471  // Always emit type metadata on non-available_externally definitions, and on472  // available_externally definitions if we are performing whole program473  // devirtualization. For WPD we need the type metadata on all vtable474  // definitions to ensure we associate derived classes with base classes475  // defined in headers but with a strong definition only in a shared476  // library.477  assert(!cir::MissingFeatures::vtableEmitMetadata());478  if (cgm.getCodeGenOpts().WholeProgramVTables) {479    cgm.errorNYI(rd->getSourceRange(),480                 "emitVTableDefinitions: WholeProgramVTables");481  }482 483  assert(!cir::MissingFeatures::vtableRelativeLayout());484  if (vtContext.isRelativeLayout()) {485    cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");486  }487}488 489mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(490    CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,491    Address thisAddr, DeleteOrMemberCallExpr expr) {492  auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);493  auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);494  assert((callExpr != nullptr) ^ (delExpr != nullptr));495  assert(callExpr == nullptr || callExpr->arg_begin() == callExpr->arg_end());496  assert(dtorType == Dtor_Deleting || dtorType == Dtor_Complete);497 498  GlobalDecl globalDecl(dtor, dtorType);499  const CIRGenFunctionInfo *fnInfo =500      &cgm.getTypes().arrangeCXXStructorDeclaration(globalDecl);501  const cir::FuncType &fnTy = cgm.getTypes().getFunctionType(*fnInfo);502  auto callee = CIRGenCallee::forVirtual(callExpr, globalDecl, thisAddr, fnTy);503 504  QualType thisTy =505      callExpr ? callExpr->getObjectType() : delExpr->getDestroyedType();506 507  cgf.emitCXXDestructorCall(globalDecl, callee, thisAddr.emitRawPointer(),508                            thisTy, nullptr, QualType(), nullptr);509  return nullptr;510}511 512void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(513    const CXXRecordDecl *rd) {514  CIRGenVTables &vtables = cgm.getVTables();515  cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);516  vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);517}518 519namespace {520class CIRGenItaniumRTTIBuilder {521  CIRGenModule &cgm;                 // Per-module state.522  const CIRGenItaniumCXXABI &cxxABI; // Per-module state.523 524  /// The fields of the RTTI descriptor currently being built.525  SmallVector<mlir::Attribute, 16> fields;526 527  // Returns the mangled type name of the given type.528  cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,529                                  cir::GlobalLinkageKind linkage);530 531  /// descriptor of the given type.532  mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,533                                                  QualType ty);534 535  /// Build the vtable pointer for the given type.536  void buildVTablePointer(mlir::Location loc, const Type *ty);537 538  /// Build an abi::__si_class_type_info, used for single inheritance, according539  /// to the Itanium C++ ABI, 2.9.5p6b.540  void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);541 542  /// Build an abi::__vmi_class_type_info, used for543  /// classes with bases that do not satisfy the abi::__si_class_type_info544  /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.545  void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);546 547public:548  CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)549      : cgm(cgm), cxxABI(abi) {}550 551  /// Build the RTTI type info struct for the given type, or552  /// link to an existing RTTI descriptor if one already exists.553  mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);554 555  /// Build the RTTI type info struct for the given type.556  mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,557                                cir::GlobalLinkageKind linkage,558                                mlir::SymbolTable::Visibility visibility);559};560} // namespace561 562// TODO(cir): Will be removed after sharing them with the classical codegen563namespace {564 565// Pointer type info flags.566enum {567  /// PTI_Const - Type has const qualifier.568  PTI_Const = 0x1,569 570  /// PTI_Volatile - Type has volatile qualifier.571  PTI_Volatile = 0x2,572 573  /// PTI_Restrict - Type has restrict qualifier.574  PTI_Restrict = 0x4,575 576  /// PTI_Incomplete - Type is incomplete.577  PTI_Incomplete = 0x8,578 579  /// PTI_ContainingClassIncomplete - Containing class is incomplete.580  /// (in pointer to member).581  PTI_ContainingClassIncomplete = 0x10,582 583  /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).584  // PTI_TransactionSafe = 0x20,585 586  /// PTI_Noexcept - Pointee is noexcept function (C++1z).587  PTI_Noexcept = 0x40,588};589 590// VMI type info flags.591enum {592  /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.593  VMI_NonDiamondRepeat = 0x1,594 595  /// VMI_DiamondShaped - Class is diamond shaped.596  VMI_DiamondShaped = 0x2597};598 599// Base class type info flags.600enum {601  /// BCTI_Virtual - Base class is virtual.602  BCTI_Virtual = 0x1,603 604  /// BCTI_Public - Base class is public.605  BCTI_Public = 0x2606};607 608/// Given a builtin type, returns whether the type609/// info for that type is defined in the standard library.610/// TODO(cir): this can unified with LLVM codegen611static bool typeInfoIsInStandardLibrary(const BuiltinType *ty) {612  // Itanium C++ ABI 2.9.2:613  //   Basic type information (e.g. for "int", "bool", etc.) will be kept in614  //   the run-time support library. Specifically, the run-time support615  //   library should contain type_info objects for the types X, X* and616  //   X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,617  //   unsigned char, signed char, short, unsigned short, int, unsigned int,618  //   long, unsigned long, long long, unsigned long long, float, double,619  //   long double, char16_t, char32_t, and the IEEE 754r decimal and620  //   half-precision floating point types.621  //622  // GCC also emits RTTI for __int128.623  // FIXME: We do not emit RTTI information for decimal types here.624 625  // Types added here must also be added to emitFundamentalRTTIDescriptors.626  switch (ty->getKind()) {627  case BuiltinType::WasmExternRef:628  case BuiltinType::HLSLResource:629    llvm_unreachable("NYI");630  case BuiltinType::Void:631  case BuiltinType::NullPtr:632  case BuiltinType::Bool:633  case BuiltinType::WChar_S:634  case BuiltinType::WChar_U:635  case BuiltinType::Char_U:636  case BuiltinType::Char_S:637  case BuiltinType::UChar:638  case BuiltinType::SChar:639  case BuiltinType::Short:640  case BuiltinType::UShort:641  case BuiltinType::Int:642  case BuiltinType::UInt:643  case BuiltinType::Long:644  case BuiltinType::ULong:645  case BuiltinType::LongLong:646  case BuiltinType::ULongLong:647  case BuiltinType::Half:648  case BuiltinType::Float:649  case BuiltinType::Double:650  case BuiltinType::LongDouble:651  case BuiltinType::Float16:652  case BuiltinType::Float128:653  case BuiltinType::Ibm128:654  case BuiltinType::Char8:655  case BuiltinType::Char16:656  case BuiltinType::Char32:657  case BuiltinType::Int128:658  case BuiltinType::UInt128:659    return true;660 661#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \662  case BuiltinType::Id:663#include "clang/Basic/OpenCLImageTypes.def"664#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:665#include "clang/Basic/OpenCLExtensionTypes.def"666  case BuiltinType::OCLSampler:667  case BuiltinType::OCLEvent:668  case BuiltinType::OCLClkEvent:669  case BuiltinType::OCLQueue:670  case BuiltinType::OCLReserveID:671#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:672#include "clang/Basic/AArch64ACLETypes.def"673#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:674#include "clang/Basic/PPCTypes.def"675#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:676#include "clang/Basic/RISCVVTypes.def"677#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:678#include "clang/Basic/AMDGPUTypes.def"679  case BuiltinType::ShortAccum:680  case BuiltinType::Accum:681  case BuiltinType::LongAccum:682  case BuiltinType::UShortAccum:683  case BuiltinType::UAccum:684  case BuiltinType::ULongAccum:685  case BuiltinType::ShortFract:686  case BuiltinType::Fract:687  case BuiltinType::LongFract:688  case BuiltinType::UShortFract:689  case BuiltinType::UFract:690  case BuiltinType::ULongFract:691  case BuiltinType::SatShortAccum:692  case BuiltinType::SatAccum:693  case BuiltinType::SatLongAccum:694  case BuiltinType::SatUShortAccum:695  case BuiltinType::SatUAccum:696  case BuiltinType::SatULongAccum:697  case BuiltinType::SatShortFract:698  case BuiltinType::SatFract:699  case BuiltinType::SatLongFract:700  case BuiltinType::SatUShortFract:701  case BuiltinType::SatUFract:702  case BuiltinType::SatULongFract:703  case BuiltinType::BFloat16:704    return false;705 706  case BuiltinType::Dependent:707#define BUILTIN_TYPE(Id, SingletonId)708#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:709#include "clang/AST/BuiltinTypes.def"710    llvm_unreachable("asking for RRTI for a placeholder type!");711 712  case BuiltinType::ObjCId:713  case BuiltinType::ObjCClass:714  case BuiltinType::ObjCSel:715    llvm_unreachable("FIXME: Objective-C types are unsupported!");716  }717 718  llvm_unreachable("Invalid BuiltinType Kind!");719}720 721static bool typeInfoIsInStandardLibrary(const PointerType *pointerTy) {722  QualType pointeeTy = pointerTy->getPointeeType();723  const auto *builtinTy = dyn_cast<BuiltinType>(pointeeTy);724  if (!builtinTy)725    return false;726 727  // Check the qualifiers.728  Qualifiers quals = pointeeTy.getQualifiers();729  quals.removeConst();730 731  if (!quals.empty())732    return false;733 734  return typeInfoIsInStandardLibrary(builtinTy);735}736 737/// IsStandardLibraryRTTIDescriptor - Returns whether the type738/// information for the given type exists in the standard library.739static bool isStandardLibraryRttiDescriptor(QualType ty) {740  // Type info for builtin types is defined in the standard library.741  if (const auto *builtinTy = dyn_cast<BuiltinType>(ty))742    return typeInfoIsInStandardLibrary(builtinTy);743 744  // Type info for some pointer types to builtin types is defined in the745  // standard library.746  if (const auto *pointerTy = dyn_cast<PointerType>(ty))747    return typeInfoIsInStandardLibrary(pointerTy);748 749  return false;750}751 752/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for753/// the given type exists somewhere else, and that we should not emit the type754/// information in this translation unit.  Assumes that it is not a755/// standard-library type.756static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {757  ASTContext &context = cgm.getASTContext();758 759  // If RTTI is disabled, assume it might be disabled in the760  // translation unit that defines any potential key function, too.761  if (!context.getLangOpts().RTTI)762    return false;763 764  if (const auto *recordTy = dyn_cast<RecordType>(ty)) {765    const auto *rd =766        cast<CXXRecordDecl>(recordTy->getDecl())->getDefinitionOrSelf();767    if (!rd->hasDefinition())768      return false;769 770    if (!rd->isDynamicClass())771      return false;772 773    // FIXME: this may need to be reconsidered if the key function774    // changes.775    // N.B. We must always emit the RTTI data ourselves if there exists a key776    // function.777    bool isDLLImport = rd->hasAttr<DLLImportAttr>();778 779    // Don't import the RTTI but emit it locally.780    if (cgm.getTriple().isOSCygMing())781      return false;782 783    if (cgm.getVTables().isVTableExternal(rd)) {784      if (cgm.getTarget().hasPS4DLLImportExport())785        return true;786 787      return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();788    }789 790    if (isDLLImport)791      return true;792  }793 794  return false;795}796 797/// Contains virtual and non-virtual bases seen when traversing a class798/// hierarchy.799struct SeenBases {800  llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;801  llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;802};803 804/// Compute the value of the flags member in abi::__vmi_class_type_info.805///806static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,807                                             SeenBases &bases) {808 809  unsigned flags = 0;810  auto *baseDecl = base->getType()->castAsCXXRecordDecl();811 812  if (base->isVirtual()) {813    // Mark the virtual base as seen.814    if (!bases.virtualBases.insert(baseDecl).second) {815      // If this virtual base has been seen before, then the class is diamond816      // shaped.817      flags |= VMI_DiamondShaped;818    } else {819      if (bases.nonVirtualBases.count(baseDecl))820        flags |= VMI_NonDiamondRepeat;821    }822  } else {823    // Mark the non-virtual base as seen.824    if (!bases.nonVirtualBases.insert(baseDecl).second) {825      // If this non-virtual base has been seen before, then the class has non-826      // diamond shaped repeated inheritance.827      flags |= VMI_NonDiamondRepeat;828    } else {829      if (bases.virtualBases.count(baseDecl))830        flags |= VMI_NonDiamondRepeat;831    }832  }833 834  // Walk all bases.835  for (const auto &bs : baseDecl->bases())836    flags |= computeVmiClassTypeInfoFlags(&bs, bases);837 838  return flags;839}840 841static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {842  unsigned flags = 0;843  SeenBases bases;844 845  // Walk all bases.846  for (const auto &bs : rd->bases())847    flags |= computeVmiClassTypeInfoFlags(&bs, bases);848 849  return flags;850}851 852// Return whether the given record decl has a "single,853// public, non-virtual base at offset zero (i.e. the derived class is dynamic854// iff the base is)", according to Itanium C++ ABI, 2.95p6b.855// TODO(cir): this can unified with LLVM codegen856static bool canUseSingleInheritance(const CXXRecordDecl *rd) {857  // Check the number of bases.858  if (rd->getNumBases() != 1)859    return false;860 861  // Get the base.862  CXXRecordDecl::base_class_const_iterator base = rd->bases_begin();863 864  // Check that the base is not virtual.865  if (base->isVirtual())866    return false;867 868  // Check that the base is public.869  if (base->getAccessSpecifier() != AS_public)870    return false;871 872  // Check that the class is dynamic iff the base is.873  auto *baseDecl = base->getType()->castAsCXXRecordDecl();874  return baseDecl->isEmpty() ||875         baseDecl->isDynamicClass() == rd->isDynamicClass();876}877 878/// IsIncompleteClassType - Returns whether the given record type is incomplete.879static bool isIncompleteClassType(const RecordType *recordTy) {880  return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();881}882 883/// Returns whether the given type contains an884/// incomplete class type. This is true if885///886///   * The given type is an incomplete class type.887///   * The given type is a pointer type whose pointee type contains an888///     incomplete class type.889///   * The given type is a member pointer type whose class is an incomplete890///     class type.891///   * The given type is a member pointer type whoise pointee type contains an892///     incomplete class type.893/// is an indirect or direct pointer to an incomplete class type.894static bool containsIncompleteClassType(QualType ty) {895  if (const auto *recordTy = dyn_cast<RecordType>(ty)) {896    if (isIncompleteClassType(recordTy))897      return true;898  }899 900  if (const auto *pointerTy = dyn_cast<PointerType>(ty))901    return containsIncompleteClassType(pointerTy->getPointeeType());902 903  if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) {904    // Check if the class type is incomplete.905    if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())906      return true;907 908    return containsIncompleteClassType(memberPointerTy->getPointeeType());909  }910 911  return false;912}913 914const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {915  // abi::__class_type_info.916  static const char *const classTypeInfo =917      "_ZTVN10__cxxabiv117__class_type_infoE";918  // abi::__si_class_type_info.919  static const char *const siClassTypeInfo =920      "_ZTVN10__cxxabiv120__si_class_type_infoE";921  // abi::__vmi_class_type_info.922  static const char *const vmiClassTypeInfo =923      "_ZTVN10__cxxabiv121__vmi_class_type_infoE";924 925  switch (ty->getTypeClass()) {926#define TYPE(Class, Base)927#define ABSTRACT_TYPE(Class, Base)928#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:929#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:930#define DEPENDENT_TYPE(Class, Base) case Type::Class:931#include "clang/AST/TypeNodes.inc"932    llvm_unreachable("Non-canonical and dependent types shouldn't get here");933 934  case Type::LValueReference:935  case Type::RValueReference:936    llvm_unreachable("References shouldn't get here");937 938  case Type::Auto:939  case Type::DeducedTemplateSpecialization:940    llvm_unreachable("Undeduced type shouldn't get here");941 942  case Type::Pipe:943    llvm_unreachable("Pipe types shouldn't get here");944 945  case Type::ArrayParameter:946    llvm_unreachable("Array Parameter types should not get here.");947 948  case Type::Builtin:949  case Type::BitInt:950  // GCC treats vector and complex types as fundamental types.951  case Type::Vector:952  case Type::ExtVector:953  case Type::ConstantMatrix:954  case Type::Complex:955  case Type::Atomic:956  // FIXME: GCC treats block pointers as fundamental types?!957  case Type::BlockPointer:958    return "_ZTVN10__cxxabiv123__fundamental_type_infoE";959  case Type::ConstantArray:960  case Type::IncompleteArray:961  case Type::VariableArray:962    cgm.errorNYI("VTableClassNameForType: __array_type_info");963    break;964 965  case Type::FunctionNoProto:966  case Type::FunctionProto:967    cgm.errorNYI("VTableClassNameForType: __function_type_info");968    break;969 970  case Type::Enum:971    return "_ZTVN10__cxxabiv116__enum_type_infoE";972 973  case Type::Record: {974    const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())975                         ->getDefinitionOrSelf();976 977    if (!rd->hasDefinition() || !rd->getNumBases()) {978      return classTypeInfo;979    }980 981    if (canUseSingleInheritance(rd)) {982      return siClassTypeInfo;983    }984 985    return vmiClassTypeInfo;986  }987 988  case Type::ObjCObject:989    cgm.errorNYI("VTableClassNameForType: ObjCObject");990    break;991 992  case Type::ObjCInterface:993    cgm.errorNYI("VTableClassNameForType: ObjCInterface");994    break;995 996  case Type::ObjCObjectPointer:997  case Type::Pointer:998    cgm.errorNYI("VTableClassNameForType: __pointer_type_info");999    break;1000 1001  case Type::MemberPointer:1002    cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info");1003    break;1004 1005  case Type::HLSLAttributedResource:1006  case Type::HLSLInlineSpirv:1007    llvm_unreachable("HLSL doesn't support virtual functions");1008  }1009 1010  return nullptr;1011}1012} // namespace1013 1014/// Return the linkage that the type info and type info name constants1015/// should have for the given type.1016static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,1017                                                 QualType ty) {1018  //   In addition, it and all of the intermediate abi::__pointer_type_info1019  //   structs in the chain down to the abi::__class_type_info for the1020  //   incomplete class type must be prevented from resolving to the1021  //   corresponding type_info structs for the complete class type, possibly1022  //   by making them local static objects. Finally, a dummy class RTTI is1023  //   generated for the incomplete type that will not resolve to the final1024  //   complete class RTTI (because the latter need not exist), possibly by1025  //   making it a local static object.1026  if (containsIncompleteClassType(ty))1027    return cir::GlobalLinkageKind::InternalLinkage;1028 1029  switch (ty->getLinkage()) {1030  case Linkage::Invalid:1031    llvm_unreachable("Linkage hasn't been computed!");1032 1033  case Linkage::None:1034  case Linkage::Internal:1035  case Linkage::UniqueExternal:1036    return cir::GlobalLinkageKind::InternalLinkage;1037 1038  case Linkage::VisibleNone:1039  case Linkage::Module:1040  case Linkage::External:1041    // RTTI is not enabled, which means that this type info struct is going1042    // to be used for exception handling. Give it linkonce_odr linkage.1043    if (!cgm.getLangOpts().RTTI)1044      return cir::GlobalLinkageKind::LinkOnceODRLinkage;1045 1046    if (const RecordType *record = dyn_cast<RecordType>(ty)) {1047      const auto *rd =1048          cast<CXXRecordDecl>(record->getDecl())->getDefinitionOrSelf();1049      if (rd->hasAttr<WeakAttr>())1050        return cir::GlobalLinkageKind::WeakODRLinkage;1051 1052      if (cgm.getTriple().isWindowsItaniumEnvironment())1053        if (rd->hasAttr<DLLImportAttr>() &&1054            shouldUseExternalRttiDescriptor(cgm, ty))1055          return cir::GlobalLinkageKind::ExternalLinkage;1056 1057      // MinGW always uses LinkOnceODRLinkage for type info.1058      if (rd->isDynamicClass() && !cgm.getASTContext()1059                                       .getTargetInfo()1060                                       .getTriple()1061                                       .isWindowsGNUEnvironment())1062        return cgm.getVTableLinkage(rd);1063    }1064 1065    return cir::GlobalLinkageKind::LinkOnceODRLinkage;1066  }1067 1068  llvm_unreachable("Invalid linkage!");1069}1070 1071cir::GlobalOp1072CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,1073                                            cir::GlobalLinkageKind linkage) {1074  CIRGenBuilderTy &builder = cgm.getBuilder();1075  SmallString<256> name;1076  llvm::raw_svector_ostream out(name);1077  cgm.getCXXABI().getMangleContext().mangleCXXRTTIName(ty, out);1078 1079  // We know that the mangled name of the type starts at index 4 of the1080  // mangled name of the typename, so we can just index into it in order to1081  // get the mangled name of the type.1082  mlir::Attribute init = builder.getString(1083      name.substr(4), cgm.convertType(cgm.getASTContext().CharTy),1084      std::nullopt);1085 1086  CharUnits align =1087      cgm.getASTContext().getTypeAlignInChars(cgm.getASTContext().CharTy);1088 1089  // builder.getString can return a #cir.zero if the string given to it only1090  // contains null bytes. However, type names cannot be full of null bytes.1091  // So cast Init to a ConstArrayAttr should be safe.1092  auto initStr = cast<cir::ConstArrayAttr>(init);1093 1094  cir::GlobalOp gv = cgm.createOrReplaceCXXRuntimeVariable(1095      loc, name, initStr.getType(), linkage, align);1096  CIRGenModule::setInitializer(gv, init);1097  return gv;1098}1099 1100mlir::Attribute1101CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,1102                                                          QualType ty) {1103  // Mangle the RTTI name.1104  SmallString<256> name;1105  llvm::raw_svector_ostream out(name);1106  cgm.getCXXABI().getMangleContext().mangleCXXRTTI(ty, out);1107  CIRGenBuilderTy &builder = cgm.getBuilder();1108 1109  // Look for an existing global.1110  cir::GlobalOp gv = dyn_cast_or_null<cir::GlobalOp>(1111      mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));1112 1113  if (!gv) {1114    // Create a new global variable.1115    // From LLVM codegen => Note for the future: If we would ever like to do1116    // deferred emission of RTTI, check if emitting vtables opportunistically1117    // need any adjustment.1118    gv = CIRGenModule::createGlobalOp(cgm, loc, name, builder.getUInt8PtrTy(),1119                                      /*isConstant=*/true);1120    const CXXRecordDecl *rd = ty->getAsCXXRecordDecl();1121    cgm.setGVProperties(gv, rd);1122 1123    // Import the typeinfo symbol when all non-inline virtual methods are1124    // imported.1125    if (cgm.getTarget().hasPS4DLLImportExport()) {1126      cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");1127    }1128  }1129 1130  return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);1131}1132 1133void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,1134                                                  const Type *ty) {1135  CIRGenBuilderTy &builder = cgm.getBuilder();1136  const char *vTableName = vTableClassNameForType(cgm, ty);1137 1138  // Check if the alias exists. If it doesn't, then get or create the global.1139  if (cgm.getItaniumVTableContext().isRelativeLayout()) {1140    cgm.errorNYI("buildVTablePointer: isRelativeLayout");1141    return;1142  }1143 1144  mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());1145  llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);1146  cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(1147      loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,1148      CharUnits::fromQuantity(align));1149 1150  // The vtable address point is 2.1151  mlir::Attribute field{};1152  if (cgm.getItaniumVTableContext().isRelativeLayout()) {1153    cgm.errorNYI("buildVTablePointer: isRelativeLayout");1154  } else {1155    SmallVector<mlir::Attribute, 4> offsets{1156        cgm.getBuilder().getI32IntegerAttr(2)};1157    auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);1158    field = cgm.getBuilder().getGlobalViewAttr(cgm.getBuilder().getUInt8PtrTy(),1159                                               vTable, indices);1160  }1161 1162  assert(field && "expected attribute");1163  fields.push_back(field);1164}1165 1166/// Build an abi::__si_class_type_info, used for single inheritance, according1167/// to the Itanium C++ ABI, 2.95p6b.1168void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,1169                                                    const CXXRecordDecl *rd) {1170  // Itanium C++ ABI 2.9.5p6b:1171  // It adds to abi::__class_type_info a single member pointing to the1172  // type_info structure for the base type,1173  mlir::Attribute baseTypeInfo =1174      CIRGenItaniumRTTIBuilder(cxxABI, cgm)1175          .buildTypeInfo(loc, rd->bases_begin()->getType());1176  fields.push_back(baseTypeInfo);1177}1178 1179/// Build an abi::__vmi_class_type_info, used for1180/// classes with bases that do not satisfy the abi::__si_class_type_info1181/// constraints, according to the Itanium C++ ABI, 2.9.5p5c.1182void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,1183                                                     const CXXRecordDecl *rd) {1184  mlir::Type unsignedIntLTy =1185      cgm.convertType(cgm.getASTContext().UnsignedIntTy);1186 1187  // Itanium C++ ABI 2.9.5p6c:1188  //   __flags is a word with flags describing details about the class1189  //   structure, which may be referenced by using the __flags_masks1190  //   enumeration. These flags refer to both direct and indirect bases.1191  unsigned flags = computeVmiClassTypeInfoFlags(rd);1192  fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));1193 1194  // Itanium C++ ABI 2.9.5p6c:1195  //   __base_count is a word with the number of direct proper base class1196  //   descriptions that follow.1197  fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));1198 1199  if (!rd->getNumBases())1200    return;1201 1202  // Now add the base class descriptions.1203 1204  // Itanium C++ ABI 2.9.5p6c:1205  //   __base_info[] is an array of base class descriptions -- one for every1206  //   direct proper base. Each description is of the type:1207  //1208  //   struct abi::__base_class_type_info {1209  //   public:1210  //     const __class_type_info *__base_type;1211  //     long __offset_flags;1212  //1213  //     enum __offset_flags_masks {1214  //       __virtual_mask = 0x1,1215  //       __public_mask = 0x2,1216  //       __offset_shift = 81217  //     };1218  //   };1219 1220  // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long1221  // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on1222  // LLP64 platforms.1223  // FIXME: Consider updating libc++abi to match, and extend this logic to all1224  // LLP64 platforms.1225  QualType offsetFlagsTy = cgm.getASTContext().LongTy;1226  const TargetInfo &ti = cgm.getASTContext().getTargetInfo();1227  if (ti.getTriple().isOSCygMing() &&1228      ti.getPointerWidth(LangAS::Default) > ti.getLongWidth())1229    offsetFlagsTy = cgm.getASTContext().LongLongTy;1230  mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);1231 1232  for (const CXXBaseSpecifier &base : rd->bases()) {1233    // The __base_type member points to the RTTI for the base type.1234    fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)1235                         .buildTypeInfo(loc, base.getType()));1236 1237    CXXRecordDecl *baseDecl = base.getType()->castAsCXXRecordDecl();1238    int64_t offsetFlags = 0;1239 1240    // All but the lower 8 bits of __offset_flags are a signed offset.1241    // For a non-virtual base, this is the offset in the object of the base1242    // subobject. For a virtual base, this is the offset in the virtual table of1243    // the virtual base offset for the virtual base referenced (negative).1244    CharUnits offset;1245    if (base.isVirtual())1246      offset = cgm.getItaniumVTableContext().getVirtualBaseOffsetOffset(1247          rd, baseDecl);1248    else {1249      const ASTRecordLayout &layout =1250          cgm.getASTContext().getASTRecordLayout(rd);1251      offset = layout.getBaseClassOffset(baseDecl);1252    }1253    offsetFlags = uint64_t(offset.getQuantity()) << 8;1254 1255    // The low-order byte of __offset_flags contains flags, as given by the1256    // masks from the enumeration __offset_flags_masks.1257    if (base.isVirtual())1258      offsetFlags |= BCTI_Virtual;1259    if (base.getAccessSpecifier() == AS_public)1260      offsetFlags |= BCTI_Public;1261 1262    fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));1263  }1264}1265 1266mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,1267                                                        QualType ty) {1268  // We want to operate on the canonical type.1269  ty = ty.getCanonicalType();1270 1271  // Check if we've already emitted an RTTI descriptor for this type.1272  SmallString<256> name;1273  llvm::raw_svector_ostream out(name);1274  cgm.getCXXABI().getMangleContext().mangleCXXRTTI(ty, out);1275 1276  auto oldGV = dyn_cast_or_null<cir::GlobalOp>(1277      mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));1278 1279  if (oldGV && !oldGV.isDeclaration()) {1280    assert(!oldGV.hasAvailableExternallyLinkage() &&1281           "available_externally typeinfos not yet implemented");1282    return cgm.getBuilder().getGlobalViewAttr(cgm.getBuilder().getUInt8PtrTy(),1283                                              oldGV);1284  }1285 1286  // Check if there is already an external RTTI descriptor for this type.1287  if (isStandardLibraryRttiDescriptor(ty) ||1288      shouldUseExternalRttiDescriptor(cgm, ty))1289    return getAddrOfExternalRTTIDescriptor(loc, ty);1290 1291  // Emit the standard library with external linkage.1292  cir::GlobalLinkageKind linkage = getTypeInfoLinkage(cgm, ty);1293 1294  // Give the type_info object and name the formal visibility of the1295  // type itself.1296  assert(!cir::MissingFeatures::hiddenVisibility());1297  assert(!cir::MissingFeatures::protectedVisibility());1298 1299  mlir::SymbolTable::Visibility symVisibility;1300  if (cir::isLocalLinkage(linkage))1301    // If the linkage is local, only default visibility makes sense.1302    symVisibility = mlir::SymbolTable::Visibility::Public;1303  else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==1304           CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {1305    cgm.errorNYI(1306        "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");1307    symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());1308  } else1309    symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());1310 1311  return buildTypeInfo(loc, ty, linkage, symVisibility);1312}1313 1314mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(1315    mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,1316    mlir::SymbolTable::Visibility visibility) {1317  CIRGenBuilderTy &builder = cgm.getBuilder();1318 1319  assert(!cir::MissingFeatures::setDLLStorageClass());1320 1321  // Add the vtable pointer.1322  buildVTablePointer(loc, cast<Type>(ty));1323 1324  // And the name.1325  cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);1326  mlir::Attribute typeNameField;1327 1328  // If we're supposed to demote the visibility, be sure to set a flag1329  // to use a string comparison for type_info comparisons.1330  CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =1331      cxxABI.classifyRTTIUniqueness(ty, linkage);1332  if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {1333    // The flag is the sign bit, which on ARM64 is defined to be clear1334    // for global pointers. This is very ARM64-specific.1335    cgm.errorNYI(1336        "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");1337  } else {1338    typeNameField =1339        builder.getGlobalViewAttr(builder.getUInt8PtrTy(), typeName);1340  }1341 1342  fields.push_back(typeNameField);1343 1344  switch (ty->getTypeClass()) {1345#define TYPE(Class, Base)1346#define ABSTRACT_TYPE(Class, Base)1347#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:1348#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:1349#define DEPENDENT_TYPE(Class, Base) case Type::Class:1350#include "clang/AST/TypeNodes.inc"1351    llvm_unreachable("Non-canonical and dependent types shouldn't get here");1352 1353  // GCC treats vector types as fundamental types.1354  case Type::Builtin:1355  case Type::Vector:1356  case Type::ExtVector:1357  case Type::ConstantMatrix:1358  case Type::Complex:1359  case Type::BlockPointer:1360    // Itanium C++ ABI 2.9.5p4:1361    // abi::__fundamental_type_info adds no data members to std::type_info.1362    break;1363 1364  case Type::LValueReference:1365  case Type::RValueReference:1366    llvm_unreachable("References shouldn't get here");1367 1368  case Type::Auto:1369  case Type::DeducedTemplateSpecialization:1370    llvm_unreachable("Undeduced type shouldn't get here");1371 1372  case Type::Pipe:1373    break;1374 1375  case Type::BitInt:1376    break;1377 1378  case Type::ConstantArray:1379  case Type::IncompleteArray:1380  case Type::VariableArray:1381  case Type::ArrayParameter:1382    // Itanium C++ ABI 2.9.5p5:1383    // abi::__array_type_info adds no data members to std::type_info.1384    break;1385 1386  case Type::FunctionNoProto:1387  case Type::FunctionProto:1388    // Itanium C++ ABI 2.9.5p5:1389    // abi::__function_type_info adds no data members to std::type_info.1390    break;1391 1392  case Type::Enum:1393    // Itanium C++ ABI 2.9.5p5:1394    // abi::__enum_type_info adds no data members to std::type_info.1395    break;1396 1397  case Type::Record: {1398    const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())1399                         ->getDefinitionOrSelf();1400    if (!rd->hasDefinition() || !rd->getNumBases()) {1401      // We don't need to emit any fields.1402      break;1403    }1404 1405    if (canUseSingleInheritance(rd)) {1406      buildSIClassTypeInfo(loc, rd);1407    } else {1408      buildVMIClassTypeInfo(loc, rd);1409    }1410 1411    break;1412  }1413 1414  case Type::ObjCObject:1415  case Type::ObjCInterface:1416    cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");1417    break;1418 1419  case Type::ObjCObjectPointer:1420    cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");1421    break;1422 1423  case Type::Pointer:1424    cgm.errorNYI("buildTypeInfo: Pointer");1425    break;1426 1427  case Type::MemberPointer:1428    cgm.errorNYI("buildTypeInfo: MemberPointer");1429    break;1430 1431  case Type::Atomic:1432    // No fields, at least for the moment.1433    break;1434 1435  case Type::HLSLAttributedResource:1436  case Type::HLSLInlineSpirv:1437    llvm_unreachable("HLSL doesn't support RTTI");1438  }1439 1440  assert(!cir::MissingFeatures::opGlobalDLLImportExport());1441  cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));1442 1443  SmallString<256> name;1444  llvm::raw_svector_ostream out(name);1445  cgm.getCXXABI().getMangleContext().mangleCXXRTTI(ty, out);1446 1447  // Create new global and search for an existing global.1448  auto oldGV = dyn_cast_or_null<cir::GlobalOp>(1449      mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));1450 1451  cir::GlobalOp gv =1452      CIRGenModule::createGlobalOp(cgm, loc, name, init.getType(),1453                                   /*isConstant=*/true);1454 1455  // Export the typeinfo in the same circumstances as the vtable is1456  // exported.1457  if (cgm.getTarget().hasPS4DLLImportExport()) {1458    cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");1459    return {};1460  }1461 1462  // If there's already an old global variable, replace it with the new one.1463  if (oldGV) {1464    // Replace occurrences of the old variable if needed.1465    gv.setName(oldGV.getName());1466    if (!oldGV->use_empty()) {1467      cgm.errorNYI("buildTypeInfo: old GV !use_empty");1468      return {};1469    }1470    oldGV->erase();1471  }1472 1473  if (cgm.supportsCOMDAT() && cir::isWeakForLinker(gv.getLinkage())) {1474    assert(!cir::MissingFeatures::setComdat());1475    cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");1476    return {};1477  }1478 1479  CharUnits align = cgm.getASTContext().toCharUnitsFromBits(1480      cgm.getTarget().getPointerAlign(LangAS::Default));1481  gv.setAlignmentAttr(cgm.getSize(align));1482 1483  // The Itanium ABI specifies that type_info objects must be globally1484  // unique, with one exception: if the type is an incomplete class1485  // type or a (possibly indirect) pointer to one.  That exception1486  // affects the general case of comparing type_info objects produced1487  // by the typeid operator, which is why the comparison operators on1488  // std::type_info generally use the type_info name pointers instead1489  // of the object addresses.  However, the language's built-in uses1490  // of RTTI generally require class types to be complete, even when1491  // manipulating pointers to those class types.  This allows the1492  // implementation of dynamic_cast to rely on address equality tests,1493  // which is much faster.1494 1495  // All of this is to say that it's important that both the type_info1496  // object and the type_info name be uniqued when weakly emitted.1497 1498  mlir::SymbolTable::setSymbolVisibility(typeName, visibility);1499  assert(!cir::MissingFeatures::setDLLStorageClass());1500  assert(!cir::MissingFeatures::opGlobalPartition());1501  assert(!cir::MissingFeatures::setDSOLocal());1502 1503  mlir::SymbolTable::setSymbolVisibility(gv, visibility);1504  assert(!cir::MissingFeatures::setDLLStorageClass());1505  assert(!cir::MissingFeatures::opGlobalPartition());1506  assert(!cir::MissingFeatures::setDSOLocal());1507 1508  CIRGenModule::setInitializer(gv, init);1509  return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);1510}1511 1512mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,1513                                                             QualType ty) {1514  return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);1515}1516 1517/// What sort of uniqueness rules should we use for the RTTI for the1518/// given type?1519CIRGenItaniumCXXABI::RTTIUniquenessKind1520CIRGenItaniumCXXABI::classifyRTTIUniqueness(1521    QualType canTy, cir::GlobalLinkageKind linkage) const {1522  if (shouldRTTIBeUnique())1523    return RUK_Unique;1524 1525  // It's only necessary for linkonce_odr or weak_odr linkage.1526  if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&1527      linkage != cir::GlobalLinkageKind::WeakODRLinkage)1528    return RUK_Unique;1529 1530  // It's only necessary with default visibility.1531  if (canTy->getVisibility() != DefaultVisibility)1532    return RUK_Unique;1533 1534  // If we're not required to publish this symbol, hide it.1535  if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)1536    return RUK_NonUniqueHidden;1537 1538  // If we're required to publish this symbol, as we might be under an1539  // explicit instantiation, leave it with default visibility but1540  // enable string-comparisons.1541  assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);1542  return RUK_NonUniqueVisible;1543}1544 1545void CIRGenItaniumCXXABI::emitDestructorCall(1546    CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,1547    bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {1548  GlobalDecl gd(dd, type);1549  mlir::Value vtt =1550      getCXXDestructorImplicitParam(cgf, dd, type, forVirtualBase, delegating);1551  ASTContext &astContext = cgm.getASTContext();1552  QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);1553  assert(!cir::MissingFeatures::appleKext());1554  CIRGenCallee callee =1555      CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd), gd);1556 1557  cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,1558                            vttTy, nullptr);1559}1560 1561void CIRGenItaniumCXXABI::registerGlobalDtor(const VarDecl *vd,1562                                             cir::FuncOp dtor,1563                                             mlir::Value addr) {1564  if (vd->isNoDestroy(cgm.getASTContext()))1565    return;1566 1567  if (vd->getTLSKind()) {1568    cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: TLS");1569    return;1570  }1571 1572  // HLSL doesn't support atexit.1573  if (cgm.getLangOpts().HLSL) {1574    cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: HLSL");1575    return;1576  }1577 1578  // The default behavior is to use atexit. This is handled in lowering1579  // prepare. Nothing to be done for CIR here.1580}1581 1582mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(1583    CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,1584    bool forVirtualBase, bool delegating) {1585  GlobalDecl gd(dd, type);1586  return cgf.getVTTParameter(gd, forVirtualBase, delegating);1587}1588 1589// The idea here is creating a separate block for the throw with an1590// `UnreachableOp` as the terminator. So, we branch from the current block1591// to the throw block and create a block for the remaining operations.1592static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,1593                                mlir::Value exceptionPtr = {},1594                                mlir::FlatSymbolRefAttr typeInfo = {},1595                                mlir::FlatSymbolRefAttr dtor = {}) {1596  mlir::Block *currentBlock = builder.getInsertionBlock();1597  mlir::Region *region = currentBlock->getParent();1598 1599  if (currentBlock->empty()) {1600    cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);1601    cir::UnreachableOp::create(builder, loc);1602  } else {1603    mlir::Block *throwBlock = builder.createBlock(region);1604 1605    cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);1606    cir::UnreachableOp::create(builder, loc);1607 1608    builder.setInsertionPointToEnd(currentBlock);1609    cir::BrOp::create(builder, loc, throwBlock);1610  }1611 1612  (void)builder.createBlock(region);1613}1614 1615void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {1616  // void __cxa_rethrow();1617  if (isNoReturn) {1618    CIRGenBuilderTy &builder = cgf.getBuilder();1619    assert(cgf.currSrcLoc && "expected source location");1620    mlir::Location loc = *cgf.currSrcLoc;1621    insertThrowAndSplit(builder, loc);1622  } else {1623    cgm.errorNYI("emitRethrow with isNoReturn false");1624  }1625}1626 1627void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,1628                                    const CXXThrowExpr *e) {1629  // This differs a bit from LLVM codegen, CIR has native operations for some1630  // cxa functions, and defers allocation size computation, always pass the dtor1631  // symbol, etc. CIRGen also does not use getAllocateExceptionFn / getThrowFn.1632 1633  // Now allocate the exception object.1634  CIRGenBuilderTy &builder = cgf.getBuilder();1635  QualType clangThrowType = e->getSubExpr()->getType();1636  cir::PointerType throwTy =1637      builder.getPointerTo(cgf.convertType(clangThrowType));1638  uint64_t typeSize =1639      cgf.getContext().getTypeSizeInChars(clangThrowType).getQuantity();1640  mlir::Location subExprLoc = cgf.getLoc(e->getSubExpr()->getSourceRange());1641 1642  // Defer computing allocation size to some later lowering pass.1643  mlir::TypedValue<cir::PointerType> exceptionPtr =1644      cir::AllocExceptionOp::create(builder, subExprLoc, throwTy,1645                                    builder.getI64IntegerAttr(typeSize))1646          .getAddr();1647 1648  // Build expression and store its result into exceptionPtr.1649  CharUnits exnAlign = cgf.getContext().getExnObjectAlignment();1650  cgf.emitAnyExprToExn(e->getSubExpr(), Address(exceptionPtr, exnAlign));1651 1652  // Get the RTTI symbol address.1653  auto typeInfo = mlir::cast<cir::GlobalViewAttr>(1654      cgm.getAddrOfRTTIDescriptor(subExprLoc, clangThrowType,1655                                  /*forEH=*/true));1656  assert(!typeInfo.getIndices() && "expected no indirection");1657 1658  // The address of the destructor.1659  //1660  // Note: LLVM codegen already optimizes out the dtor if the1661  // type is a record with trivial dtor (by passing down a1662  // null dtor). In CIR, we forward this info and allow for1663  // Lowering pass to skip passing the trivial function.1664  //1665  if (const RecordType *recordTy = clangThrowType->getAs<RecordType>()) {1666    auto *rec = cast<CXXRecordDecl>(recordTy->getDecl()->getDefinition());1667    assert(!cir::MissingFeatures::isTrivialCtorOrDtor());1668    if (!rec->hasTrivialDestructor()) {1669      cgm.errorNYI("emitThrow: non-trivial destructor");1670      return;1671    }1672  }1673 1674  // Now throw the exception.1675  mlir::Location loc = cgf.getLoc(e->getSourceRange());1676  insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol());1677}1678 1679CIRGenCXXABI *clang::CIRGen::CreateCIRGenItaniumCXXABI(CIRGenModule &cgm) {1680  switch (cgm.getASTContext().getCXXABIKind()) {1681  case TargetCXXABI::GenericItanium:1682  case TargetCXXABI::GenericAArch64:1683    return new CIRGenItaniumCXXABI(cgm);1684 1685  case TargetCXXABI::AppleARM64:1686    // The general Itanium ABI will do until we implement something that1687    // requires special handling.1688    assert(!cir::MissingFeatures::cxxabiAppleARM64CXXABI());1689    return new CIRGenItaniumCXXABI(cgm);1690 1691  default:1692    llvm_unreachable("bad or NYI ABI kind");1693  }1694}1695 1696cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,1697                                                   CharUnits vptrOffset) {1698  assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");1699  cir::GlobalOp &vtable = vtables[rd];1700  if (vtable)1701    return vtable;1702 1703  // Queue up this vtable for possible deferred emission.1704  assert(!cir::MissingFeatures::deferredVtables());1705 1706  SmallString<256> name;1707  llvm::raw_svector_ostream out(name);1708  getMangleContext().mangleCXXVTable(rd, out);1709 1710  const VTableLayout &vtLayout =1711      cgm.getItaniumVTableContext().getVTableLayout(rd);1712  mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);1713 1714  // Use pointer alignment for the vtable. Otherwise we would align them based1715  // on the size of the initializer which doesn't make sense as only single1716  // values are read.1717  unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()1718                          ? 321719                          : cgm.getTarget().getPointerAlign(LangAS::Default);1720 1721  vtable = cgm.createOrReplaceCXXRuntimeVariable(1722      cgm.getLoc(rd->getSourceRange()), name, vtableType,1723      cir::GlobalLinkageKind::ExternalLinkage,1724      cgm.getASTContext().toCharUnitsFromBits(ptrAlign));1725  // LLVM codegen handles unnamedAddr1726  assert(!cir::MissingFeatures::opGlobalUnnamedAddr());1727 1728  // In MS C++ if you have a class with virtual functions in which you are using1729  // selective member import/export, then all virtual functions must be exported1730  // unless they are inline, otherwise a link error will result. To match this1731  // behavior, for such classes, we dllimport the vtable if it is defined1732  // externally and all the non-inline virtual methods are marked dllimport, and1733  // we dllexport the vtable if it is defined in this TU and all the non-inline1734  // virtual methods are marked dllexport.1735  if (cgm.getTarget().hasPS4DLLImportExport())1736    cgm.errorNYI(rd->getSourceRange(),1737                 "getAddrOfVTable: PS4 DLL import/export");1738 1739  cgm.setGVProperties(vtable, rd);1740  return vtable;1741}1742 1743CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(1744    CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,1745    SourceLocation srcLoc) {1746  CIRGenBuilderTy &builder = cgm.getBuilder();1747  mlir::Location loc = cgf.getLoc(srcLoc);1748  cir::PointerType tyPtr = builder.getPointerTo(ty);1749  auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());1750  mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());1751 1752  uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);1753  mlir::Value vfunc{};1754  if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {1755    cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");1756  } else {1757    assert(!cir::MissingFeatures::emitTypeMetadataCodeForVCall());1758 1759    mlir::Value vfuncLoad;1760    if (cgm.getItaniumVTableContext().isRelativeLayout()) {1761      assert(!cir::MissingFeatures::vtableRelativeLayout());1762      cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");1763    } else {1764      auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(1765          builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);1766      vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,1767                                            cgf.getPointerAlign());1768    }1769 1770    // Add !invariant.load md to virtual function load to indicate that1771    // function didn't change inside vtable.1772    // It's safe to add it without -fstrict-vtable-pointers, but it would not1773    // help in devirtualization because it will only matter if we will have 21774    // the same virtual function loads from the same vtable load, which won't1775    // happen without enabled devirtualization with -fstrict-vtable-pointers.1776    if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&1777        cgm.getCodeGenOpts().StrictVTablePointers) {1778      cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");1779    }1780    vfunc = vfuncLoad;1781  }1782 1783  CIRGenCallee callee(gd, vfunc.getDefiningOp());1784  return callee;1785}1786 1787mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(1788    CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,1789    const CXXRecordDecl *nearestVBase) {1790  assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&1791         needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");1792 1793  // Get the secondary vpointer index.1794  uint64_t virtualPointerIndex =1795      cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);1796 1797  /// Load the VTT.1798  mlir::Value vttPtr = cgf.loadCXXVTT();1799  mlir::Location loc = cgf.getLoc(vtableClass->getSourceRange());1800  // Calculate the address point from the VTT, and the offset may be zero.1801  vttPtr = cgf.getBuilder().createVTTAddrPoint(loc, vttPtr.getType(), vttPtr,1802                                               virtualPointerIndex);1803  // And load the address point from the VTT.1804  auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());1805  return cgf.getBuilder().createAlignedLoad(loc, vptrType, vttPtr,1806                                            cgf.getPointerAlign());1807}1808 1809mlir::Value1810CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,1811                                           const CXXRecordDecl *vtableClass) {1812  cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());1813 1814  // Find the appropriate vtable within the vtable group, and the address point1815  // within that vtable.1816  VTableLayout::AddressPointLocation addressPoint =1817      cgm.getItaniumVTableContext()1818          .getVTableLayout(vtableClass)1819          .getAddressPoint(base);1820 1821  mlir::OpBuilder &builder = cgm.getBuilder();1822  auto vtablePtrTy = cir::VPtrType::get(builder.getContext());1823 1824  return cir::VTableAddrPointOp::create(1825      builder, cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,1826      mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),1827      cir::AddressPointAttr::get(cgm.getBuilder().getContext(),1828                                 addressPoint.VTableIndex,1829                                 addressPoint.AddressPointIndex));1830}1831 1832mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(1833    CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,1834    clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {1835 1836  if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&1837      needsVTTParameter(cgf.curGD)) {1838    return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,1839                                                  nearestVBase);1840  }1841  return getVTableAddressPoint(base, vtableClass);1842}1843 1844bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(1845    CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {1846  if (vptr.nearestVBase == nullptr)1847    return false;1848  return needsVTTParameter(cgf.curGD);1849}1850 1851mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(1852    mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,1853    const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {1854  CIRGenBuilderTy &builder = cgf.getBuilder();1855  mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);1856  mlir::Value vtableBytePtr = builder.createBitcast(vtablePtr, cgm.uInt8PtrTy);1857  CharUnits vbaseOffsetOffset =1858      cgm.getItaniumVTableContext().getVirtualBaseOffsetOffset(classDecl,1859                                                               baseClassDecl);1860  mlir::Value offsetVal =1861      builder.getSInt64(vbaseOffsetOffset.getQuantity(), loc);1862  auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.uInt8PtrTy,1863                                                 vtableBytePtr, offsetVal);1864 1865  mlir::Value vbaseOffset;1866  if (cgm.getItaniumVTableContext().isRelativeLayout()) {1867    assert(!cir::MissingFeatures::vtableRelativeLayout());1868    cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");1869  } else {1870    mlir::Value offsetPtr = builder.createBitcast(1871        vbaseOffsetPtr, builder.getPointerTo(cgm.ptrDiffTy));1872    vbaseOffset = builder.createLoad(1873        loc, Address(offsetPtr, cgm.ptrDiffTy, cgf.getPointerAlign()));1874  }1875  return vbaseOffset;1876}1877 1878static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {1879  // Prototype: void __cxa_bad_cast();1880 1881  // TODO(cir): set the calling convention of the runtime function.1882  assert(!cir::MissingFeatures::opFuncCallingConv());1883 1884  cir::FuncType fnTy =1885      cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());1886  return cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_cast");1887}1888 1889static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) {1890  // TODO(cir): set the calling convention to the runtime function.1891  assert(!cir::MissingFeatures::opFuncCallingConv());1892 1893  cgf.emitRuntimeCall(loc, getBadCastFn(cgf));1894  cir::UnreachableOp::create(cgf.getBuilder(), loc);1895  cgf.getBuilder().clearInsertionPoint();1896}1897 1898void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf,1899                                          mlir::Location loc) {1900  emitCallToBadCast(cgf, loc);1901}1902 1903// TODO(cir): This could be shared with classic codegen.1904static CharUnits computeOffsetHint(ASTContext &astContext,1905                                   const CXXRecordDecl *src,1906                                   const CXXRecordDecl *dst) {1907  CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,1908                     /*DetectVirtual=*/false);1909 1910  // If Dst is not derived from Src we can skip the whole computation below and1911  // return that Src is not a public base of Dst.  Record all inheritance paths.1912  if (!dst->isDerivedFrom(src, paths))1913    return CharUnits::fromQuantity(-2ULL);1914 1915  unsigned numPublicPaths = 0;1916  CharUnits offset;1917 1918  // Now walk all possible inheritance paths.1919  for (const CXXBasePath &path : paths) {1920    if (path.Access != AS_public) // Ignore non-public inheritance.1921      continue;1922 1923    ++numPublicPaths;1924 1925    for (const CXXBasePathElement &pathElement : path) {1926      // If the path contains a virtual base class we can't give any hint.1927      // -1: no hint.1928      if (pathElement.Base->isVirtual())1929        return CharUnits::fromQuantity(-1ULL);1930 1931      if (numPublicPaths > 1) // Won't use offsets, skip computation.1932        continue;1933 1934      // Accumulate the base class offsets.1935      const ASTRecordLayout &L =1936          astContext.getASTRecordLayout(pathElement.Class);1937      offset += L.getBaseClassOffset(1938          pathElement.Base->getType()->getAsCXXRecordDecl());1939    }1940  }1941 1942  // -2: Src is not a public base of Dst.1943  if (numPublicPaths == 0)1944    return CharUnits::fromQuantity(-2ULL);1945 1946  // -3: Src is a multiple public base type but never a virtual base type.1947  if (numPublicPaths > 1)1948    return CharUnits::fromQuantity(-3ULL);1949 1950  // Otherwise, the Src type is a unique public nonvirtual base type of Dst.1951  // Return the offset of Src from the origin of Dst.1952  return offset;1953}1954 1955static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {1956  // Prototype:1957  // void *__dynamic_cast(const void *sub,1958  //                      global_as const abi::__class_type_info *src,1959  //                      global_as const abi::__class_type_info *dst,1960  //                      std::ptrdiff_t src2dst_offset);1961 1962  mlir::Type voidPtrTy = cgf.getBuilder().getVoidPtrTy();1963  mlir::Type rttiPtrTy = cgf.getBuilder().getUInt8PtrTy();1964  mlir::Type ptrDiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());1965 1966  // TODO(cir): mark the function as nowind willreturn readonly.1967  assert(!cir::MissingFeatures::opFuncNoUnwind());1968  assert(!cir::MissingFeatures::opFuncWillReturn());1969  assert(!cir::MissingFeatures::opFuncReadOnly());1970 1971  // TODO(cir): set the calling convention of the runtime function.1972  assert(!cir::MissingFeatures::opFuncCallingConv());1973 1974  cir::FuncType FTy = cgf.getBuilder().getFuncType(1975      {voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);1976  return cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");1977}1978 1979static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc,1980                                     QualType srcRecordTy, Address src) {1981  bool vtableUsesRelativeLayout =1982      cgf.cgm.getItaniumVTableContext().isRelativeLayout();1983  mlir::Value ptr = cgf.getBuilder().createDynCastToVoid(1984      loc, src.getPointer(), vtableUsesRelativeLayout);1985  return Address{ptr, src.getAlignment()};1986}1987 1988static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi,1989                                        CIRGenFunction &cgf, mlir::Location loc,1990                                        QualType srcRecordTy,1991                                        QualType destRecordTy,1992                                        cir::PointerType destCIRTy,1993                                        bool isRefCast, Address src) {1994  // Find all the inheritance paths from SrcRecordTy to DestRecordTy.1995  const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();1996  const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();1997  CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,1998                     /*DetectVirtual=*/false);1999  (void)destDecl->isDerivedFrom(srcDecl, paths);2000 2001  // Find an offset within `destDecl` where a `srcDecl` instance and its vptr2002  // might appear.2003  std::optional<CharUnits> offset;2004  for (const CXXBasePath &path : paths) {2005    // dynamic_cast only finds public inheritance paths.2006    if (path.Access != AS_public)2007      continue;2008 2009    CharUnits pathOffset;2010    for (const CXXBasePathElement &pathElement : path) {2011      // Find the offset along this inheritance step.2012      const CXXRecordDecl *base =2013          pathElement.Base->getType()->getAsCXXRecordDecl();2014      if (pathElement.Base->isVirtual()) {2015        // For a virtual base class, we know that the derived class is exactly2016        // destDecl, so we can use the vbase offset from its layout.2017        const ASTRecordLayout &layout =2018            cgf.getContext().getASTRecordLayout(destDecl);2019        pathOffset = layout.getVBaseClassOffset(base);2020      } else {2021        const ASTRecordLayout &layout =2022            cgf.getContext().getASTRecordLayout(pathElement.Class);2023        pathOffset += layout.getBaseClassOffset(base);2024      }2025    }2026 2027    if (!offset) {2028      offset = pathOffset;2029    } else if (offset != pathOffset) {2030      // base appears in at least two different places. Find the most-derived2031      // object and see if it's a DestDecl. Note that the most-derived object2032      // must be at least as aligned as this base class subobject, and must2033      // have a vptr at offset 0.2034      src = emitDynamicCastToVoid(cgf, loc, srcRecordTy, src);2035      srcDecl = destDecl;2036      offset = CharUnits::Zero();2037      break;2038    }2039  }2040 2041  CIRGenBuilderTy &builder = cgf.getBuilder();2042 2043  if (!offset) {2044    // If there are no public inheritance paths, the cast always fails.2045    mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);2046    if (isRefCast) {2047      mlir::Region *currentRegion = builder.getBlock()->getParent();2048      emitCallToBadCast(cgf, loc);2049 2050      // The call to bad_cast will terminate the block. Create a new block to2051      // hold any follow up code.2052      builder.createBlock(currentRegion, currentRegion->end());2053    }2054 2055    return nullPtrValue;2056  }2057 2058  // Compare the vptr against the expected vptr for the destination type at2059  // this offset. Note that we do not know what type src points to in the case2060  // where the derived class multiply inherits from the base class so we can't2061  // use getVTablePtr, so we load the vptr directly instead.2062 2063  mlir::Value expectedVPtr =2064      abi.getVTableAddressPoint(BaseSubobject(srcDecl, *offset), destDecl);2065 2066  // TODO(cir): handle address space here.2067  assert(!cir::MissingFeatures::addressSpace());2068  mlir::Type vptrTy = expectedVPtr.getType();2069  mlir::Type vptrPtrTy = builder.getPointerTo(vptrTy);2070  Address srcVPtrPtr(builder.createBitcast(src.getPointer(), vptrPtrTy),2071                     src.getAlignment());2072  mlir::Value srcVPtr = builder.createLoad(loc, srcVPtrPtr);2073 2074  // TODO(cir): decorate SrcVPtr with TBAA info.2075  assert(!cir::MissingFeatures::opTBAA());2076 2077  mlir::Value success =2078      builder.createCompare(loc, cir::CmpOpKind::eq, srcVPtr, expectedVPtr);2079 2080  auto emitCastResult = [&] {2081    if (offset->isZero())2082      return builder.createBitcast(src.getPointer(), destCIRTy);2083 2084    // TODO(cir): handle address space here.2085    assert(!cir::MissingFeatures::addressSpace());2086    mlir::Type u8PtrTy = builder.getUInt8PtrTy();2087 2088    mlir::Value strideToApply =2089        builder.getConstInt(loc, builder.getUInt64Ty(), -offset->getQuantity());2090    mlir::Value srcU8Ptr = builder.createBitcast(src.getPointer(), u8PtrTy);2091    mlir::Value resultU8Ptr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,2092                                                       srcU8Ptr, strideToApply);2093    return builder.createBitcast(resultU8Ptr, destCIRTy);2094  };2095 2096  if (isRefCast) {2097    mlir::Value failed = builder.createNot(success);2098    cir::IfOp::create(builder, loc, failed, /*withElseRegion=*/false,2099                      [&](mlir::OpBuilder &, mlir::Location) {2100                        emitCallToBadCast(cgf, loc);2101                      });2102    return emitCastResult();2103  }2104 2105  return cir::TernaryOp::create(2106             builder, loc, success,2107             [&](mlir::OpBuilder &, mlir::Location) {2108               auto result = emitCastResult();2109               builder.createYield(loc, result);2110             },2111             [&](mlir::OpBuilder &, mlir::Location) {2112               mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);2113               builder.createYield(loc, nullPtrValue);2114             })2115      .getResult();2116}2117 2118static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf,2119                                                    mlir::Location loc,2120                                                    QualType srcRecordTy,2121                                                    QualType destRecordTy) {2122  auto srcRtti = mlir::cast<cir::GlobalViewAttr>(2123      cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy));2124  auto destRtti = mlir::cast<cir::GlobalViewAttr>(2125      cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy));2126 2127  cir::FuncOp runtimeFuncOp = getItaniumDynamicCastFn(cgf);2128  cir::FuncOp badCastFuncOp = getBadCastFn(cgf);2129  auto runtimeFuncRef = mlir::FlatSymbolRefAttr::get(runtimeFuncOp);2130  auto badCastFuncRef = mlir::FlatSymbolRefAttr::get(badCastFuncOp);2131 2132  const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();2133  const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();2134  CharUnits offsetHint = computeOffsetHint(cgf.getContext(), srcDecl, destDecl);2135 2136  mlir::Type ptrdiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());2137  auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());2138 2139  return cir::DynamicCastInfoAttr::get(srcRtti, destRtti, runtimeFuncRef,2140                                       badCastFuncRef, offsetHintAttr);2141}2142 2143mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,2144                                                 mlir::Location loc,2145                                                 QualType srcRecordTy,2146                                                 QualType destRecordTy,2147                                                 cir::PointerType destCIRTy,2148                                                 bool isRefCast, Address src) {2149  bool isCastToVoid = destRecordTy.isNull();2150  assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference");2151 2152  if (isCastToVoid)2153    return emitDynamicCastToVoid(cgf, loc, srcRecordTy, src).getPointer();2154 2155  // If the destination is effectively final, the cast succeeds if and only2156  // if the dynamic type of the pointer is exactly the destination type.2157  if (destRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&2158      cgf.cgm.getCodeGenOpts().OptimizationLevel > 0) {2159    CIRGenBuilderTy &builder = cgf.getBuilder();2160    // If this isn't a reference cast, check the pointer to see if it's null.2161    if (!isRefCast) {2162      mlir::Value srcPtrIsNull = builder.createPtrIsNull(src.getPointer());2163      return cir::TernaryOp::create(2164                 builder, loc, srcPtrIsNull,2165                 [&](mlir::OpBuilder, mlir::Location) {2166                   builder.createYield(2167                       loc, builder.getNullPtr(destCIRTy, loc).getResult());2168                 },2169                 [&](mlir::OpBuilder &, mlir::Location) {2170                   mlir::Value exactCast = emitExactDynamicCast(2171                       *this, cgf, loc, srcRecordTy, destRecordTy, destCIRTy,2172                       isRefCast, src);2173                   builder.createYield(loc, exactCast);2174                 })2175          .getResult();2176    }2177 2178    return emitExactDynamicCast(*this, cgf, loc, srcRecordTy, destRecordTy,2179                                destCIRTy, isRefCast, src);2180  }2181 2182  cir::DynamicCastInfoAttr castInfo =2183      emitDynamicCastInfo(cgf, loc, srcRecordTy, destRecordTy);2184  return cgf.getBuilder().createDynCast(loc, src.getPointer(), destCIRTy,2185                                        isRefCast, castInfo);2186}2187 2188/// The Itanium ABI always places an offset to the complete object2189/// at entry -2 in the vtable.2190void CIRGenItaniumCXXABI::emitVirtualObjectDelete(2191    CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,2192    QualType elementType, const CXXDestructorDecl *dtor) {2193  bool useGlobalDelete = delExpr->isGlobalDelete();2194  if (useGlobalDelete) {2195    cgf.cgm.errorNYI(delExpr->getSourceRange(),2196                     "emitVirtualObjectDelete: global delete");2197  }2198 2199  CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;2200  emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);2201}2202 2203/************************** Array allocation cookies **************************/2204 2205CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {2206  // The array cookie is a size_t; pad that up to the element alignment.2207  // The cookie is actually right-justified in that space.2208  return std::max(2209      cgm.getSizeSize(),2210      cgm.getASTContext().getPreferredTypeAlignInChars(elementType));2211}2212 2213Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,2214                                                   Address newPtr,2215                                                   mlir::Value numElements,2216                                                   const CXXNewExpr *e,2217                                                   QualType elementType) {2218  assert(requiresArrayCookie(e));2219 2220  // TODO: When sanitizer support is implemented, we'll need to2221  // get the address space from `newPtr`.2222  assert(!cir::MissingFeatures::addressSpace());2223  assert(!cir::MissingFeatures::sanitizers());2224 2225  ASTContext &ctx = cgm.getASTContext();2226  CharUnits sizeSize = cgf.getSizeSize();2227  mlir::Location loc = cgf.getLoc(e->getSourceRange());2228 2229  // The size of the cookie.2230  CharUnits cookieSize =2231      std::max(sizeSize, ctx.getPreferredTypeAlignInChars(elementType));2232  assert(cookieSize == getArrayCookieSizeImpl(elementType));2233 2234  cir::PointerType u8PtrTy = cgf.getBuilder().getUInt8PtrTy();2235  mlir::Value baseBytePtr =2236      cgf.getBuilder().createPtrBitcast(newPtr.getPointer(), u8PtrTy);2237 2238  // Compute an offset to the cookie.2239  CharUnits cookieOffset = cookieSize - sizeSize;2240  mlir::Value cookiePtrValue = baseBytePtr;2241  if (!cookieOffset.isZero()) {2242    mlir::Value offsetOp = cgf.getBuilder().getSignedInt(2243        loc, cookieOffset.getQuantity(), /*width=*/32);2244    cookiePtrValue =2245        cgf.getBuilder().createPtrStride(loc, cookiePtrValue, offsetOp);2246  }2247 2248  CharUnits baseAlignment = newPtr.getAlignment();2249  CharUnits cookiePtrAlignment = baseAlignment.alignmentAtOffset(cookieOffset);2250  Address cookiePtr(cookiePtrValue, u8PtrTy, cookiePtrAlignment);2251 2252  // Write the number of elements into the appropriate slot.2253  Address numElementsPtr =2254      cookiePtr.withElementType(cgf.getBuilder(), cgf.sizeTy);2255  cgf.getBuilder().createStore(loc, numElements, numElementsPtr);2256 2257  // Finally, compute a pointer to the actual data buffer by skipping2258  // over the cookie completely.2259  mlir::Value dataOffset =2260      cgf.getBuilder().getSignedInt(loc, cookieSize.getQuantity(),2261                                    /*width=*/32);2262  mlir::Value dataPtr =2263      cgf.getBuilder().createPtrStride(loc, baseBytePtr, dataOffset);2264  mlir::Value finalPtr =2265      cgf.getBuilder().createPtrBitcast(dataPtr, newPtr.getElementType());2266  CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);2267  return Address(finalPtr, newPtr.getElementType(), finalAlignment);2268}2269