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