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