xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===- CIRGenExprAggregrate.cpp - Emit CIR Code from Aggregate Expressions ===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Aggregate Expr nodes as CIR code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CIRGenBuilder.h"
14*700637cbSDimitry Andric #include "CIRGenFunction.h"
15*700637cbSDimitry Andric #include "CIRGenValue.h"
16*700637cbSDimitry Andric #include "clang/CIR/Dialect/IR/CIRAttrs.h"
17*700637cbSDimitry Andric 
18*700637cbSDimitry Andric #include "clang/AST/Expr.h"
19*700637cbSDimitry Andric #include "clang/AST/RecordLayout.h"
20*700637cbSDimitry Andric #include "clang/AST/StmtVisitor.h"
21*700637cbSDimitry Andric #include <cstdint>
22*700637cbSDimitry Andric 
23*700637cbSDimitry Andric using namespace clang;
24*700637cbSDimitry Andric using namespace clang::CIRGen;
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric namespace {
27*700637cbSDimitry Andric class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric   CIRGenFunction &cgf;
30*700637cbSDimitry Andric   AggValueSlot dest;
31*700637cbSDimitry Andric 
32*700637cbSDimitry Andric   // Calls `fn` with a valid return value slot, potentially creating a temporary
33*700637cbSDimitry Andric   // to do so. If a temporary is created, an appropriate copy into `Dest` will
34*700637cbSDimitry Andric   // be emitted, as will lifetime markers.
35*700637cbSDimitry Andric   //
36*700637cbSDimitry Andric   // The given function should take a ReturnValueSlot, and return an RValue that
37*700637cbSDimitry Andric   // points to said slot.
38*700637cbSDimitry Andric   void withReturnValueSlot(const Expr *e,
39*700637cbSDimitry Andric                            llvm::function_ref<RValue(ReturnValueSlot)> fn);
40*700637cbSDimitry Andric 
ensureSlot(mlir::Location loc,QualType t)41*700637cbSDimitry Andric   AggValueSlot ensureSlot(mlir::Location loc, QualType t) {
42*700637cbSDimitry Andric     if (!dest.isIgnored())
43*700637cbSDimitry Andric       return dest;
44*700637cbSDimitry Andric 
45*700637cbSDimitry Andric     cgf.cgm.errorNYI(loc, "Slot for ignored address");
46*700637cbSDimitry Andric     return dest;
47*700637cbSDimitry Andric   }
48*700637cbSDimitry Andric 
49*700637cbSDimitry Andric public:
AggExprEmitter(CIRGenFunction & cgf,AggValueSlot dest)50*700637cbSDimitry Andric   AggExprEmitter(CIRGenFunction &cgf, AggValueSlot dest)
51*700637cbSDimitry Andric       : cgf(cgf), dest(dest) {}
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric   /// Given an expression with aggregate type that represents a value lvalue,
54*700637cbSDimitry Andric   /// this method emits the address of the lvalue, then loads the result into
55*700637cbSDimitry Andric   /// DestPtr.
56*700637cbSDimitry Andric   void emitAggLoadOfLValue(const Expr *e);
57*700637cbSDimitry Andric 
58*700637cbSDimitry Andric   void emitArrayInit(Address destPtr, cir::ArrayType arrayTy, QualType arrayQTy,
59*700637cbSDimitry Andric                      Expr *exprToVisit, ArrayRef<Expr *> args,
60*700637cbSDimitry Andric                      Expr *arrayFiller);
61*700637cbSDimitry Andric 
62*700637cbSDimitry Andric   /// Perform the final copy to DestPtr, if desired.
63*700637cbSDimitry Andric   void emitFinalDestCopy(QualType type, const LValue &src);
64*700637cbSDimitry Andric 
65*700637cbSDimitry Andric   void emitInitializationToLValue(Expr *e, LValue lv);
66*700637cbSDimitry Andric 
67*700637cbSDimitry Andric   void emitNullInitializationToLValue(mlir::Location loc, LValue lv);
68*700637cbSDimitry Andric 
Visit(Expr * e)69*700637cbSDimitry Andric   void Visit(Expr *e) { StmtVisitor<AggExprEmitter>::Visit(e); }
70*700637cbSDimitry Andric 
71*700637cbSDimitry Andric   void VisitCallExpr(const CallExpr *e);
72*700637cbSDimitry Andric 
VisitDeclRefExpr(DeclRefExpr * e)73*700637cbSDimitry Andric   void VisitDeclRefExpr(DeclRefExpr *e) { emitAggLoadOfLValue(e); }
74*700637cbSDimitry Andric 
75*700637cbSDimitry Andric   void VisitInitListExpr(InitListExpr *e);
76*700637cbSDimitry Andric   void VisitCXXConstructExpr(const CXXConstructExpr *e);
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric   void visitCXXParenListOrInitListExpr(Expr *e, ArrayRef<Expr *> args,
79*700637cbSDimitry Andric                                        FieldDecl *initializedFieldInUnion,
80*700637cbSDimitry Andric                                        Expr *arrayFiller);
81*700637cbSDimitry Andric };
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric } // namespace
84*700637cbSDimitry Andric 
isTrivialFiller(Expr * e)85*700637cbSDimitry Andric static bool isTrivialFiller(Expr *e) {
86*700637cbSDimitry Andric   if (!e)
87*700637cbSDimitry Andric     return true;
88*700637cbSDimitry Andric 
89*700637cbSDimitry Andric   if (isa<ImplicitValueInitExpr>(e))
90*700637cbSDimitry Andric     return true;
91*700637cbSDimitry Andric 
92*700637cbSDimitry Andric   if (auto *ile = dyn_cast<InitListExpr>(e)) {
93*700637cbSDimitry Andric     if (ile->getNumInits())
94*700637cbSDimitry Andric       return false;
95*700637cbSDimitry Andric     return isTrivialFiller(ile->getArrayFiller());
96*700637cbSDimitry Andric   }
97*700637cbSDimitry Andric 
98*700637cbSDimitry Andric   if (const auto *cons = dyn_cast_or_null<CXXConstructExpr>(e))
99*700637cbSDimitry Andric     return cons->getConstructor()->isDefaultConstructor() &&
100*700637cbSDimitry Andric            cons->getConstructor()->isTrivial();
101*700637cbSDimitry Andric 
102*700637cbSDimitry Andric   return false;
103*700637cbSDimitry Andric }
104*700637cbSDimitry Andric 
105*700637cbSDimitry Andric /// Given an expression with aggregate type that represents a value lvalue, this
106*700637cbSDimitry Andric /// method emits the address of the lvalue, then loads the result into DestPtr.
emitAggLoadOfLValue(const Expr * e)107*700637cbSDimitry Andric void AggExprEmitter::emitAggLoadOfLValue(const Expr *e) {
108*700637cbSDimitry Andric   LValue lv = cgf.emitLValue(e);
109*700637cbSDimitry Andric 
110*700637cbSDimitry Andric   // If the type of the l-value is atomic, then do an atomic load.
111*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opLoadStoreAtomic());
112*700637cbSDimitry Andric 
113*700637cbSDimitry Andric   emitFinalDestCopy(e->getType(), lv);
114*700637cbSDimitry Andric }
115*700637cbSDimitry Andric 
emitArrayInit(Address destPtr,cir::ArrayType arrayTy,QualType arrayQTy,Expr * e,ArrayRef<Expr * > args,Expr * arrayFiller)116*700637cbSDimitry Andric void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
117*700637cbSDimitry Andric                                    QualType arrayQTy, Expr *e,
118*700637cbSDimitry Andric                                    ArrayRef<Expr *> args, Expr *arrayFiller) {
119*700637cbSDimitry Andric   CIRGenBuilderTy &builder = cgf.getBuilder();
120*700637cbSDimitry Andric   const mlir::Location loc = cgf.getLoc(e->getSourceRange());
121*700637cbSDimitry Andric 
122*700637cbSDimitry Andric   const uint64_t numInitElements = args.size();
123*700637cbSDimitry Andric 
124*700637cbSDimitry Andric   const QualType elementType =
125*700637cbSDimitry Andric       cgf.getContext().getAsArrayType(arrayQTy)->getElementType();
126*700637cbSDimitry Andric 
127*700637cbSDimitry Andric   if (elementType.isDestructedType()) {
128*700637cbSDimitry Andric     cgf.cgm.errorNYI(loc, "dtorKind NYI");
129*700637cbSDimitry Andric     return;
130*700637cbSDimitry Andric   }
131*700637cbSDimitry Andric 
132*700637cbSDimitry Andric   const QualType elementPtrType = cgf.getContext().getPointerType(elementType);
133*700637cbSDimitry Andric 
134*700637cbSDimitry Andric   const mlir::Type cirElementType = cgf.convertType(elementType);
135*700637cbSDimitry Andric   const cir::PointerType cirElementPtrType =
136*700637cbSDimitry Andric       builder.getPointerTo(cirElementType);
137*700637cbSDimitry Andric 
138*700637cbSDimitry Andric   auto begin = builder.create<cir::CastOp>(loc, cirElementPtrType,
139*700637cbSDimitry Andric                                            cir::CastKind::array_to_ptrdecay,
140*700637cbSDimitry Andric                                            destPtr.getPointer());
141*700637cbSDimitry Andric 
142*700637cbSDimitry Andric   const CharUnits elementSize =
143*700637cbSDimitry Andric       cgf.getContext().getTypeSizeInChars(elementType);
144*700637cbSDimitry Andric   const CharUnits elementAlign =
145*700637cbSDimitry Andric       destPtr.getAlignment().alignmentOfArrayElement(elementSize);
146*700637cbSDimitry Andric 
147*700637cbSDimitry Andric   // The 'current element to initialize'.  The invariants on this
148*700637cbSDimitry Andric   // variable are complicated.  Essentially, after each iteration of
149*700637cbSDimitry Andric   // the loop, it points to the last initialized element, except
150*700637cbSDimitry Andric   // that it points to the beginning of the array before any
151*700637cbSDimitry Andric   // elements have been initialized.
152*700637cbSDimitry Andric   mlir::Value element = begin;
153*700637cbSDimitry Andric 
154*700637cbSDimitry Andric   // Don't build the 'one' before the cycle to avoid
155*700637cbSDimitry Andric   // emmiting the redundant `cir.const 1` instrs.
156*700637cbSDimitry Andric   mlir::Value one;
157*700637cbSDimitry Andric 
158*700637cbSDimitry Andric   // Emit the explicit initializers.
159*700637cbSDimitry Andric   for (uint64_t i = 0; i != numInitElements; ++i) {
160*700637cbSDimitry Andric     // Advance to the next element.
161*700637cbSDimitry Andric     if (i > 0) {
162*700637cbSDimitry Andric       one = builder.getConstantInt(loc, cgf.PtrDiffTy, i);
163*700637cbSDimitry Andric       element = builder.createPtrStride(loc, begin, one);
164*700637cbSDimitry Andric     }
165*700637cbSDimitry Andric 
166*700637cbSDimitry Andric     const Address address = Address(element, cirElementType, elementAlign);
167*700637cbSDimitry Andric     const LValue elementLV = cgf.makeAddrLValue(address, elementType);
168*700637cbSDimitry Andric     emitInitializationToLValue(args[i], elementLV);
169*700637cbSDimitry Andric   }
170*700637cbSDimitry Andric 
171*700637cbSDimitry Andric   const uint64_t numArrayElements = arrayTy.getSize();
172*700637cbSDimitry Andric 
173*700637cbSDimitry Andric   // Check whether there's a non-trivial array-fill expression.
174*700637cbSDimitry Andric   const bool hasTrivialFiller = isTrivialFiller(arrayFiller);
175*700637cbSDimitry Andric 
176*700637cbSDimitry Andric   // Any remaining elements need to be zero-initialized, possibly
177*700637cbSDimitry Andric   // using the filler expression.  We can skip this if the we're
178*700637cbSDimitry Andric   // emitting to zeroed memory.
179*700637cbSDimitry Andric   if (numInitElements != numArrayElements &&
180*700637cbSDimitry Andric       !(dest.isZeroed() && hasTrivialFiller &&
181*700637cbSDimitry Andric         cgf.getTypes().isZeroInitializable(elementType))) {
182*700637cbSDimitry Andric     // Advance to the start of the rest of the array.
183*700637cbSDimitry Andric     if (numInitElements) {
184*700637cbSDimitry Andric       one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1);
185*700637cbSDimitry Andric       element = builder.create<cir::PtrStrideOp>(loc, cirElementPtrType,
186*700637cbSDimitry Andric                                                  element, one);
187*700637cbSDimitry Andric     }
188*700637cbSDimitry Andric 
189*700637cbSDimitry Andric     // Allocate the temporary variable
190*700637cbSDimitry Andric     // to store the pointer to first unitialized element
191*700637cbSDimitry Andric     const Address tmpAddr = cgf.createTempAlloca(
192*700637cbSDimitry Andric         cirElementPtrType, cgf.getPointerAlign(), loc, "arrayinit.temp");
193*700637cbSDimitry Andric     LValue tmpLV = cgf.makeAddrLValue(tmpAddr, elementPtrType);
194*700637cbSDimitry Andric     cgf.emitStoreThroughLValue(RValue::get(element), tmpLV);
195*700637cbSDimitry Andric 
196*700637cbSDimitry Andric     // TODO(CIR): Replace this part later with cir::DoWhileOp
197*700637cbSDimitry Andric     for (unsigned i = numInitElements; i != numArrayElements; ++i) {
198*700637cbSDimitry Andric       cir::LoadOp currentElement = builder.createLoad(loc, tmpAddr);
199*700637cbSDimitry Andric 
200*700637cbSDimitry Andric       // Emit the actual filler expression.
201*700637cbSDimitry Andric       const LValue elementLV = cgf.makeAddrLValue(
202*700637cbSDimitry Andric           Address(currentElement, cirElementType, elementAlign), elementType);
203*700637cbSDimitry Andric 
204*700637cbSDimitry Andric       if (arrayFiller)
205*700637cbSDimitry Andric         emitInitializationToLValue(arrayFiller, elementLV);
206*700637cbSDimitry Andric       else
207*700637cbSDimitry Andric         emitNullInitializationToLValue(loc, elementLV);
208*700637cbSDimitry Andric 
209*700637cbSDimitry Andric       // Advance pointer and store them to temporary variable
210*700637cbSDimitry Andric       one = builder.getConstantInt(loc, cgf.PtrDiffTy, 1);
211*700637cbSDimitry Andric       cir::PtrStrideOp nextElement =
212*700637cbSDimitry Andric           builder.createPtrStride(loc, currentElement, one);
213*700637cbSDimitry Andric       cgf.emitStoreThroughLValue(RValue::get(nextElement), tmpLV);
214*700637cbSDimitry Andric     }
215*700637cbSDimitry Andric   }
216*700637cbSDimitry Andric }
217*700637cbSDimitry Andric 
218*700637cbSDimitry Andric /// Perform the final copy to destPtr, if desired.
emitFinalDestCopy(QualType type,const LValue & src)219*700637cbSDimitry Andric void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
220*700637cbSDimitry Andric   // If dest is ignored, then we're evaluating an aggregate expression
221*700637cbSDimitry Andric   // in a context that doesn't care about the result.  Note that loads
222*700637cbSDimitry Andric   // from volatile l-values force the existence of a non-ignored
223*700637cbSDimitry Andric   // destination.
224*700637cbSDimitry Andric   if (dest.isIgnored())
225*700637cbSDimitry Andric     return;
226*700637cbSDimitry Andric 
227*700637cbSDimitry Andric   cgf.cgm.errorNYI("emitFinalDestCopy: non-ignored dest is NYI");
228*700637cbSDimitry Andric }
229*700637cbSDimitry Andric 
emitInitializationToLValue(Expr * e,LValue lv)230*700637cbSDimitry Andric void AggExprEmitter::emitInitializationToLValue(Expr *e, LValue lv) {
231*700637cbSDimitry Andric   const QualType type = lv.getType();
232*700637cbSDimitry Andric 
233*700637cbSDimitry Andric   if (isa<ImplicitValueInitExpr, CXXScalarValueInitExpr>(e)) {
234*700637cbSDimitry Andric     const mlir::Location loc = e->getSourceRange().isValid()
235*700637cbSDimitry Andric                                    ? cgf.getLoc(e->getSourceRange())
236*700637cbSDimitry Andric                                    : *cgf.currSrcLoc;
237*700637cbSDimitry Andric     return emitNullInitializationToLValue(loc, lv);
238*700637cbSDimitry Andric   }
239*700637cbSDimitry Andric 
240*700637cbSDimitry Andric   if (isa<NoInitExpr>(e))
241*700637cbSDimitry Andric     return;
242*700637cbSDimitry Andric 
243*700637cbSDimitry Andric   if (type->isReferenceType())
244*700637cbSDimitry Andric     cgf.cgm.errorNYI("emitInitializationToLValue ReferenceType");
245*700637cbSDimitry Andric 
246*700637cbSDimitry Andric   switch (cgf.getEvaluationKind(type)) {
247*700637cbSDimitry Andric   case cir::TEK_Complex:
248*700637cbSDimitry Andric     cgf.cgm.errorNYI("emitInitializationToLValue TEK_Complex");
249*700637cbSDimitry Andric     break;
250*700637cbSDimitry Andric   case cir::TEK_Aggregate:
251*700637cbSDimitry Andric     cgf.emitAggExpr(e, AggValueSlot::forLValue(lv, AggValueSlot::IsDestructed,
252*700637cbSDimitry Andric                                                AggValueSlot::IsNotAliased,
253*700637cbSDimitry Andric                                                AggValueSlot::MayOverlap,
254*700637cbSDimitry Andric                                                dest.isZeroed()));
255*700637cbSDimitry Andric 
256*700637cbSDimitry Andric     return;
257*700637cbSDimitry Andric   case cir::TEK_Scalar:
258*700637cbSDimitry Andric     if (lv.isSimple())
259*700637cbSDimitry Andric       cgf.emitScalarInit(e, cgf.getLoc(e->getSourceRange()), lv);
260*700637cbSDimitry Andric     else
261*700637cbSDimitry Andric       cgf.emitStoreThroughLValue(RValue::get(cgf.emitScalarExpr(e)), lv);
262*700637cbSDimitry Andric     return;
263*700637cbSDimitry Andric   }
264*700637cbSDimitry Andric }
265*700637cbSDimitry Andric 
VisitCXXConstructExpr(const CXXConstructExpr * e)266*700637cbSDimitry Andric void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *e) {
267*700637cbSDimitry Andric   AggValueSlot slot = ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
268*700637cbSDimitry Andric   cgf.emitCXXConstructExpr(e, slot);
269*700637cbSDimitry Andric }
270*700637cbSDimitry Andric 
emitNullInitializationToLValue(mlir::Location loc,LValue lv)271*700637cbSDimitry Andric void AggExprEmitter::emitNullInitializationToLValue(mlir::Location loc,
272*700637cbSDimitry Andric                                                     LValue lv) {
273*700637cbSDimitry Andric   const QualType type = lv.getType();
274*700637cbSDimitry Andric 
275*700637cbSDimitry Andric   // If the destination slot is already zeroed out before the aggregate is
276*700637cbSDimitry Andric   // copied into it, we don't have to emit any zeros here.
277*700637cbSDimitry Andric   if (dest.isZeroed() && cgf.getTypes().isZeroInitializable(type))
278*700637cbSDimitry Andric     return;
279*700637cbSDimitry Andric 
280*700637cbSDimitry Andric   if (cgf.hasScalarEvaluationKind(type)) {
281*700637cbSDimitry Andric     // For non-aggregates, we can store the appropriate null constant.
282*700637cbSDimitry Andric     mlir::Value null = cgf.cgm.emitNullConstant(type, loc);
283*700637cbSDimitry Andric     if (lv.isSimple()) {
284*700637cbSDimitry Andric       cgf.emitStoreOfScalar(null, lv, /* isInitialization */ true);
285*700637cbSDimitry Andric       return;
286*700637cbSDimitry Andric     }
287*700637cbSDimitry Andric 
288*700637cbSDimitry Andric     cgf.cgm.errorNYI("emitStoreThroughBitfieldLValue");
289*700637cbSDimitry Andric     return;
290*700637cbSDimitry Andric   }
291*700637cbSDimitry Andric 
292*700637cbSDimitry Andric   // There's a potential optimization opportunity in combining
293*700637cbSDimitry Andric   // memsets; that would be easy for arrays, but relatively
294*700637cbSDimitry Andric   // difficult for structures with the current code.
295*700637cbSDimitry Andric   cgf.emitNullInitialization(loc, lv.getAddress(), lv.getType());
296*700637cbSDimitry Andric }
297*700637cbSDimitry Andric 
VisitCallExpr(const CallExpr * e)298*700637cbSDimitry Andric void AggExprEmitter::VisitCallExpr(const CallExpr *e) {
299*700637cbSDimitry Andric   if (e->getCallReturnType(cgf.getContext())->isReferenceType()) {
300*700637cbSDimitry Andric     cgf.cgm.errorNYI(e->getSourceRange(), "reference return type");
301*700637cbSDimitry Andric     return;
302*700637cbSDimitry Andric   }
303*700637cbSDimitry Andric 
304*700637cbSDimitry Andric   withReturnValueSlot(
305*700637cbSDimitry Andric       e, [&](ReturnValueSlot slot) { return cgf.emitCallExpr(e, slot); });
306*700637cbSDimitry Andric }
307*700637cbSDimitry Andric 
withReturnValueSlot(const Expr * e,llvm::function_ref<RValue (ReturnValueSlot)> fn)308*700637cbSDimitry Andric void AggExprEmitter::withReturnValueSlot(
309*700637cbSDimitry Andric     const Expr *e, llvm::function_ref<RValue(ReturnValueSlot)> fn) {
310*700637cbSDimitry Andric   QualType retTy = e->getType();
311*700637cbSDimitry Andric 
312*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());
313*700637cbSDimitry Andric   bool requiresDestruction =
314*700637cbSDimitry Andric       retTy.isDestructedType() == QualType::DK_nontrivial_c_struct;
315*700637cbSDimitry Andric   if (requiresDestruction)
316*700637cbSDimitry Andric     cgf.cgm.errorNYI(
317*700637cbSDimitry Andric         e->getSourceRange(),
318*700637cbSDimitry Andric         "withReturnValueSlot: return value requiring destruction is NYI");
319*700637cbSDimitry Andric 
320*700637cbSDimitry Andric   // If it makes no observable difference, save a memcpy + temporary.
321*700637cbSDimitry Andric   //
322*700637cbSDimitry Andric   // We need to always provide our own temporary if destruction is required.
323*700637cbSDimitry Andric   // Otherwise, fn will emit its own, notice that it's "unused", and end its
324*700637cbSDimitry Andric   // lifetime before we have the chance to emit a proper destructor call.
325*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotAlias());
326*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotGC());
327*700637cbSDimitry Andric 
328*700637cbSDimitry Andric   Address retAddr = dest.getAddress();
329*700637cbSDimitry Andric   assert(!cir::MissingFeatures::emitLifetimeMarkers());
330*700637cbSDimitry Andric 
331*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotVolatile());
332*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotDestructedFlag());
333*700637cbSDimitry Andric   fn(ReturnValueSlot(retAddr));
334*700637cbSDimitry Andric }
335*700637cbSDimitry Andric 
VisitInitListExpr(InitListExpr * e)336*700637cbSDimitry Andric void AggExprEmitter::VisitInitListExpr(InitListExpr *e) {
337*700637cbSDimitry Andric   if (e->hadArrayRangeDesignator())
338*700637cbSDimitry Andric     llvm_unreachable("GNU array range designator extension");
339*700637cbSDimitry Andric 
340*700637cbSDimitry Andric   if (e->isTransparent())
341*700637cbSDimitry Andric     return Visit(e->getInit(0));
342*700637cbSDimitry Andric 
343*700637cbSDimitry Andric   visitCXXParenListOrInitListExpr(
344*700637cbSDimitry Andric       e, e->inits(), e->getInitializedFieldInUnion(), e->getArrayFiller());
345*700637cbSDimitry Andric }
346*700637cbSDimitry Andric 
visitCXXParenListOrInitListExpr(Expr * e,ArrayRef<Expr * > args,FieldDecl * initializedFieldInUnion,Expr * arrayFiller)347*700637cbSDimitry Andric void AggExprEmitter::visitCXXParenListOrInitListExpr(
348*700637cbSDimitry Andric     Expr *e, ArrayRef<Expr *> args, FieldDecl *initializedFieldInUnion,
349*700637cbSDimitry Andric     Expr *arrayFiller) {
350*700637cbSDimitry Andric 
351*700637cbSDimitry Andric   const AggValueSlot dest =
352*700637cbSDimitry Andric       ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
353*700637cbSDimitry Andric 
354*700637cbSDimitry Andric   if (e->getType()->isConstantArrayType()) {
355*700637cbSDimitry Andric     cir::ArrayType arrayTy =
356*700637cbSDimitry Andric         cast<cir::ArrayType>(dest.getAddress().getElementType());
357*700637cbSDimitry Andric     emitArrayInit(dest.getAddress(), arrayTy, e->getType(), e, args,
358*700637cbSDimitry Andric                   arrayFiller);
359*700637cbSDimitry Andric     return;
360*700637cbSDimitry Andric   }
361*700637cbSDimitry Andric 
362*700637cbSDimitry Andric   cgf.cgm.errorNYI(
363*700637cbSDimitry Andric       "visitCXXParenListOrInitListExpr Record or VariableSizeArray type");
364*700637cbSDimitry Andric }
365*700637cbSDimitry Andric 
366*700637cbSDimitry Andric // TODO(cir): This could be shared with classic codegen.
getOverlapForBaseInit(const CXXRecordDecl * rd,const CXXRecordDecl * baseRD,bool isVirtual)367*700637cbSDimitry Andric AggValueSlot::Overlap_t CIRGenFunction::getOverlapForBaseInit(
368*700637cbSDimitry Andric     const CXXRecordDecl *rd, const CXXRecordDecl *baseRD, bool isVirtual) {
369*700637cbSDimitry Andric   // If the most-derived object is a field declared with [[no_unique_address]],
370*700637cbSDimitry Andric   // the tail padding of any virtual base could be reused for other subobjects
371*700637cbSDimitry Andric   // of that field's class.
372*700637cbSDimitry Andric   if (isVirtual)
373*700637cbSDimitry Andric     return AggValueSlot::MayOverlap;
374*700637cbSDimitry Andric 
375*700637cbSDimitry Andric   // If the base class is laid out entirely within the nvsize of the derived
376*700637cbSDimitry Andric   // class, its tail padding cannot yet be initialized, so we can issue
377*700637cbSDimitry Andric   // stores at the full width of the base class.
378*700637cbSDimitry Andric   const ASTRecordLayout &layout = getContext().getASTRecordLayout(rd);
379*700637cbSDimitry Andric   if (layout.getBaseClassOffset(baseRD) +
380*700637cbSDimitry Andric           getContext().getASTRecordLayout(baseRD).getSize() <=
381*700637cbSDimitry Andric       layout.getNonVirtualSize())
382*700637cbSDimitry Andric     return AggValueSlot::DoesNotOverlap;
383*700637cbSDimitry Andric 
384*700637cbSDimitry Andric   // The tail padding may contain values we need to preserve.
385*700637cbSDimitry Andric   return AggValueSlot::MayOverlap;
386*700637cbSDimitry Andric }
387*700637cbSDimitry Andric 
emitAggExpr(const Expr * e,AggValueSlot slot)388*700637cbSDimitry Andric void CIRGenFunction::emitAggExpr(const Expr *e, AggValueSlot slot) {
389*700637cbSDimitry Andric   AggExprEmitter(*this, slot).Visit(const_cast<Expr *>(e));
390*700637cbSDimitry Andric }
391*700637cbSDimitry Andric 
emitAggExprToLValue(const Expr * e)392*700637cbSDimitry Andric LValue CIRGenFunction::emitAggExprToLValue(const Expr *e) {
393*700637cbSDimitry Andric   assert(hasAggregateEvaluationKind(e->getType()) && "Invalid argument!");
394*700637cbSDimitry Andric   Address temp = createMemTemp(e->getType(), getLoc(e->getSourceRange()));
395*700637cbSDimitry Andric   LValue lv = makeAddrLValue(temp, e->getType());
396*700637cbSDimitry Andric   emitAggExpr(e, AggValueSlot::forLValue(lv, AggValueSlot::IsNotDestructed,
397*700637cbSDimitry Andric                                          AggValueSlot::IsNotAliased,
398*700637cbSDimitry Andric                                          AggValueSlot::DoesNotOverlap));
399*700637cbSDimitry Andric   return lv;
400*700637cbSDimitry Andric }
401