brintos

brintos / llvm-project-archived public Read only

0
0
Text · 39.0 KiB · 872fc8d Raw
1018 lines · cpp
1//===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate 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 to emit Aggregate Expr nodes as CIR code.10//11//===----------------------------------------------------------------------===//12 13#include "CIRGenBuilder.h"14#include "CIRGenFunction.h"15#include "CIRGenValue.h"16#include "clang/CIR/Dialect/IR/CIRAttrs.h"17 18#include "clang/AST/Expr.h"19#include "clang/AST/RecordLayout.h"20#include "clang/AST/StmtVisitor.h"21#include <cstdint>22 23using namespace clang;24using namespace clang::CIRGen;25 26namespace {27// FIXME(cir): This should be a common helper between CIRGen28// and traditional CodeGen29/// Is the value of the given expression possibly a reference to or30/// into a __block variable?31static bool isBlockVarRef(const Expr *e) {32  // Make sure we look through parens.33  e = e->IgnoreParens();34 35  // Check for a direct reference to a __block variable.36  if (const DeclRefExpr *dre = dyn_cast<DeclRefExpr>(e)) {37    const VarDecl *var = dyn_cast<VarDecl>(dre->getDecl());38    return (var && var->hasAttr<BlocksAttr>());39  }40 41  // More complicated stuff.42 43  // Binary operators.44  if (const BinaryOperator *op = dyn_cast<BinaryOperator>(e)) {45    // For an assignment or pointer-to-member operation, just care46    // about the LHS.47    if (op->isAssignmentOp() || op->isPtrMemOp())48      return isBlockVarRef(op->getLHS());49 50    // For a comma, just care about the RHS.51    if (op->getOpcode() == BO_Comma)52      return isBlockVarRef(op->getRHS());53 54    // FIXME: pointer arithmetic?55    return false;56 57    // Check both sides of a conditional operator.58  } else if (const AbstractConditionalOperator *op =59                 dyn_cast<AbstractConditionalOperator>(e)) {60    return isBlockVarRef(op->getTrueExpr()) ||61           isBlockVarRef(op->getFalseExpr());62 63    // OVEs are required to support BinaryConditionalOperators.64  } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(e)) {65    if (const Expr *src = op->getSourceExpr())66      return isBlockVarRef(src);67 68    // Casts are necessary to get things like (*(int*)&var) = foo().69    // We don't really care about the kind of cast here, except70    // we don't want to look through l2r casts, because it's okay71    // to get the *value* in a __block variable.72  } else if (const CastExpr *cast = dyn_cast<CastExpr>(e)) {73    if (cast->getCastKind() == CK_LValueToRValue)74      return false;75    return isBlockVarRef(cast->getSubExpr());76 77    // Handle unary operators.  Again, just aggressively look through78    // it, ignoring the operation.79  } else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) {80    return isBlockVarRef(uop->getSubExpr());81 82    // Look into the base of a field access.83  } else if (const MemberExpr *mem = dyn_cast<MemberExpr>(e)) {84    return isBlockVarRef(mem->getBase());85 86    // Look into the base of a subscript.87  } else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(e)) {88    return isBlockVarRef(sub->getBase());89  }90 91  return false;92}93 94class AggExprEmitter : public StmtVisitor<AggExprEmitter> {95 96  CIRGenFunction &cgf;97  AggValueSlot dest;98 99  // Calls `fn` with a valid return value slot, potentially creating a temporary100  // to do so. If a temporary is created, an appropriate copy into `Dest` will101  // be emitted, as will lifetime markers.102  //103  // The given function should take a ReturnValueSlot, and return an RValue that104  // points to said slot.105  void withReturnValueSlot(const Expr *e,106                           llvm::function_ref<RValue(ReturnValueSlot)> fn);107 108  AggValueSlot ensureSlot(mlir::Location loc, QualType t) {109    if (!dest.isIgnored())110      return dest;111    return cgf.createAggTemp(t, loc, "agg.tmp.ensured");112  }113 114  void ensureDest(mlir::Location loc, QualType ty) {115    if (!dest.isIgnored())116      return;117    dest = cgf.createAggTemp(ty, loc, "agg.tmp.ensured");118  }119 120public:121  AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)122      : cgf(cgf), dest(dest) {}123 124  /// Given an expression with aggregate type that represents a value lvalue,125  /// this method emits the address of the lvalue, then loads the result into126  /// DestPtr.127  void emitAggLoadOfLValue(const Expr *e);128 129  void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,130                     Expr *exprToVisit, ArrayRef<Expr *> args,131                     Expr *arrayFiller);132 133  /// Perform the final copy to DestPtr, if desired.134  void emitFinalDestCopy(QualType type, const LValue &src);135 136  void emitCopy(QualType type, const AggValueSlot &dest,137                const AggValueSlot &src);138 139  void emitInitializationToLValue(Expr *e, LValue lv);140 141  void emitNullInitializationToLValue(mlir::Location loc, LValue lv);142 143  void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }144 145  void VisitArraySubscriptExpr(ArraySubscriptExpr *e) {146    emitAggLoadOfLValue(e);147  }148 149  void VisitCallExpr(const CallExpr *e);150  void VisitStmtExpr(const StmtExpr *e) {151    CIRGenFunction::StmtExprEvaluation eval(cgf);152    Address retAlloca =153        cgf.createMemTemp(e->getType(), cgf.getLoc(e->getSourceRange()));154    (void)cgf.emitCompoundStmt(*e->getSubStmt(), &retAlloca, dest);155  }156 157  void VisitBinAssign(const BinaryOperator *e) {158    // For an assignment to work, the value on the right has159    // to be compatible with the value on the left.160    assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),161                                                   e->getRHS()->getType()) &&162           "Invalid assignment");163 164    if (isBlockVarRef(e->getLHS()) &&165        e->getRHS()->HasSideEffects(cgf.getContext())) {166      cgf.cgm.errorNYI(e->getSourceRange(),167                       "block var reference with side effects");168      return;169    }170 171    LValue lhs = cgf.emitLValue(e->getLHS());172 173    // If we have an atomic type, evaluate into the destination and then174    // do an atomic copy.175    assert(!cir::MissingFeatures::atomicTypes());176 177    // Codegen the RHS so that it stores directly into the LHS.178    assert(!cir::MissingFeatures::aggValueSlotGC());179    AggValueSlot lhsSlot = AggValueSlot::forLValue(180        lhs, AggValueSlot::IsDestructed, AggValueSlot::IsAliased,181        AggValueSlot::MayOverlap);182 183    // A non-volatile aggregate destination might have volatile member.184    if (!lhsSlot.isVolatile() && cgf.hasVolatileMember(e->getLHS()->getType()))185      lhsSlot.setVolatile(true);186 187    cgf.emitAggExpr(e->getRHS(), lhsSlot);188 189    // Copy into the destination if the assignment isn't ignored.190    emitFinalDestCopy(e->getType(), lhs);191 192    if (!dest.isIgnored() && !dest.isExternallyDestructed() &&193        e->getType().isDestructedType() == QualType::DK_nontrivial_c_struct)194      cgf.pushDestroy(QualType::DK_nontrivial_c_struct, dest.getAddress(),195                      e->getType());196  }197 198  void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }199 200  void VisitInitListExpr(InitListExpr *e);201  void VisitCXXConstructExpr(const CXXConstructExpr *e);202 203  void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,204                                       FieldDecl *initializedFieldInUnion,205                                       Expr *arrayFiller);206  void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) {207    CIRGenFunction::CXXDefaultInitExprScope Scope(cgf, die);208    Visit(die->getExpr());209  }210  void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *e) {211    // Ensure that we have a slot, but if we already do, remember212    // whether it was externally destructed.213    bool wasExternallyDestructed = dest.isExternallyDestructed();214    ensureDest(cgf.getLoc(e->getSourceRange()), e->getType());215 216    // We're going to push a destructor if there isn't already one.217    dest.setExternallyDestructed();218 219    Visit(e->getSubExpr());220 221    // Push that destructor we promised.222    if (!wasExternallyDestructed)223      cgf.emitCXXTemporary(e->getTemporary(), e->getType(), dest.getAddress());224  }225  void VisitLambdaExpr(LambdaExpr *e);226  void VisitExprWithCleanups(ExprWithCleanups *e);227 228  // Stubs -- These should be moved up when they are implemented.229  void VisitCastExpr(CastExpr *e) {230    switch (e->getCastKind()) {231    case CK_LValueToRValue:232      // If we're loading from a volatile type, force the destination233      // into existence.234      if (e->getSubExpr()->getType().isVolatileQualified())235        cgf.cgm.errorNYI(e->getSourceRange(),236                         "AggExprEmitter: volatile lvalue-to-rvalue cast");237      [[fallthrough]];238    case CK_NoOp:239    case CK_UserDefinedConversion:240    case CK_ConstructorConversion:241      assert(cgf.getContext().hasSameUnqualifiedType(e->getSubExpr()->getType(),242                                                     e->getType()) &&243             "Implicit cast types must be compatible");244      Visit(e->getSubExpr());245      break;246    default:247      cgf.cgm.errorNYI(e->getSourceRange(),248                       std::string("AggExprEmitter: VisitCastExpr: ") +249                           e->getCastKindName());250      break;251    }252  }253  void VisitStmt(Stmt *s) {254    cgf.cgm.errorNYI(s->getSourceRange(),255                     std::string("AggExprEmitter::VisitStmt: ") +256                         s->getStmtClassName());257  }258  void VisitParenExpr(ParenExpr *pe) { Visit(pe->getSubExpr()); }259  void VisitGenericSelectionExpr(GenericSelectionExpr *ge) {260    Visit(ge->getResultExpr());261  }262  void VisitCoawaitExpr(CoawaitExpr *e) {263    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoawaitExpr");264  }265  void VisitCoyieldExpr(CoyieldExpr *e) {266    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCoyieldExpr");267  }268  void VisitUnaryCoawait(UnaryOperator *e) {269    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitUnaryCoawait");270  }271  void VisitUnaryExtension(UnaryOperator *e) { Visit(e->getSubExpr()); }272  void VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e) {273    cgf.cgm.errorNYI(e->getSourceRange(),274                     "AggExprEmitter: VisitSubstNonTypeTemplateParmExpr");275  }276  void VisitConstantExpr(ConstantExpr *e) {277    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitConstantExpr");278  }279  void VisitMemberExpr(MemberExpr *e) { emitAggLoadOfLValue(e); }280  void VisitUnaryDeref(UnaryOperator *e) { emitAggLoadOfLValue(e); }281  void VisitStringLiteral(StringLiteral *e) { emitAggLoadOfLValue(e); }282  void VisitCompoundLiteralExpr(CompoundLiteralExpr *e);283 284  void VisitPredefinedExpr(const PredefinedExpr *e) {285    cgf.cgm.errorNYI(e->getSourceRange(),286                     "AggExprEmitter: VisitPredefinedExpr");287  }288  void VisitBinaryOperator(const BinaryOperator *e) {289    cgf.cgm.errorNYI(e->getSourceRange(),290                     "AggExprEmitter: VisitBinaryOperator");291  }292  void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *e) {293    cgf.cgm.errorNYI(e->getSourceRange(),294                     "AggExprEmitter: VisitPointerToDataMemberBinaryOperator");295  }296  void VisitBinComma(const BinaryOperator *e) {297    cgf.emitIgnoredExpr(e->getLHS());298    Visit(e->getRHS());299  }300  void VisitBinCmp(const BinaryOperator *e) {301    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitBinCmp");302  }303  void VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) {304    cgf.cgm.errorNYI(e->getSourceRange(),305                     "AggExprEmitter: VisitCXXRewrittenBinaryOperator");306  }307  void VisitObjCMessageExpr(ObjCMessageExpr *e) {308    cgf.cgm.errorNYI(e->getSourceRange(),309                     "AggExprEmitter: VisitObjCMessageExpr");310  }311  void VisitObjCIVarRefExpr(ObjCIvarRefExpr *e) {312    cgf.cgm.errorNYI(e->getSourceRange(),313                     "AggExprEmitter: VisitObjCIVarRefExpr");314  }315 316  void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *e) {317    AggValueSlot dest = ensureSlot(cgf.getLoc(e->getExprLoc()), e->getType());318    LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());319    emitInitializationToLValue(e->getBase(), destLV);320    VisitInitListExpr(e->getUpdater());321  }322  void VisitAbstractConditionalOperator(const AbstractConditionalOperator *e) {323    cgf.cgm.errorNYI(e->getSourceRange(),324                     "AggExprEmitter: VisitAbstractConditionalOperator");325  }326  void VisitChooseExpr(const ChooseExpr *e) { Visit(e->getChosenSubExpr()); }327  void VisitCXXParenListInitExpr(CXXParenListInitExpr *e) {328    visitCXXParenListOrInitListExpr(e, e->getInitExprs(),329                                    e->getInitializedFieldInUnion(),330                                    e->getArrayFiller());331  }332 333  void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *e,334                              llvm::Value *outerBegin = nullptr) {335    cgf.cgm.errorNYI(e->getSourceRange(),336                     "AggExprEmitter: VisitArrayInitLoopExpr");337  }338  void VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) {339    cgf.cgm.errorNYI(e->getSourceRange(),340                     "AggExprEmitter: VisitImplicitValueInitExpr");341  }342  void VisitNoInitExpr(NoInitExpr *e) {343    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitNoInitExpr");344  }345  void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) {346    CIRGenFunction::CXXDefaultArgExprScope scope(cgf, dae);347    Visit(dae->getExpr());348  }349  void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) {350    cgf.cgm.errorNYI(e->getSourceRange(),351                     "AggExprEmitter: VisitCXXInheritedCtorInitExpr");352  }353  void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *e) {354    cgf.cgm.errorNYI(e->getSourceRange(),355                     "AggExprEmitter: VisitCXXStdInitializerListExpr");356  }357  void VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) {358    cgf.cgm.errorNYI(e->getSourceRange(),359                     "AggExprEmitter: VisitCXXScalarValueInitExpr");360  }361  void VisitCXXTypeidExpr(CXXTypeidExpr *e) {362    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCXXTypeidExpr");363  }364  void VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *e) {365    Visit(e->getSubExpr());366  }367  void VisitOpaqueValueExpr(OpaqueValueExpr *e) {368    cgf.cgm.errorNYI(e->getSourceRange(),369                     "AggExprEmitter: VisitOpaqueValueExpr");370  }371 372  void VisitPseudoObjectExpr(PseudoObjectExpr *e) {373    cgf.cgm.errorNYI(e->getSourceRange(),374                     "AggExprEmitter: VisitPseudoObjectExpr");375  }376 377  void VisitVAArgExpr(VAArgExpr *e) {378    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitVAArgExpr");379  }380 381  void VisitCXXThrowExpr(const CXXThrowExpr *e) {382    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCXXThrowExpr");383  }384  void VisitAtomicExpr(AtomicExpr *e) {385    cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitAtomicExpr");386  }387};388 389} // namespace390 391static bool isTrivialFiller(Expr *e) {392  if (!e)393    return true;394 395  if (isa<ImplicitValueInitExpr>(e))396    return true;397 398  if (auto *ile = dyn_cast<InitListExpr>(e)) {399    if (ile->getNumInits())400      return false;401    return isTrivialFiller(ile->getArrayFiller());402  }403 404  if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))405    return cons->getConstructor()->isDefaultConstructor() &&406           cons->getConstructor()->isTrivial();407 408  return false;409}410 411/// Given an expression with aggregate type that represents a value lvalue, this412/// method emits the address of the lvalue, then loads the result into DestPtr.413void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {414  LValue lv = cgf.emitLValue(e);415 416  // If the type of the l-value is atomic, then do an atomic load.417  assert(!cir::MissingFeatures::opLoadStoreAtomic());418 419  emitFinalDestCopy(e->getType(), lv);420}421 422void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *e) {423  if (dest.isPotentiallyAliased() && e->getType().isPODType(cgf.getContext())) {424    // For a POD type, just emit a load of the lvalue + a copy, because our425    // compound literal might alias the destination.426    emitAggLoadOfLValue(e);427    return;428  }429 430  AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());431 432  // Block-scope compound literals are destroyed at the end of the enclosing433  // scope in C.434  bool destruct =435      !cgf.getLangOpts().CPlusPlus && !slot.isExternallyDestructed();436  if (destruct)437    slot.setExternallyDestructed();438 439  cgf.emitAggExpr(e->getInitializer(), slot);440 441  if (destruct)442    if ([[maybe_unused]] QualType::DestructionKind dtorKind =443            e->getType().isDestructedType())444      cgf.cgm.errorNYI(e->getSourceRange(), "compound literal with destructor");445}446 447void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,448                                   QualType arrayQTy, Expr *e,449                                   ArrayRef<Expr *> args, Expr *arrayFiller) {450  CIRGenBuilderTy &builder = cgf.getBuilder();451  const mlir::Location loc = cgf.getLoc(e->getSourceRange());452 453  const uint64_t numInitElements = args.size();454 455  const QualType elementType =456      cgf.getContext().getAsArrayType(arrayQTy)->getElementType();457 458  if (elementType.isDestructedType() && cgf.cgm.getLangOpts().Exceptions) {459    cgf.cgm.errorNYI(loc, "initialized array requires destruction");460    return;461  }462 463  const QualType elementPtrType = cgf.getContext().getPointerType(elementType);464 465  const mlir::Type cirElementType = cgf.convertType(elementType);466  const cir::PointerType cirElementPtrType =467      builder.getPointerTo(cirElementType);468 469  auto begin = cir::CastOp::create(builder, loc, cirElementPtrType,470                                   cir::CastKind::array_to_ptrdecay,471                                   destPtr.getPointer());472 473  const CharUnits elementSize =474      cgf.getContext().getTypeSizeInChars(elementType);475  const CharUnits elementAlign =476      destPtr.getAlignment().alignmentOfArrayElement(elementSize);477 478  // The 'current element to initialize'.  The invariants on this479  // variable are complicated.  Essentially, after each iteration of480  // the loop, it points to the last initialized element, except481  // that it points to the beginning of the array before any482  // elements have been initialized.483  mlir::Value element = begin;484 485  // Don't build the 'one' before the cycle to avoid486  // emmiting the redundant `cir.const 1` instrs.487  mlir::Value one;488 489  // Emit the explicit initializers.490  for (uint64_t i = 0; i != numInitElements; ++i) {491    // Advance to the next element.492    if (i > 0) {493      one = builder.getConstantInt(loc, cgf.ptrDiffTy, i);494      element = builder.createPtrStride(loc, begin, one);495    }496 497    const Address address = Address(element, cirElementType, elementAlign);498    const LValue elementLV = cgf.makeAddrLValue(address, elementType);499    emitInitializationToLValue(args[i], elementLV);500  }501 502  const uint64_t numArrayElements = arrayTy.getSize();503 504  // Check whether there's a non-trivial array-fill expression.505  const bool hasTrivialFiller = isTrivialFiller(arrayFiller);506 507  // Any remaining elements need to be zero-initialized, possibly508  // using the filler expression.  We can skip this if the we're509  // emitting to zeroed memory.510  if (numInitElements != numArrayElements &&511      !(dest.isZeroed() && hasTrivialFiller &&512        cgf.getTypes().isZeroInitializable(elementType))) {513    // Advance to the start of the rest of the array.514    if (numInitElements) {515      one = builder.getConstantInt(loc, cgf.ptrDiffTy, 1);516      element = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,517                                         element, one);518    }519 520    // Allocate the temporary variable521    // to store the pointer to first unitialized element522    const Address tmpAddr = cgf.createTempAlloca(523        cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");524    LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);525    cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);526 527    // Compute the end of array528    cir::ConstantOp numArrayElementsConst = builder.getConstInt(529        loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), numArrayElements);530    mlir::Value end = cir::PtrStrideOp::create(builder, loc, cirElementPtrType,531                                               begin, numArrayElementsConst);532 533    builder.createDoWhile(534        loc,535        /*condBuilder=*/536        [&](mlir::OpBuilder &b, mlir::Location loc) {537          cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);538          mlir::Type boolTy = cgf.convertType(cgf.getContext().BoolTy);539          cir::CmpOp cmp = cir::CmpOp::create(540              builder, loc, boolTy, cir::CmpOpKind::ne, currentElement, end);541          builder.createCondition(cmp);542        },543        /*bodyBuilder=*/544        [&](mlir::OpBuilder &b, mlir::Location loc) {545          cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);546 547          assert(!cir::MissingFeatures::requiresCleanups());548 549          // Emit the actual filler expression.550          LValue elementLV = cgf.makeAddrLValue(551              Address(currentElement, cirElementType, elementAlign),552              elementType);553          if (arrayFiller)554            emitInitializationToLValue(arrayFiller, elementLV);555          else556            emitNullInitializationToLValue(loc, elementLV);557 558          // Tell the EH cleanup that we finished with the last element.559          if (cgf.cgm.getLangOpts().Exceptions) {560            cgf.cgm.errorNYI(loc, "update destructed array element for EH");561            return;562          }563 564          // Advance pointer and store them to temporary variable565          cir::ConstantOp one = builder.getConstInt(566              loc, mlir::cast<cir::IntType>(cgf.ptrDiffTy), 1);567          auto nextElement = cir::PtrStrideOp::create(568              builder, loc, cirElementPtrType, currentElement, one);569          cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);570 571          builder.createYield(loc);572        });573  }574}575 576/// Perform the final copy to destPtr, if desired.577void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {578  // If dest is ignored, then we're evaluating an aggregate expression579  // in a context that doesn't care about the result.  Note that loads580  // from volatile l-values force the existence of a non-ignored581  // destination.582  if (dest.isIgnored())583    return;584 585  assert(!cir::MissingFeatures::aggValueSlotVolatile());586  assert(!cir::MissingFeatures::aggEmitFinalDestCopyRValue());587  assert(!cir::MissingFeatures::aggValueSlotGC());588 589  AggValueSlot srcAgg = AggValueSlot::forLValue(src, AggValueSlot::IsDestructed,590                                                AggValueSlot::IsAliased,591                                                AggValueSlot::MayOverlap);592  emitCopy(type, dest, srcAgg);593}594 595/// Perform a copy from the source into the destination.596///597/// \param type - the type of the aggregate being copied; qualifiers are598///   ignored599void AggExprEmitter::emitCopy(QualType type, const AggValueSlot &dest,600                              const AggValueSlot &src) {601  assert(!cir::MissingFeatures::aggValueSlotGC());602 603  // If the result of the assignment is used, copy the LHS there also.604  // It's volatile if either side is.  Use the minimum alignment of605  // the two sides.606  LValue destLV = cgf.makeAddrLValue(dest.getAddress(), type);607  LValue srcLV = cgf.makeAddrLValue(src.getAddress(), type);608  assert(!cir::MissingFeatures::aggValueSlotVolatile());609  cgf.emitAggregateCopy(destLV, srcLV, type, dest.mayOverlap(),610                        dest.isVolatile() || src.isVolatile());611}612 613void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {614  const QualType type = lv.getType();615 616  if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {617    const mlir::Location loc = e->getSourceRange().isValid()618                                   ? cgf.getLoc(e->getSourceRange())619                                   : *cgf.currSrcLoc;620    return emitNullInitializationToLValue(loc, lv);621  }622 623  if (isa<NoInitExpr>(e))624    return;625 626  if (type->isReferenceType()) {627    RValue rv = cgf.emitReferenceBindingToExpr(e);628    return cgf.emitStoreThroughLValue(rv, lv);629  }630 631  switch (cgf.getEvaluationKind(type)) {632  case cir::TEK_Complex:633    cgf.emitComplexExprIntoLValue(e, lv, /*isInit*/ true);634    break;635  case cir::TEK_Aggregate:636    cgf.emitAggExpr(e, AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed,637                                               AggValueSlot::IsNotAliased,638                                               AggValueSlot::MayOverlap,639                                               dest.isZeroed()));640 641    return;642  case cir::TEK_Scalar:643    if (lv.isSimple())644      cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);645    else646      cgf.emitStoreThroughLValue(RValue::get(cgf.emitScalarExpr(e)), lv);647    return;648  }649}650 651void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {652  AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());653  cgf.emitCXXConstructExpr(e, slot);654}655 656void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,657                                                    LValue lv) {658  const QualType type = lv.getType();659 660  // If the destination slot is already zeroed out before the aggregate is661  // copied into it, we don't have to emit any zeros here.662  if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))663    return;664 665  if (cgf.hasScalarEvaluationKind(type)) {666    // For non-aggregates, we can store the appropriate null constant.667    mlir::Value null = cgf.cgm.emitNullConstant(type, loc);668    if (lv.isSimple()) {669      cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);670      return;671    }672 673    cgf.emitStoreThroughBitfieldLValue(RValue::get(null), lv);674    return;675  }676 677  // There's a potential optimization opportunity in combining678  // memsets; that would be easy for arrays, but relatively679  // difficult for structures with the current code.680  cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());681}682 683void AggExprEmitter::VisitLambdaExpr(LambdaExpr *e) {684  CIRGenFunction::SourceLocRAIIObject loc{cgf, cgf.getLoc(e->getSourceRange())};685  AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());686  [[maybe_unused]] LValue slotLV =687      cgf.makeAddrLValue(slot.getAddress(), e->getType());688 689  // We'll need to enter cleanup scopes in case any of the element690  // initializers throws an exception or contains branch out of the expressions.691  assert(!cir::MissingFeatures::opScopeCleanupRegion());692 693  for (auto [curField, capture, captureInit] : llvm::zip(694           e->getLambdaClass()->fields(), e->captures(), e->capture_inits())) {695    // Pick a name for the field.696    llvm::StringRef fieldName = curField->getName();697    if (capture.capturesVariable()) {698      assert(!curField->isBitField() && "lambdas don't have bitfield members!");699      ValueDecl *v = capture.getCapturedVar();700      fieldName = v->getName();701      cgf.cgm.lambdaFieldToName[curField] = fieldName;702    } else if (capture.capturesThis()) {703      cgf.cgm.lambdaFieldToName[curField] = "this";704    } else {705      cgf.cgm.errorNYI(e->getSourceRange(), "Unhandled capture kind");706      cgf.cgm.lambdaFieldToName[curField] = "unhandled-capture-kind";707    }708 709    // Emit initialization710    LValue lv =711        cgf.emitLValueForFieldInitialization(slotLV, curField, fieldName);712    if (curField->hasCapturedVLAType())713      cgf.cgm.errorNYI(e->getSourceRange(), "lambda captured VLA type");714 715    emitInitializationToLValue(captureInit, lv);716 717    // Push a destructor if necessary.718    if ([[maybe_unused]] QualType::DestructionKind DtorKind =719            curField->getType().isDestructedType())720      cgf.cgm.errorNYI(e->getSourceRange(), "lambda with destructed field");721  }722}723 724void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *e) {725  CIRGenFunction::RunCleanupsScope cleanups(cgf);726  Visit(e->getSubExpr());727}728 729void AggExprEmitter::VisitCallExpr(const CallExpr *e) {730  if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {731    cgf.cgm.errorNYI(e->getSourceRange(), "reference return type");732    return;733  }734 735  withReturnValueSlot(736      e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });737}738 739void AggExprEmitter::withReturnValueSlot(740    const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {741  QualType retTy = e->getType();742 743  assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());744  bool requiresDestruction =745      retTy.isDestructedType() == QualType::DK_nontrivial_c_struct;746  if (requiresDestruction)747    cgf.cgm.errorNYI(748        e->getSourceRange(),749        "withReturnValueSlot: return value requiring destruction is NYI");750 751  // If it makes no observable difference, save a memcpy + temporary.752  //753  // We need to always provide our own temporary if destruction is required.754  // Otherwise, fn will emit its own, notice that it's "unused", and end its755  // lifetime before we have the chance to emit a proper destructor call.756  assert(!cir::MissingFeatures::aggValueSlotAlias());757  assert(!cir::MissingFeatures::aggValueSlotGC());758 759  Address retAddr = dest.getAddress();760  assert(!cir::MissingFeatures::emitLifetimeMarkers());761 762  assert(!cir::MissingFeatures::aggValueSlotVolatile());763  assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());764  fn(ReturnValueSlot(retAddr));765}766 767void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {768  if (e->hadArrayRangeDesignator())769    llvm_unreachable("GNU array range designator extension");770 771  if (e->isTransparent())772    return Visit(e->getInit(0));773 774  visitCXXParenListOrInitListExpr(775      e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());776}777 778void AggExprEmitter::visitCXXParenListOrInitListExpr(779    Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,780    Expr *arrayFiller) {781 782  const mlir::Location loc = cgf.getLoc(e->getSourceRange());783  const AggValueSlot dest = ensureSlot(loc, e->getType());784 785  if (e->getType()->isConstantArrayType()) {786    cir::ArrayType arrayTy =787        cast<cir::ArrayType>(dest.getAddress().getElementType());788    emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,789                  arrayFiller);790    return;791  } else if (e->getType()->isVariableArrayType()) {792    cgf.cgm.errorNYI(e->getSourceRange(),793                     "visitCXXParenListOrInitListExpr variable array type");794    return;795  }796 797  if (e->getType()->isArrayType()) {798    cgf.cgm.errorNYI(e->getSourceRange(),799                     "visitCXXParenListOrInitListExpr array type");800    return;801  }802 803  assert(e->getType()->isRecordType() && "Only support structs/unions here!");804 805  // Do struct initialization; this code just sets each individual member806  // to the approprate value.  This makes bitfield support automatic;807  // the disadvantage is that the generated code is more difficult for808  // the optimizer, especially with bitfields.809  unsigned numInitElements = args.size();810  auto *record = e->getType()->castAsRecordDecl();811 812  // We'll need to enter cleanup scopes in case any of the element813  // initializers throws an exception.814  assert(!cir::MissingFeatures::requiresCleanups());815 816  unsigned curInitIndex = 0;817 818  // Emit initialization of base classes.819  if (auto *cxxrd = dyn_cast<CXXRecordDecl>(record)) {820    assert(numInitElements >= cxxrd->getNumBases() &&821           "missing initializer for base class");822    for (auto &base : cxxrd->bases()) {823      assert(!base.isVirtual() && "should not see vbases here");824      CXXRecordDecl *baseRD = base.getType()->getAsCXXRecordDecl();825      Address address = cgf.getAddressOfDirectBaseInCompleteClass(826          loc, dest.getAddress(), cxxrd, baseRD,827          /*baseIsVirtual=*/false);828      assert(!cir::MissingFeatures::aggValueSlotGC());829      AggValueSlot aggSlot = AggValueSlot::forAddr(830          address, Qualifiers(), AggValueSlot::IsDestructed,831          AggValueSlot::IsNotAliased,832          cgf.getOverlapForBaseInit(cxxrd, baseRD, false));833      cgf.emitAggExpr(args[curInitIndex++], aggSlot);834      if (base.getType().isDestructedType()) {835        cgf.cgm.errorNYI(e->getSourceRange(),836                         "push deferred deactivation cleanup");837        return;838      }839    }840  }841 842  // Prepare a 'this' for CXXDefaultInitExprs.843  CIRGenFunction::FieldConstructionScope fcScope(cgf, dest.getAddress());844 845  LValue destLV = cgf.makeAddrLValue(dest.getAddress(), e->getType());846 847  if (record->isUnion()) {848    cgf.cgm.errorNYI(e->getSourceRange(),849                     "visitCXXParenListOrInitListExpr union type");850    return;851  }852 853  // Here we iterate over the fields; this makes it simpler to both854  // default-initialize fields and skip over unnamed fields.855  for (const FieldDecl *field : record->fields()) {856    // We're done once we hit the flexible array member.857    if (field->getType()->isIncompleteArrayType())858      break;859 860    // Always skip anonymous bitfields.861    if (field->isUnnamedBitField())862      continue;863 864    // We're done if we reach the end of the explicit initializers, we865    // have a zeroed object, and the rest of the fields are866    // zero-initializable.867    if (curInitIndex == numInitElements && dest.isZeroed() &&868        cgf.getTypes().isZeroInitializable(e->getType()))869      break;870    LValue lv =871        cgf.emitLValueForFieldInitialization(destLV, field, field->getName());872    // We never generate write-barriers for initialized fields.873    assert(!cir::MissingFeatures::setNonGC());874 875    if (curInitIndex < numInitElements) {876      // Store the initializer into the field.877      CIRGenFunction::SourceLocRAIIObject loc{878          cgf, cgf.getLoc(record->getSourceRange())};879      emitInitializationToLValue(args[curInitIndex++], lv);880    } else {881      // We're out of initializers; default-initialize to null882      emitNullInitializationToLValue(cgf.getLoc(e->getSourceRange()), lv);883    }884 885    // Push a destructor if necessary.886    // FIXME: if we have an array of structures, all explicitly887    // initialized, we can end up pushing a linear number of cleanups.888    if (field->getType().isDestructedType()) {889      cgf.cgm.errorNYI(e->getSourceRange(),890                       "visitCXXParenListOrInitListExpr destructor");891      return;892    }893 894    // From classic codegen, maybe not useful for CIR:895    // If the GEP didn't get used because of a dead zero init or something896    // else, clean it up for -O0 builds and general tidiness.897  }898}899 900// TODO(cir): This could be shared with classic codegen.901AggValueSlot::Overlap_t CIRGenFunction::getOverlapForBaseInit(902    const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {903  // If the most-derived object is a field declared with [[no_unique_address]],904  // the tail padding of any virtual base could be reused for other subobjects905  // of that field's class.906  if (isVirtual)907    return AggValueSlot::MayOverlap;908 909  // If the base class is laid out entirely within the nvsize of the derived910  // class, its tail padding cannot yet be initialized, so we can issue911  // stores at the full width of the base class.912  const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);913  if (layout.getBaseClassOffset(baseRD) +914          getContext().getASTRecordLayout(baseRD).getSize() <=915      layout.getNonVirtualSize())916    return AggValueSlot::DoesNotOverlap;917 918  // The tail padding may contain values we need to preserve.919  return AggValueSlot::MayOverlap;920}921 922void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {923  AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));924}925 926void CIRGenFunction::emitAggregateCopy(LValue dest, LValue src, QualType ty,927                                       AggValueSlot::Overlap_t mayOverlap,928                                       bool isVolatile) {929  // TODO(cir): this function needs improvements, commented code for now since930  // this will be touched again soon.931  assert(!ty->isAnyComplexType() && "Unexpected copy of complex");932 933  Address destPtr = dest.getAddress();934  Address srcPtr = src.getAddress();935 936  if (getLangOpts().CPlusPlus) {937    if (auto *record = ty->getAsCXXRecordDecl()) {938      assert((record->hasTrivialCopyConstructor() ||939              record->hasTrivialCopyAssignment() ||940              record->hasTrivialMoveConstructor() ||941              record->hasTrivialMoveAssignment() ||942              record->hasAttr<TrivialABIAttr>() || record->isUnion()) &&943             "Trying to aggregate-copy a type without a trivial copy/move "944             "constructor or assignment operator");945      // Ignore empty classes in C++.946      if (record->isEmpty())947        return;948    }949  }950 951  assert(!cir::MissingFeatures::cudaSupport());952 953  // Aggregate assignment turns into llvm.memcpy.  This is almost valid per954  // C99 6.5.16.1p3, which states "If the value being stored in an object is955  // read from another object that overlaps in anyway the storage of the first956  // object, then the overlap shall be exact and the two objects shall have957  // qualified or unqualified versions of a compatible type."958  //959  // memcpy is not defined if the source and destination pointers are exactly960  // equal, but other compilers do this optimization, and almost every memcpy961  // implementation handles this case safely.  If there is a libc that does not962  // safely handle this, we can add a target hook.963 964  // Get data size info for this aggregate. Don't copy the tail padding if this965  // might be a potentially-overlapping subobject, since the tail padding might966  // be occupied by a different object. Otherwise, copying it is fine.967  TypeInfoChars typeInfo;968  if (mayOverlap)969    typeInfo = getContext().getTypeInfoDataSizeInChars(ty);970  else971    typeInfo = getContext().getTypeInfoInChars(ty);972 973  assert(!cir::MissingFeatures::aggValueSlotVolatile());974 975  // NOTE(cir): original codegen would normally convert destPtr and srcPtr to976  // i8* since memcpy operates on bytes. We don't need that in CIR because977  // cir.copy will operate on any CIR pointer that points to a sized type.978 979  // Don't do any of the memmove_collectable tests if GC isn't set.980  if (cgm.getLangOpts().getGC() != LangOptions::NonGC)981    cgm.errorNYI("emitAggregateCopy: GC");982 983  [[maybe_unused]] cir::CopyOp copyOp =984      builder.createCopy(destPtr.getPointer(), srcPtr.getPointer(), isVolatile);985 986  assert(!cir::MissingFeatures::opTBAA());987}988 989// TODO(cir): This could be shared with classic codegen.990AggValueSlot::Overlap_t991CIRGenFunction::getOverlapForFieldInit(const FieldDecl *fd) {992  if (!fd->hasAttr<NoUniqueAddressAttr>() || !fd->getType()->isRecordType())993    return AggValueSlot::DoesNotOverlap;994 995  // If the field lies entirely within the enclosing class's nvsize, its tail996  // padding cannot overlap any already-initialized object. (The only subobjects997  // with greater addresses that might already be initialized are vbases.)998  const RecordDecl *classRD = fd->getParent();999  const ASTRecordLayout &layout = getContext().getASTRecordLayout(classRD);1000  if (layout.getFieldOffset(fd->getFieldIndex()) +1001          getContext().getTypeSize(fd->getType()) <=1002      (uint64_t)getContext().toBits(layout.getNonVirtualSize()))1003    return AggValueSlot::DoesNotOverlap;1004 1005  // The tail padding may contain values we need to preserve.1006  return AggValueSlot::MayOverlap;1007}1008 1009LValue CIRGenFunction::emitAggExprToLValue(const Expr *e) {1010  assert(hasAggregateEvaluationKind(e->getType()) && "Invalid argument!");1011  Address temp = createMemTemp(e->getType(), getLoc(e->getSourceRange()));1012  LValue lv = makeAddrLValue(temp, e->getType());1013  emitAggExpr(e, AggValueSlot::forLValue(lv, AggValueSlot::IsNotDestructed,1014                                         AggValueSlot::IsNotAliased,1015                                         AggValueSlot::DoesNotOverlap));1016  return lv;1017}1018