brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.6 KiB · 81fd8ee Raw
1034 lines · cpp
1//===--- CIRGenExprCXX.cpp - Emit CIR Code for C++ expressions ------------===//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 contains code dealing with code generation of C++ expressions10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenCXXABI.h"14#include "CIRGenConstantEmitter.h"15#include "CIRGenFunction.h"16 17#include "clang/AST/DeclCXX.h"18#include "clang/AST/ExprCXX.h"19#include "clang/Basic/OperatorKinds.h"20#include "clang/CIR/MissingFeatures.h"21 22using namespace clang;23using namespace clang::CIRGen;24 25namespace {26struct MemberCallInfo {27  RequiredArgs reqArgs;28  // Number of prefix arguments for the call. Ignores the `this` pointer.29  unsigned prefixSize;30};31} // namespace32 33static MemberCallInfo commonBuildCXXMemberOrOperatorCall(34    CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,35    mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,36    CallArgList &args, CallArgList *rtlArgs) {37  assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||38         isa<CXXOperatorCallExpr>(ce));39  assert(md->isInstance() &&40         "Trying to emit a member or operator call expr on a static method!");41 42  // Push the this ptr.43  const CXXRecordDecl *rd =44      cgf.cgm.getCXXABI().getThisArgumentTypeForMethod(md);45  args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));46 47  // If there is an implicit parameter (e.g. VTT), emit it.48  if (implicitParam) {49    args.add(RValue::get(implicitParam), implicitParamTy);50  }51 52  const auto *fpt = md->getType()->castAs<FunctionProtoType>();53  RequiredArgs required =54      RequiredArgs::getFromProtoWithExtraSlots(fpt, args.size());55  unsigned prefixSize = args.size() - 1;56 57  // Add the rest of the call args58  if (rtlArgs) {59    // Special case: if the caller emitted the arguments right-to-left already60    // (prior to emitting the *this argument), we're done. This happens for61    // assignment operators.62    args.addFrom(*rtlArgs);63  } else if (ce) {64    // Special case: skip first argument of CXXOperatorCall (it is "this").65    unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;66    cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),67                     ce->getDirectCallee());68  } else {69    assert(70        fpt->getNumParams() == 0 &&71        "No CallExpr specified for function with non-zero number of arguments");72  }73 74  //  return {required, prefixSize};75  return {required, prefixSize};76}77 78RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(79    const CallExpr *ce, const CXXMethodDecl *md, ReturnValueSlot returnValue,80    bool hasQualifier, NestedNameSpecifier qualifier, bool isArrow,81    const Expr *base) {82  assert(isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));83 84  // Compute the object pointer.85  bool canUseVirtualCall = md->isVirtual() && !hasQualifier;86  const CXXMethodDecl *devirtualizedMethod = nullptr;87  assert(!cir::MissingFeatures::devirtualizeMemberFunction());88 89  // Note on trivial assignment90  // --------------------------91  // Classic codegen avoids generating the trivial copy/move assignment operator92  // when it isn't necessary, choosing instead to just produce IR with an93  // equivalent effect. We have chosen not to do that in CIR, instead emitting94  // trivial copy/move assignment operators and allowing later transformations95  // to optimize them away if appropriate.96 97  // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment98  // operator before the LHS.99  CallArgList rtlArgStorage;100  CallArgList *rtlArgs = nullptr;101  if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {102    if (oce->isAssignmentOp()) {103      rtlArgs = &rtlArgStorage;104      emitCallArgs(*rtlArgs, md->getType()->castAs<FunctionProtoType>(),105                   drop_begin(ce->arguments(), 1), ce->getDirectCallee(),106                   /*ParamsToSkip*/ 0);107    }108  }109 110  LValue thisPtr;111  if (isArrow) {112    LValueBaseInfo baseInfo;113    assert(!cir::MissingFeatures::opTBAA());114    Address thisValue = emitPointerWithAlignment(base, &baseInfo);115    thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);116  } else {117    thisPtr = emitLValue(base);118  }119 120  if (isa<CXXConstructorDecl>(md)) {121    cgm.errorNYI(ce->getSourceRange(),122                 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");123    return RValue::get(nullptr);124  }125 126  if ((md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion())) &&127      isa<CXXDestructorDecl>(md))128    return RValue::get(nullptr);129 130  // Compute the function type we're calling131  const CXXMethodDecl *calleeDecl =132      devirtualizedMethod ? devirtualizedMethod : md;133  const CIRGenFunctionInfo *fInfo = nullptr;134  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl))135    fInfo = &cgm.getTypes().arrangeCXXStructorDeclaration(136        GlobalDecl(dtor, Dtor_Complete));137  else138    fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);139 140  cir::FuncType ty = cgm.getTypes().getFunctionType(*fInfo);141 142  assert(!cir::MissingFeatures::sanitizers());143  assert(!cir::MissingFeatures::emitTypeCheck());144 145  // C++ [class.virtual]p12:146  //   Explicit qualification with the scope operator (5.1) suppresses the147  //   virtual call mechanism.148  //149  // We also don't emit a virtual call if the base expression has a record type150  // because then we know what the type is.151  bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;152 153  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {154    assert(ce->arg_begin() == ce->arg_end() &&155           "Destructor shouldn't have explicit parameters");156    assert(returnValue.isNull() && "Destructor shouldn't have return value");157    if (useVirtualCall) {158      cgm.getCXXABI().emitVirtualDestructorCall(*this, dtor, Dtor_Complete,159                                                thisPtr.getAddress(),160                                                cast<CXXMemberCallExpr>(ce));161    } else {162      GlobalDecl globalDecl(dtor, Dtor_Complete);163      CIRGenCallee callee;164      assert(!cir::MissingFeatures::appleKext());165      if (!devirtualizedMethod) {166        callee = CIRGenCallee::forDirect(167            cgm.getAddrOfCXXStructor(globalDecl, fInfo, ty), globalDecl);168      } else {169        cgm.errorNYI(ce->getSourceRange(), "devirtualized destructor call");170        return RValue::get(nullptr);171      }172 173      QualType thisTy =174          isArrow ? base->getType()->getPointeeType() : base->getType();175      // CIRGen does not pass CallOrInvoke here (different from OG LLVM codegen)176      // because in practice it always null even in OG.177      emitCXXDestructorCall(globalDecl, callee, thisPtr.getPointer(), thisTy,178                            /*implicitParam=*/nullptr,179                            /*implicitParamTy=*/QualType(), ce);180    }181    return RValue::get(nullptr);182  }183 184  CIRGenCallee callee;185  if (useVirtualCall) {186    callee = CIRGenCallee::forVirtual(ce, md, thisPtr.getAddress(), ty);187  } else {188    assert(!cir::MissingFeatures::sanitizers());189    if (getLangOpts().AppleKext) {190      cgm.errorNYI(ce->getSourceRange(),191                   "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");192      return RValue::get(nullptr);193    }194 195    callee = CIRGenCallee::forDirect(cgm.getAddrOfFunction(calleeDecl, ty),196                                     GlobalDecl(calleeDecl));197  }198 199  if (md->isVirtual()) {200    Address newThisAddr =201        cgm.getCXXABI().adjustThisArgumentForVirtualFunctionCall(202            *this, calleeDecl, thisPtr.getAddress(), useVirtualCall);203    thisPtr.setAddress(newThisAddr);204  }205 206  return emitCXXMemberOrOperatorCall(207      calleeDecl, callee, returnValue, thisPtr.getPointer(),208      /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);209}210 211RValue212CIRGenFunction::emitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *e,213                                              const CXXMethodDecl *md,214                                              ReturnValueSlot returnValue) {215  assert(md->isInstance() &&216         "Trying to emit a member call expr on a static method!");217  return emitCXXMemberOrOperatorMemberCallExpr(218      e, md, returnValue, /*HasQualifier=*/false, /*Qualifier=*/std::nullopt,219      /*IsArrow=*/false, e->getArg(0));220}221 222RValue CIRGenFunction::emitCXXMemberOrOperatorCall(223    const CXXMethodDecl *md, const CIRGenCallee &callee,224    ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value implicitParam,225    QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {226  const auto *fpt = md->getType()->castAs<FunctionProtoType>();227  CallArgList args;228  MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(229      *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);230  auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(231      args, fpt, callInfo.reqArgs, callInfo.prefixSize);232  assert((ce || currSrcLoc) && "expected source location");233  mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;234  assert(!cir::MissingFeatures::opCallMustTail());235  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);236}237 238static void emitNullBaseClassInitialization(CIRGenFunction &cgf,239                                            Address destPtr,240                                            const CXXRecordDecl *base) {241  if (base->isEmpty())242    return;243 244  const ASTRecordLayout &layout = cgf.getContext().getASTRecordLayout(base);245  CharUnits nvSize = layout.getNonVirtualSize();246 247  // We cannot simply zero-initialize the entire base sub-object if vbptrs are248  // present, they are initialized by the most derived class before calling the249  // constructor.250  SmallVector<std::pair<CharUnits, CharUnits>, 1> stores;251  stores.emplace_back(CharUnits::Zero(), nvSize);252 253  // Each store is split by the existence of a vbptr.254  // TODO(cir): This only needs handling for the MS CXXABI.255  assert(!cir::MissingFeatures::msabi());256 257  // If the type contains a pointer to data member we can't memset it to zero.258  // Instead, create a null constant and copy it to the destination.259  // TODO: there are other patterns besides zero that we can usefully memset,260  // like -1, which happens to be the pattern used by member-pointers.261  // TODO: isZeroInitializable can be over-conservative in the case where a262  // virtual base contains a member pointer.263  mlir::TypedAttr nullConstantForBase = cgf.cgm.emitNullConstantForBase(base);264  if (!cgf.getBuilder().isNullValue(nullConstantForBase)) {265    cgf.cgm.errorNYI(266        base->getSourceRange(),267        "emitNullBaseClassInitialization: base constant is not null");268  } else {269    // Otherwise, just memset the whole thing to zero.  This is legal270    // because in LLVM, all default initializers (other than the ones we just271    // handled above) are guaranteed to have a bit pattern of all zeros.272    // TODO(cir): When the MS CXXABI is supported, we will need to iterate over273    // `stores` and create a separate memset for each one. For now, we know that274    // there will only be one store and it will begin at offset zero, so that275    // simplifies this code considerably.276    assert(stores.size() == 1 && "Expected only one store");277    assert(stores[0].first == CharUnits::Zero() &&278           "Expected store to begin at offset zero");279    CIRGenBuilderTy builder = cgf.getBuilder();280    mlir::Location loc = cgf.getLoc(base->getBeginLoc());281    builder.createStore(loc, builder.getConstant(loc, nullConstantForBase),282                        destPtr);283  }284}285 286void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,287                                          AggValueSlot dest) {288  assert(!dest.isIgnored() && "Must have a destination!");289  const CXXConstructorDecl *cd = e->getConstructor();290 291  // If we require zero initialization before (or instead of) calling the292  // constructor, as can be the case with a non-user-provided default293  // constructor, emit the zero initialization now, unless destination is294  // already zeroed.295  if (e->requiresZeroInitialization() && !dest.isZeroed()) {296    switch (e->getConstructionKind()) {297    case CXXConstructionKind::Delegating:298    case CXXConstructionKind::Complete:299      emitNullInitialization(getLoc(e->getSourceRange()), dest.getAddress(),300                             e->getType());301      break;302    case CXXConstructionKind::VirtualBase:303    case CXXConstructionKind::NonVirtualBase:304      emitNullBaseClassInitialization(*this, dest.getAddress(),305                                      cd->getParent());306      break;307    }308  }309 310  // If this is a call to a trivial default constructor, do nothing.311  if (cd->isTrivial() && cd->isDefaultConstructor())312    return;313 314  // Elide the constructor if we're constructing from a temporary315  if (getLangOpts().ElideConstructors && e->isElidable()) {316    // FIXME: This only handles the simplest case, where the source object is317    //        passed directly as the first argument to the constructor. This318    //        should also handle stepping through implicit casts and conversion319    //        sequences which involve two steps, with a conversion operator320    //        follwed by a converting constructor.321    const Expr *srcObj = e->getArg(0);322    assert(srcObj->isTemporaryObject(getContext(), cd->getParent()));323    assert(324        getContext().hasSameUnqualifiedType(e->getType(), srcObj->getType()));325    emitAggExpr(srcObj, dest);326    return;327  }328 329  if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {330    assert(!cir::MissingFeatures::sanitizers());331    emitCXXAggrConstructorCall(cd, arrayType, dest.getAddress(), e, false);332  } else {333 334    clang::CXXCtorType type = Ctor_Complete;335    bool forVirtualBase = false;336    bool delegating = false;337 338    switch (e->getConstructionKind()) {339    case CXXConstructionKind::Complete:340      type = Ctor_Complete;341      break;342    case CXXConstructionKind::Delegating:343      // We should be emitting a constructor; GlobalDecl will assert this344      type = curGD.getCtorType();345      delegating = true;346      break;347    case CXXConstructionKind::VirtualBase:348      forVirtualBase = true;349      [[fallthrough]];350    case CXXConstructionKind::NonVirtualBase:351      type = Ctor_Base;352      break;353    }354 355    emitCXXConstructorCall(cd, type, forVirtualBase, delegating, dest, e);356  }357}358 359static CharUnits calculateCookiePadding(CIRGenFunction &cgf,360                                        const CXXNewExpr *e) {361  if (!e->isArray())362    return CharUnits::Zero();363 364  // No cookie is required if the operator new[] being used is the365  // reserved placement operator new[].366  if (e->getOperatorNew()->isReservedGlobalPlacementOperator())367    return CharUnits::Zero();368 369  return cgf.cgm.getCXXABI().getArrayCookieSize(e);370}371 372static mlir::Value emitCXXNewAllocSize(CIRGenFunction &cgf, const CXXNewExpr *e,373                                       unsigned minElements,374                                       mlir::Value &numElements,375                                       mlir::Value &sizeWithoutCookie) {376  QualType type = e->getAllocatedType();377  mlir::Location loc = cgf.getLoc(e->getSourceRange());378 379  if (!e->isArray()) {380    CharUnits typeSize = cgf.getContext().getTypeSizeInChars(type);381    sizeWithoutCookie = cgf.getBuilder().getConstant(382        loc, cir::IntAttr::get(cgf.sizeTy, typeSize.getQuantity()));383    return sizeWithoutCookie;384  }385 386  // The width of size_t.387  unsigned sizeWidth = cgf.cgm.getDataLayout().getTypeSizeInBits(cgf.sizeTy);388 389  // The number of elements can be have an arbitrary integer type;390  // essentially, we need to multiply it by a constant factor, add a391  // cookie size, and verify that the result is representable as a392  // size_t.  That's just a gloss, though, and it's wrong in one393  // important way: if the count is negative, it's an error even if394  // the cookie size would bring the total size >= 0.395  //396  // If the array size is constant, Sema will have prevented negative397  // values and size overflow.398 399  // Compute the constant factor.400  llvm::APInt arraySizeMultiplier(sizeWidth, 1);401  while (const ConstantArrayType *cat =402             cgf.getContext().getAsConstantArrayType(type)) {403    type = cat->getElementType();404    arraySizeMultiplier *= cat->getSize();405  }406 407  CharUnits typeSize = cgf.getContext().getTypeSizeInChars(type);408  llvm::APInt typeSizeMultiplier(sizeWidth, typeSize.getQuantity());409  typeSizeMultiplier *= arraySizeMultiplier;410 411  // Figure out the cookie size.412  llvm::APInt cookieSize(sizeWidth,413                         calculateCookiePadding(cgf, e).getQuantity());414 415  // This will be a size_t.416  mlir::Value size;417 418  // Emit the array size expression.419  // We multiply the size of all dimensions for NumElements.420  // e.g for 'int[2][3]', ElemType is 'int' and NumElements is 6.421  const Expr *arraySize = *e->getArraySize();422  mlir::Attribute constNumElements =423      ConstantEmitter(cgf.cgm, &cgf)424          .emitAbstract(arraySize, arraySize->getType());425  if (constNumElements) {426    // Get an APInt from the constant427    const llvm::APInt &count =428        mlir::cast<cir::IntAttr>(constNumElements).getValue();429 430    [[maybe_unused]] unsigned numElementsWidth = count.getBitWidth();431    bool hasAnyOverflow = false;432 433    // The equivalent code in CodeGen/CGExprCXX.cpp handles these cases as434    // overflow, but that should never happen. The size argument is implicitly435    // cast to a size_t, so it can never be negative and numElementsWidth will436    // always equal sizeWidth.437    assert(!count.isNegative() && "Expected non-negative array size");438    assert(numElementsWidth == sizeWidth &&439           "Expected a size_t array size constant");440 441    // Okay, compute a count at the right width.442    llvm::APInt adjustedCount = count.zextOrTrunc(sizeWidth);443 444    // Scale numElements by that.  This might overflow, but we don't445    // care because it only overflows if allocationSize does too, and446    // if that overflows then we shouldn't use this.447    // This emits a constant that may not be used, but we can't tell here448    // whether it will be needed or not.449    numElements =450        cgf.getBuilder().getConstInt(loc, adjustedCount * arraySizeMultiplier);451 452    // Compute the size before cookie, and track whether it overflowed.453    bool overflow;454    llvm::APInt allocationSize =455        adjustedCount.umul_ov(typeSizeMultiplier, overflow);456 457    // Sema prevents us from hitting this case458    assert(!overflow && "Overflow in array allocation size");459 460    // Add in the cookie, and check whether it's overflowed.461    if (cookieSize != 0) {462      // Save the current size without a cookie.  This shouldn't be463      // used if there was overflow464      sizeWithoutCookie = cgf.getBuilder().getConstInt(465          loc, allocationSize.zextOrTrunc(sizeWidth));466 467      allocationSize = allocationSize.uadd_ov(cookieSize, overflow);468      hasAnyOverflow |= overflow;469    }470 471    // On overflow, produce a -1 so operator new will fail472    if (hasAnyOverflow) {473      size =474          cgf.getBuilder().getConstInt(loc, llvm::APInt::getAllOnes(sizeWidth));475    } else {476      size = cgf.getBuilder().getConstInt(loc, allocationSize);477    }478  } else {479    // TODO: Handle the variable size case480    cgf.cgm.errorNYI(e->getSourceRange(),481                     "emitCXXNewAllocSize: variable array size");482  }483 484  if (cookieSize == 0)485    sizeWithoutCookie = size;486  else487    assert(sizeWithoutCookie && "didn't set sizeWithoutCookie?");488 489  return size;490}491 492static void storeAnyExprIntoOneUnit(CIRGenFunction &cgf, const Expr *init,493                                    QualType allocType, Address newPtr,494                                    AggValueSlot::Overlap_t mayOverlap) {495  // FIXME: Refactor with emitExprAsInit.496  switch (cgf.getEvaluationKind(allocType)) {497  case cir::TEK_Scalar:498    cgf.emitScalarInit(init, cgf.getLoc(init->getSourceRange()),499                       cgf.makeAddrLValue(newPtr, allocType), false);500    return;501  case cir::TEK_Complex:502    cgf.emitComplexExprIntoLValue(init, cgf.makeAddrLValue(newPtr, allocType),503                                  /*isInit*/ true);504    return;505  case cir::TEK_Aggregate: {506    assert(!cir::MissingFeatures::aggValueSlotGC());507    assert(!cir::MissingFeatures::sanitizers());508    AggValueSlot slot = AggValueSlot::forAddr(509        newPtr, allocType.getQualifiers(), AggValueSlot::IsDestructed,510        AggValueSlot::IsNotAliased, mayOverlap, AggValueSlot::IsNotZeroed);511    cgf.emitAggExpr(init, slot);512    return;513  }514  }515  llvm_unreachable("bad evaluation kind");516}517 518void CIRGenFunction::emitNewArrayInitializer(519    const CXXNewExpr *e, QualType elementType, mlir::Type elementTy,520    Address beginPtr, mlir::Value numElements,521    mlir::Value allocSizeWithoutCookie) {522  // If we have a type with trivial initialization and no initializer,523  // there's nothing to do.524  if (!e->hasInitializer())525    return;526 527  unsigned initListElements = 0;528 529  const Expr *init = e->getInitializer();530  const InitListExpr *ile = dyn_cast<InitListExpr>(init);531  if (ile) {532    cgm.errorNYI(ile->getSourceRange(), "emitNewArrayInitializer: init list");533    return;534  }535 536  // If all elements have already been initialized, skip any further537  // initialization.538  auto constOp = mlir::dyn_cast<cir::ConstantOp>(numElements.getDefiningOp());539  if (constOp) {540    auto constIntAttr = mlir::dyn_cast<cir::IntAttr>(constOp.getValue());541    // Just skip out if the constant count is zero.542    if (constIntAttr && constIntAttr.getUInt() <= initListElements)543      return;544  }545 546  assert(init && "have trailing elements to initialize but no initializer");547 548  // If this is a constructor call, try to optimize it out, and failing that549  // emit a single loop to initialize all remaining elements.550  if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) {551    CXXConstructorDecl *ctor = cce->getConstructor();552    if (ctor->isTrivial()) {553      // If new expression did not specify value-initialization, then there554      // is no initialization.555      if (!cce->requiresZeroInitialization())556        return;557 558      cgm.errorNYI(cce->getSourceRange(),559                   "emitNewArrayInitializer: trivial ctor zero-init");560      return;561    }562 563    cgm.errorNYI(cce->getSourceRange(),564                 "emitNewArrayInitializer: ctor initializer");565    return;566  }567 568  cgm.errorNYI(init->getSourceRange(),569               "emitNewArrayInitializer: unsupported initializer");570  return;571}572 573static void emitNewInitializer(CIRGenFunction &cgf, const CXXNewExpr *e,574                               QualType elementType, mlir::Type elementTy,575                               Address newPtr, mlir::Value numElements,576                               mlir::Value allocSizeWithoutCookie) {577  assert(!cir::MissingFeatures::generateDebugInfo());578  if (e->isArray()) {579    cgf.emitNewArrayInitializer(e, elementType, elementTy, newPtr, numElements,580                                allocSizeWithoutCookie);581  } else if (const Expr *init = e->getInitializer()) {582    storeAnyExprIntoOneUnit(cgf, init, e->getAllocatedType(), newPtr,583                            AggValueSlot::DoesNotOverlap);584  }585}586 587RValue CIRGenFunction::emitCXXDestructorCall(588    GlobalDecl dtor, const CIRGenCallee &callee, mlir::Value thisVal,589    QualType thisTy, mlir::Value implicitParam, QualType implicitParamTy,590    const CallExpr *ce) {591  const CXXMethodDecl *dtorDecl = cast<CXXMethodDecl>(dtor.getDecl());592 593  assert(!thisTy.isNull());594  assert(thisTy->getAsCXXRecordDecl() == dtorDecl->getParent() &&595         "Pointer/Object mixup");596 597  assert(!cir::MissingFeatures::addressSpace());598 599  CallArgList args;600  commonBuildCXXMemberOrOperatorCall(*this, dtorDecl, thisVal, implicitParam,601                                     implicitParamTy, ce, args, nullptr);602  assert((ce || dtor.getDecl()) && "expected source location provider");603  assert(!cir::MissingFeatures::opCallMustTail());604  return emitCall(cgm.getTypes().arrangeCXXStructorDeclaration(dtor), callee,605                  ReturnValueSlot(), args, nullptr,606                  ce ? getLoc(ce->getExprLoc())607                     : getLoc(dtor.getDecl()->getSourceRange()));608}609 610RValue CIRGenFunction::emitCXXPseudoDestructorExpr(611    const CXXPseudoDestructorExpr *expr) {612  QualType destroyedType = expr->getDestroyedType();613  if (destroyedType.hasStrongOrWeakObjCLifetime()) {614    assert(!cir::MissingFeatures::objCLifetime());615    cgm.errorNYI(expr->getExprLoc(),616                 "emitCXXPseudoDestructorExpr: Objective-C lifetime is NYI");617  } else {618    // C++ [expr.pseudo]p1:619    //   The result shall only be used as the operand for the function call620    //   operator (), and the result of such a call has type void. The only621    //   effect is the evaluation of the postfix-expression before the dot or622    //   arrow.623    emitIgnoredExpr(expr->getBase());624  }625 626  return RValue::get(nullptr);627}628 629/// Emit a call to an operator new or operator delete function, as implicitly630/// created by new-expressions and delete-expressions.631static RValue emitNewDeleteCall(CIRGenFunction &cgf,632                                const FunctionDecl *calleeDecl,633                                const FunctionProtoType *calleeType,634                                const CallArgList &args) {635  cir::CIRCallOpInterface callOrTryCall;636  cir::FuncOp calleePtr = cgf.cgm.getAddrOfFunction(calleeDecl);637  CIRGenCallee callee =638      CIRGenCallee::forDirect(calleePtr, GlobalDecl(calleeDecl));639  RValue rv =640      cgf.emitCall(cgf.cgm.getTypes().arrangeFreeFunctionCall(args, calleeType),641                   callee, ReturnValueSlot(), args, &callOrTryCall);642 643  /// C++1y [expr.new]p10:644  ///   [In a new-expression,] an implementation is allowed to omit a call645  ///   to a replaceable global allocation function.646  ///647  /// We model such elidable calls with the 'builtin' attribute.648  assert(!cir::MissingFeatures::attributeBuiltin());649  return rv;650}651 652RValue CIRGenFunction::emitNewOrDeleteBuiltinCall(const FunctionProtoType *type,653                                                  const CallExpr *callExpr,654                                                  OverloadedOperatorKind op) {655  CallArgList args;656  emitCallArgs(args, type, callExpr->arguments());657  // Find the allocation or deallocation function that we're calling.658  ASTContext &astContext = getContext();659  assert(op == OO_New || op == OO_Delete);660  DeclarationName name = astContext.DeclarationNames.getCXXOperatorName(op);661 662  clang::DeclContextLookupResult lookupResult =663      astContext.getTranslationUnitDecl()->lookup(name);664  for (const auto *decl : lookupResult) {665    if (const auto *funcDecl = dyn_cast<FunctionDecl>(decl)) {666      if (astContext.hasSameType(funcDecl->getType(), QualType(type, 0))) {667        if (sanOpts.has(SanitizerKind::AllocToken)) {668          // TODO: Set !alloc_token metadata.669          assert(!cir::MissingFeatures::allocToken());670          cgm.errorNYI("Alloc token sanitizer not yet supported!");671        }672 673        // Emit the call to operator new/delete.674        return emitNewDeleteCall(*this, funcDecl, type, args);675      }676    }677  }678 679  llvm_unreachable("predeclared global operator new/delete is missing");680}681 682namespace {683/// Calls the given 'operator delete' on a single object.684struct CallObjectDelete final : EHScopeStack::Cleanup {685  mlir::Value ptr;686  const FunctionDecl *operatorDelete;687  QualType elementType;688 689  CallObjectDelete(mlir::Value ptr, const FunctionDecl *operatorDelete,690                   QualType elementType)691      : ptr(ptr), operatorDelete(operatorDelete), elementType(elementType) {}692 693  void emit(CIRGenFunction &cgf) override {694    cgf.emitDeleteCall(operatorDelete, ptr, elementType);695  }696};697} // namespace698 699/// Emit the code for deleting a single object.700static void emitObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,701                             Address ptr, QualType elementType) {702  // C++11 [expr.delete]p3:703  //   If the static type of the object to be deleted is different from its704  //   dynamic type, the static type shall be a base class of the dynamic type705  //   of the object to be deleted and the static type shall have a virtual706  //   destructor or the behavior is undefined.707  assert(!cir::MissingFeatures::emitTypeCheck());708 709  const FunctionDecl *operatorDelete = de->getOperatorDelete();710  assert(!operatorDelete->isDestroyingOperatorDelete());711 712  // Find the destructor for the type, if applicable.  If the713  // destructor is virtual, we'll just emit the vcall and return.714  const CXXDestructorDecl *dtor = nullptr;715  if (const auto *rd = elementType->getAsCXXRecordDecl()) {716    if (rd->hasDefinition() && !rd->hasTrivialDestructor()) {717      dtor = rd->getDestructor();718 719      if (dtor->isVirtual()) {720        assert(!cir::MissingFeatures::devirtualizeDestructor());721        cgf.cgm.getCXXABI().emitVirtualObjectDelete(cgf, de, ptr, elementType,722                                                    dtor);723        return;724      }725    }726  }727 728  // Make sure that we call delete even if the dtor throws.729  // This doesn't have to a conditional cleanup because we're going730  // to pop it off in a second.731  cgf.ehStack.pushCleanup<CallObjectDelete>(732      NormalAndEHCleanup, ptr.getPointer(), operatorDelete, elementType);733 734  if (dtor) {735    cgf.emitCXXDestructorCall(dtor, Dtor_Complete,736                              /*ForVirtualBase=*/false,737                              /*Delegating=*/false, ptr, elementType);738  } else if (elementType.getObjCLifetime()) {739    assert(!cir::MissingFeatures::objCLifetime());740    cgf.cgm.errorNYI(de->getSourceRange(), "emitObjectDelete: ObjCLifetime");741  }742 743  // In traditional LLVM codegen null checks are emitted to save a delete call.744  // In CIR we optimize for size by default, the null check should be added into745  // this function callers.746  assert(!cir::MissingFeatures::emitNullCheckForDeleteCalls());747 748  cgf.popCleanupBlock();749}750 751void CIRGenFunction::emitCXXDeleteExpr(const CXXDeleteExpr *e) {752  const Expr *arg = e->getArgument();753  Address ptr = emitPointerWithAlignment(arg);754 755  // Null check the pointer.756  //757  // We could avoid this null check if we can determine that the object758  // destruction is trivial and doesn't require an array cookie; we can759  // unconditionally perform the operator delete call in that case. For now, we760  // assume that deleted pointers are null rarely enough that it's better to761  // keep the branch. This might be worth revisiting for a -O0 code size win.762  //763  // CIR note: emit the code size friendly by default for now, such as mentioned764  // in `emitObjectDelete`.765  assert(!cir::MissingFeatures::emitNullCheckForDeleteCalls());766  QualType deleteTy = e->getDestroyedType();767 768  // A destroying operator delete overrides the entire operation of the769  // delete expression.770  if (e->getOperatorDelete()->isDestroyingOperatorDelete()) {771    cgm.errorNYI(e->getSourceRange(),772                 "emitCXXDeleteExpr: destroying operator delete");773    return;774  }775 776  // We might be deleting a pointer to array.777  deleteTy = getContext().getBaseElementType(deleteTy);778  ptr = ptr.withElementType(builder, convertTypeForMem(deleteTy));779 780  if (e->isArrayForm()) {781    assert(!cir::MissingFeatures::deleteArray());782    cgm.errorNYI(e->getSourceRange(), "emitCXXDeleteExpr: array delete");783    return;784  } else {785    emitObjectDelete(*this, e, ptr, deleteTy);786  }787}788 789mlir::Value CIRGenFunction::emitCXXNewExpr(const CXXNewExpr *e) {790  // The element type being allocated.791  QualType allocType = getContext().getBaseElementType(e->getAllocatedType());792 793  // 1. Build a call to the allocation function.794  FunctionDecl *allocator = e->getOperatorNew();795 796  // If there is a brace-initializer, cannot allocate fewer elements than inits.797  unsigned minElements = 0;798 799  mlir::Value numElements = nullptr;800  mlir::Value allocSizeWithoutCookie = nullptr;801  mlir::Value allocSize = emitCXXNewAllocSize(802      *this, e, minElements, numElements, allocSizeWithoutCookie);803  CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);804 805  // Emit the allocation call.806  Address allocation = Address::invalid();807  CallArgList allocatorArgs;808  if (allocator->isReservedGlobalPlacementOperator()) {809    // If the allocator is a global placement operator, just810    // "inline" it directly.811    assert(e->getNumPlacementArgs() == 1);812    const Expr *arg = *e->placement_arguments().begin();813 814    LValueBaseInfo baseInfo;815    allocation = emitPointerWithAlignment(arg, &baseInfo);816 817    // The pointer expression will, in many cases, be an opaque void*.818    // In these cases, discard the computed alignment and use the819    // formal alignment of the allocated type.820    if (baseInfo.getAlignmentSource() != AlignmentSource::Decl)821      allocation = allocation.withAlignment(allocAlign);822 823    // Set up allocatorArgs for the call to operator delete if it's not824    // the reserved global operator.825    if (e->getOperatorDelete() &&826        !e->getOperatorDelete()->isReservedGlobalPlacementOperator()) {827      cgm.errorNYI(e->getSourceRange(),828                   "emitCXXNewExpr: reserved placement new with delete");829    }830  } else {831    const FunctionProtoType *allocatorType =832        allocator->getType()->castAs<FunctionProtoType>();833    unsigned paramsToSkip = 0;834 835    // The allocation size is the first argument.836    QualType sizeType = getContext().getSizeType();837    allocatorArgs.add(RValue::get(allocSize), sizeType);838    ++paramsToSkip;839 840    if (allocSize != allocSizeWithoutCookie) {841      CharUnits cookieAlign = getSizeAlign(); // FIXME: Ask the ABI.842      allocAlign = std::max(allocAlign, cookieAlign);843    }844 845    // The allocation alignment may be passed as the second argument.846    if (e->passAlignment()) {847      cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: pass alignment");848    }849 850    // FIXME: Why do we not pass a CalleeDecl here?851    emitCallArgs(allocatorArgs, allocatorType, e->placement_arguments(),852                 AbstractCallee(), paramsToSkip);853    RValue rv =854        emitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);855 856    // Set !heapallocsite metadata on the call to operator new.857    assert(!cir::MissingFeatures::generateDebugInfo());858 859    // If this was a call to a global replaceable allocation function that does860    // not take an alignment argument, the allocator is known to produce storage861    // that's suitably aligned for any object that fits, up to a known862    // threshold. Otherwise assume it's suitably aligned for the allocated type.863    CharUnits allocationAlign = allocAlign;864    if (!e->passAlignment() &&865        allocator->isReplaceableGlobalAllocationFunction()) {866      const TargetInfo &target = cgm.getASTContext().getTargetInfo();867      unsigned allocatorAlign = llvm::bit_floor(std::min<uint64_t>(868          target.getNewAlign(), getContext().getTypeSize(allocType)));869      allocationAlign = std::max(870          allocationAlign, getContext().toCharUnitsFromBits(allocatorAlign));871    }872 873    mlir::Value allocPtr = rv.getValue();874    allocation = Address(875        allocPtr, mlir::cast<cir::PointerType>(allocPtr.getType()).getPointee(),876        allocationAlign);877  }878 879  // Emit a null check on the allocation result if the allocation880  // function is allowed to return null (because it has a non-throwing881  // exception spec or is the reserved placement new) and we have an882  // interesting initializer will be running sanitizers on the initialization.883  bool nullCheck = e->shouldNullCheckAllocation() &&884                   (!allocType.isPODType(getContext()) || e->hasInitializer());885  assert(!cir::MissingFeatures::exprNewNullCheck());886  if (nullCheck)887    cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: null check");888 889  // If there's an operator delete, enter a cleanup to call it if an890  // exception is thrown.891  if (e->getOperatorDelete() &&892      !e->getOperatorDelete()->isReservedGlobalPlacementOperator())893    cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: operator delete");894 895  if (allocSize != allocSizeWithoutCookie) {896    assert(e->isArray());897    allocation = cgm.getCXXABI().initializeArrayCookie(898        *this, allocation, numElements, e, allocType);899  }900 901  mlir::Type elementTy;902  if (e->isArray()) {903    // For array new, use the allocated type to handle multidimensional arrays904    // correctly905    elementTy = convertTypeForMem(e->getAllocatedType());906  } else {907    elementTy = convertTypeForMem(allocType);908  }909  Address result = builder.createElementBitCast(getLoc(e->getSourceRange()),910                                                allocation, elementTy);911 912  // Passing pointer through launder.invariant.group to avoid propagation of913  // vptrs information which may be included in previous type.914  // To not break LTO with different optimizations levels, we do it regardless915  // of optimization level.916  if (cgm.getCodeGenOpts().StrictVTablePointers &&917      allocator->isReservedGlobalPlacementOperator())918    cgm.errorNYI(e->getSourceRange(), "emitCXXNewExpr: strict vtable pointers");919 920  assert(!cir::MissingFeatures::sanitizers());921 922  emitNewInitializer(*this, e, allocType, elementTy, result, numElements,923                     allocSizeWithoutCookie);924  return result.getPointer();925}926 927void CIRGenFunction::emitDeleteCall(const FunctionDecl *deleteFD,928                                    mlir::Value ptr, QualType deleteTy) {929  assert(!cir::MissingFeatures::deleteArray());930 931  const auto *deleteFTy = deleteFD->getType()->castAs<FunctionProtoType>();932  CallArgList deleteArgs;933 934  UsualDeleteParams params = deleteFD->getUsualDeleteParams();935  auto paramTypeIt = deleteFTy->param_type_begin();936 937  // Pass std::type_identity tag if present938  if (isTypeAwareAllocation(params.TypeAwareDelete))939    cgm.errorNYI(deleteFD->getSourceRange(),940                 "emitDeleteCall: type aware delete");941 942  // Pass the pointer itself.943  QualType argTy = *paramTypeIt++;944  mlir::Value deletePtr =945      builder.createBitcast(ptr.getLoc(), ptr, convertType(argTy));946  deleteArgs.add(RValue::get(deletePtr), argTy);947 948  // Pass the std::destroying_delete tag if present.949  if (params.DestroyingDelete)950    cgm.errorNYI(deleteFD->getSourceRange(),951                 "emitDeleteCall: destroying delete");952 953  // Pass the size if the delete function has a size_t parameter.954  if (params.Size) {955    QualType sizeType = *paramTypeIt++;956    CharUnits deleteTypeSize = getContext().getTypeSizeInChars(deleteTy);957    assert(mlir::isa<cir::IntType>(convertType(sizeType)) &&958           "expected cir::IntType");959    cir::ConstantOp size = builder.getConstInt(960        *currSrcLoc, convertType(sizeType), deleteTypeSize.getQuantity());961 962    deleteArgs.add(RValue::get(size), sizeType);963  }964 965  // Pass the alignment if the delete function has an align_val_t parameter.966  if (isAlignedAllocation(params.Alignment))967    cgm.errorNYI(deleteFD->getSourceRange(),968                 "emitDeleteCall: aligned allocation");969 970  assert(paramTypeIt == deleteFTy->param_type_end() &&971         "unknown parameter to usual delete function");972 973  // Emit the call to delete.974  emitNewDeleteCall(*this, deleteFD, deleteFTy, deleteArgs);975}976 977static mlir::Value emitDynamicCastToNull(CIRGenFunction &cgf,978                                         mlir::Location loc, QualType destTy) {979  mlir::Type destCIRTy = cgf.convertType(destTy);980  assert(mlir::isa<cir::PointerType>(destCIRTy) &&981         "result of dynamic_cast should be a ptr");982 983  if (!destTy->isPointerType()) {984    mlir::Region *currentRegion = cgf.getBuilder().getBlock()->getParent();985    /// C++ [expr.dynamic.cast]p9:986    ///   A failed cast to reference type throws std::bad_cast987    cgf.cgm.getCXXABI().emitBadCastCall(cgf, loc);988 989    // The call to bad_cast will terminate the current block. Create a new block990    // to hold any follow up code.991    cgf.getBuilder().createBlock(currentRegion, currentRegion->end());992  }993 994  return cgf.getBuilder().getNullPtr(destCIRTy, loc);995}996 997mlir::Value CIRGenFunction::emitDynamicCast(Address thisAddr,998                                            const CXXDynamicCastExpr *dce) {999  mlir::Location loc = getLoc(dce->getSourceRange());1000 1001  cgm.emitExplicitCastExprType(dce, this);1002  QualType destTy = dce->getTypeAsWritten();1003  QualType srcTy = dce->getSubExpr()->getType();1004 1005  // C++ [expr.dynamic.cast]p7:1006  //   If T is "pointer to cv void," then the result is a pointer to the most1007  //   derived object pointed to by v.1008  bool isDynCastToVoid = destTy->isVoidPointerType();1009  bool isRefCast = destTy->isReferenceType();1010 1011  QualType srcRecordTy;1012  QualType destRecordTy;1013  if (isDynCastToVoid) {1014    srcRecordTy = srcTy->getPointeeType();1015    // No destRecordTy.1016  } else if (const PointerType *destPTy = destTy->getAs<PointerType>()) {1017    srcRecordTy = srcTy->castAs<PointerType>()->getPointeeType();1018    destRecordTy = destPTy->getPointeeType();1019  } else {1020    srcRecordTy = srcTy;1021    destRecordTy = destTy->castAs<ReferenceType>()->getPointeeType();1022  }1023 1024  assert(srcRecordTy->isRecordType() && "source type must be a record type!");1025  assert(!cir::MissingFeatures::emitTypeCheck());1026 1027  if (dce->isAlwaysNull())1028    return emitDynamicCastToNull(*this, loc, destTy);1029 1030  auto destCirTy = mlir::cast<cir::PointerType>(convertType(destTy));1031  return cgm.getCXXABI().emitDynamicCast(*this, loc, srcRecordTy, destRecordTy,1032                                         destCirTy, isRefCast, thisAddr);1033}1034