xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenClass.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
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 dealing with C++ code generation of classes
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CIRGenCXXABI.h"
14*700637cbSDimitry Andric #include "CIRGenFunction.h"
15*700637cbSDimitry Andric 
16*700637cbSDimitry Andric #include "clang/AST/ExprCXX.h"
17*700637cbSDimitry Andric #include "clang/AST/RecordLayout.h"
18*700637cbSDimitry Andric #include "clang/AST/Type.h"
19*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
20*700637cbSDimitry Andric 
21*700637cbSDimitry Andric using namespace clang;
22*700637cbSDimitry Andric using namespace clang::CIRGen;
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric /// Checks whether the given constructor is a valid subject for the
25*700637cbSDimitry Andric /// complete-to-base constructor delegation optimization, i.e. emitting the
26*700637cbSDimitry Andric /// complete constructor as a simple call to the base constructor.
isConstructorDelegationValid(const CXXConstructorDecl * ctor)27*700637cbSDimitry Andric bool CIRGenFunction::isConstructorDelegationValid(
28*700637cbSDimitry Andric     const CXXConstructorDecl *ctor) {
29*700637cbSDimitry Andric   // Currently we disable the optimization for classes with virtual bases
30*700637cbSDimitry Andric   // because (1) the address of parameter variables need to be consistent across
31*700637cbSDimitry Andric   // all initializers but (2) the delegate function call necessarily creates a
32*700637cbSDimitry Andric   // second copy of the parameter variable.
33*700637cbSDimitry Andric   //
34*700637cbSDimitry Andric   // The limiting example (purely theoretical AFAIK):
35*700637cbSDimitry Andric   //   struct A { A(int &c) { c++; } };
36*700637cbSDimitry Andric   //   struct A : virtual A {
37*700637cbSDimitry Andric   //     B(int count) : A(count) { printf("%d\n", count); }
38*700637cbSDimitry Andric   //   };
39*700637cbSDimitry Andric   // ...although even this example could in principle be emitted as a delegation
40*700637cbSDimitry Andric   // since the address of the parameter doesn't escape.
41*700637cbSDimitry Andric   if (ctor->getParent()->getNumVBases())
42*700637cbSDimitry Andric     return false;
43*700637cbSDimitry Andric 
44*700637cbSDimitry Andric   // We also disable the optimization for variadic functions because it's
45*700637cbSDimitry Andric   // impossible to "re-pass" varargs.
46*700637cbSDimitry Andric   if (ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
47*700637cbSDimitry Andric     return false;
48*700637cbSDimitry Andric 
49*700637cbSDimitry Andric   // FIXME: Decide if we can do a delegation of a delegating constructor.
50*700637cbSDimitry Andric   if (ctor->isDelegatingConstructor())
51*700637cbSDimitry Andric     return false;
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric   return true;
54*700637cbSDimitry Andric }
55*700637cbSDimitry Andric 
emitLValueForAnyFieldInitialization(CIRGenFunction & cgf,CXXCtorInitializer * memberInit,LValue & lhs)56*700637cbSDimitry Andric static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf,
57*700637cbSDimitry Andric                                                 CXXCtorInitializer *memberInit,
58*700637cbSDimitry Andric                                                 LValue &lhs) {
59*700637cbSDimitry Andric   FieldDecl *field = memberInit->getAnyMember();
60*700637cbSDimitry Andric   if (memberInit->isIndirectMemberInitializer()) {
61*700637cbSDimitry Andric     // If we are initializing an anonymous union field, drill down to the field.
62*700637cbSDimitry Andric     IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
63*700637cbSDimitry Andric     for (const auto *nd : indirectField->chain()) {
64*700637cbSDimitry Andric       auto *fd = cast<clang::FieldDecl>(nd);
65*700637cbSDimitry Andric       lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
66*700637cbSDimitry Andric     }
67*700637cbSDimitry Andric   } else {
68*700637cbSDimitry Andric     lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
69*700637cbSDimitry Andric   }
70*700637cbSDimitry Andric }
71*700637cbSDimitry Andric 
emitMemberInitializer(CIRGenFunction & cgf,const CXXRecordDecl * classDecl,CXXCtorInitializer * memberInit,const CXXConstructorDecl * constructor,FunctionArgList & args)72*700637cbSDimitry Andric static void emitMemberInitializer(CIRGenFunction &cgf,
73*700637cbSDimitry Andric                                   const CXXRecordDecl *classDecl,
74*700637cbSDimitry Andric                                   CXXCtorInitializer *memberInit,
75*700637cbSDimitry Andric                                   const CXXConstructorDecl *constructor,
76*700637cbSDimitry Andric                                   FunctionArgList &args) {
77*700637cbSDimitry Andric   assert(memberInit->isAnyMemberInitializer() &&
78*700637cbSDimitry Andric          "Mush have member initializer!");
79*700637cbSDimitry Andric   assert(memberInit->getInit() && "Must have initializer!");
80*700637cbSDimitry Andric 
81*700637cbSDimitry Andric   assert(!cir::MissingFeatures::generateDebugInfo());
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric   // non-static data member initializers
84*700637cbSDimitry Andric   FieldDecl *field = memberInit->getAnyMember();
85*700637cbSDimitry Andric   QualType fieldType = field->getType();
86*700637cbSDimitry Andric 
87*700637cbSDimitry Andric   mlir::Value thisPtr = cgf.loadCXXThis();
88*700637cbSDimitry Andric   QualType recordTy = cgf.getContext().getTypeDeclType(classDecl);
89*700637cbSDimitry Andric 
90*700637cbSDimitry Andric   // If a base constructor is being emitted, create an LValue that has the
91*700637cbSDimitry Andric   // non-virtual alignment.
92*700637cbSDimitry Andric   LValue lhs = (cgf.curGD.getCtorType() == Ctor_Base)
93*700637cbSDimitry Andric                    ? cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy)
94*700637cbSDimitry Andric                    : cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
95*700637cbSDimitry Andric 
96*700637cbSDimitry Andric   emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
97*700637cbSDimitry Andric 
98*700637cbSDimitry Andric   // Special case: If we are in a copy or move constructor, and we are copying
99*700637cbSDimitry Andric   // an array off PODs or classes with trivial copy constructors, ignore the AST
100*700637cbSDimitry Andric   // and perform the copy we know is equivalent.
101*700637cbSDimitry Andric   // FIXME: This is hacky at best... if we had a bit more explicit information
102*700637cbSDimitry Andric   // in the AST, we could generalize it more easily.
103*700637cbSDimitry Andric   const ConstantArrayType *array =
104*700637cbSDimitry Andric       cgf.getContext().getAsConstantArrayType(fieldType);
105*700637cbSDimitry Andric   if (array && constructor->isDefaulted() &&
106*700637cbSDimitry Andric       constructor->isCopyOrMoveConstructor()) {
107*700637cbSDimitry Andric     QualType baseElementTy = cgf.getContext().getBaseElementType(array);
108*700637cbSDimitry Andric     // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
109*700637cbSDimitry Andric     // whereas ClangIR wants to represent all object construction explicitly.
110*700637cbSDimitry Andric     if (!baseElementTy->isRecordType()) {
111*700637cbSDimitry Andric       cgf.cgm.errorNYI(memberInit->getSourceRange(),
112*700637cbSDimitry Andric                        "emitMemberInitializer: array of non-record type");
113*700637cbSDimitry Andric       return;
114*700637cbSDimitry Andric     }
115*700637cbSDimitry Andric   }
116*700637cbSDimitry Andric 
117*700637cbSDimitry Andric   cgf.emitInitializerForField(field, lhs, memberInit->getInit());
118*700637cbSDimitry Andric }
119*700637cbSDimitry Andric 
isInitializerOfDynamicClass(const CXXCtorInitializer * baseInit)120*700637cbSDimitry Andric static bool isInitializerOfDynamicClass(const CXXCtorInitializer *baseInit) {
121*700637cbSDimitry Andric   const Type *baseType = baseInit->getBaseClass();
122*700637cbSDimitry Andric   const auto *baseClassDecl =
123*700637cbSDimitry Andric       cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());
124*700637cbSDimitry Andric   return baseClassDecl->isDynamicClass();
125*700637cbSDimitry Andric }
126*700637cbSDimitry Andric 
127*700637cbSDimitry Andric /// Gets the address of a direct base class within a complete object.
128*700637cbSDimitry Andric /// This should only be used for (1) non-virtual bases or (2) virtual bases
129*700637cbSDimitry Andric /// when the type is known to be complete (e.g. in complete destructors).
130*700637cbSDimitry Andric ///
131*700637cbSDimitry Andric /// The object pointed to by 'thisAddr' is assumed to be non-null.
getAddressOfDirectBaseInCompleteClass(mlir::Location loc,Address thisAddr,const CXXRecordDecl * derived,const CXXRecordDecl * base,bool baseIsVirtual)132*700637cbSDimitry Andric Address CIRGenFunction::getAddressOfDirectBaseInCompleteClass(
133*700637cbSDimitry Andric     mlir::Location loc, Address thisAddr, const CXXRecordDecl *derived,
134*700637cbSDimitry Andric     const CXXRecordDecl *base, bool baseIsVirtual) {
135*700637cbSDimitry Andric   // 'thisAddr' must be a pointer (in some address space) to Derived.
136*700637cbSDimitry Andric   assert(thisAddr.getElementType() == convertType(derived));
137*700637cbSDimitry Andric 
138*700637cbSDimitry Andric   // Compute the offset of the virtual base.
139*700637cbSDimitry Andric   CharUnits offset;
140*700637cbSDimitry Andric   const ASTRecordLayout &layout = getContext().getASTRecordLayout(derived);
141*700637cbSDimitry Andric   if (baseIsVirtual)
142*700637cbSDimitry Andric     offset = layout.getVBaseClassOffset(base);
143*700637cbSDimitry Andric   else
144*700637cbSDimitry Andric     offset = layout.getBaseClassOffset(base);
145*700637cbSDimitry Andric 
146*700637cbSDimitry Andric   return builder.createBaseClassAddr(loc, thisAddr, convertType(base),
147*700637cbSDimitry Andric                                      offset.getQuantity(),
148*700637cbSDimitry Andric                                      /*assumeNotNull=*/true);
149*700637cbSDimitry Andric }
150*700637cbSDimitry Andric 
emitBaseInitializer(mlir::Location loc,const CXXRecordDecl * classDecl,CXXCtorInitializer * baseInit)151*700637cbSDimitry Andric void CIRGenFunction::emitBaseInitializer(mlir::Location loc,
152*700637cbSDimitry Andric                                          const CXXRecordDecl *classDecl,
153*700637cbSDimitry Andric                                          CXXCtorInitializer *baseInit) {
154*700637cbSDimitry Andric   assert(curFuncDecl && "loading 'this' without a func declaration?");
155*700637cbSDimitry Andric   assert(isa<CXXMethodDecl>(curFuncDecl));
156*700637cbSDimitry Andric 
157*700637cbSDimitry Andric   assert(baseInit->isBaseInitializer() && "Must have base initializer!");
158*700637cbSDimitry Andric 
159*700637cbSDimitry Andric   Address thisPtr = loadCXXThisAddress();
160*700637cbSDimitry Andric 
161*700637cbSDimitry Andric   const Type *baseType = baseInit->getBaseClass();
162*700637cbSDimitry Andric   const auto *baseClassDecl =
163*700637cbSDimitry Andric       cast<CXXRecordDecl>(baseType->castAs<RecordType>()->getDecl());
164*700637cbSDimitry Andric 
165*700637cbSDimitry Andric   bool isBaseVirtual = baseInit->isBaseVirtual();
166*700637cbSDimitry Andric 
167*700637cbSDimitry Andric   // If the initializer for the base (other than the constructor
168*700637cbSDimitry Andric   // itself) accesses 'this' in any way, we need to initialize the
169*700637cbSDimitry Andric   // vtables.
170*700637cbSDimitry Andric   if (classDecl->isDynamicClass()) {
171*700637cbSDimitry Andric     cgm.errorNYI(loc, "emitBaseInitializer: dynamic class");
172*700637cbSDimitry Andric     return;
173*700637cbSDimitry Andric   }
174*700637cbSDimitry Andric 
175*700637cbSDimitry Andric   // We can pretend to be a complete class because it only matters for
176*700637cbSDimitry Andric   // virtual bases, and we only do virtual bases for complete ctors.
177*700637cbSDimitry Andric   Address v = getAddressOfDirectBaseInCompleteClass(
178*700637cbSDimitry Andric       loc, thisPtr, classDecl, baseClassDecl, isBaseVirtual);
179*700637cbSDimitry Andric   assert(!cir::MissingFeatures::aggValueSlotGC());
180*700637cbSDimitry Andric   AggValueSlot aggSlot = AggValueSlot::forAddr(
181*700637cbSDimitry Andric       v, Qualifiers(), AggValueSlot::IsDestructed, AggValueSlot::IsNotAliased,
182*700637cbSDimitry Andric       getOverlapForBaseInit(classDecl, baseClassDecl, isBaseVirtual));
183*700637cbSDimitry Andric 
184*700637cbSDimitry Andric   emitAggExpr(baseInit->getInit(), aggSlot);
185*700637cbSDimitry Andric 
186*700637cbSDimitry Andric   assert(!cir::MissingFeatures::requiresCleanups());
187*700637cbSDimitry Andric }
188*700637cbSDimitry Andric 
189*700637cbSDimitry Andric /// This routine generates necessary code to initialize base classes and
190*700637cbSDimitry Andric /// non-static data members belonging to this constructor.
emitCtorPrologue(const CXXConstructorDecl * cd,CXXCtorType ctorType,FunctionArgList & args)191*700637cbSDimitry Andric void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
192*700637cbSDimitry Andric                                       CXXCtorType ctorType,
193*700637cbSDimitry Andric                                       FunctionArgList &args) {
194*700637cbSDimitry Andric   if (cd->isDelegatingConstructor()) {
195*700637cbSDimitry Andric     emitDelegatingCXXConstructorCall(cd, args);
196*700637cbSDimitry Andric     return;
197*700637cbSDimitry Andric   }
198*700637cbSDimitry Andric 
199*700637cbSDimitry Andric   // If there are no member initializers, we can just return.
200*700637cbSDimitry Andric   if (cd->getNumCtorInitializers() == 0)
201*700637cbSDimitry Andric     return;
202*700637cbSDimitry Andric 
203*700637cbSDimitry Andric   const CXXRecordDecl *classDecl = cd->getParent();
204*700637cbSDimitry Andric 
205*700637cbSDimitry Andric   // This code doesn't use range-based iteration because we may need to emit
206*700637cbSDimitry Andric   // code between the virtual base initializers and the non-virtual base or
207*700637cbSDimitry Andric   // between the non-virtual base initializers and the member initializers.
208*700637cbSDimitry Andric   CXXConstructorDecl::init_const_iterator b = cd->init_begin(),
209*700637cbSDimitry Andric                                           e = cd->init_end();
210*700637cbSDimitry Andric 
211*700637cbSDimitry Andric   // Virtual base initializers first, if any. They aren't needed if:
212*700637cbSDimitry Andric   // - This is a base ctor variant
213*700637cbSDimitry Andric   // - There are no vbases
214*700637cbSDimitry Andric   // - The class is abstract, so a complete object of it cannot be constructed
215*700637cbSDimitry Andric   //
216*700637cbSDimitry Andric   // The check for an abstract class is necessary because sema may not have
217*700637cbSDimitry Andric   // marked virtual base destructors referenced.
218*700637cbSDimitry Andric   bool constructVBases = ctorType != Ctor_Base &&
219*700637cbSDimitry Andric                          classDecl->getNumVBases() != 0 &&
220*700637cbSDimitry Andric                          !classDecl->isAbstract();
221*700637cbSDimitry Andric   if (constructVBases) {
222*700637cbSDimitry Andric     cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base");
223*700637cbSDimitry Andric     return;
224*700637cbSDimitry Andric   }
225*700637cbSDimitry Andric 
226*700637cbSDimitry Andric   const mlir::Value oldThisValue = cxxThisValue;
227*700637cbSDimitry Andric   if (!constructVBases && (*b)->isBaseInitializer() && (*b)->isBaseVirtual()) {
228*700637cbSDimitry Andric     cgm.errorNYI(cd->getSourceRange(),
229*700637cbSDimitry Andric                  "emitCtorPrologue: virtual base initializer");
230*700637cbSDimitry Andric     return;
231*700637cbSDimitry Andric   }
232*700637cbSDimitry Andric 
233*700637cbSDimitry Andric   // Handle non-virtual base initializers.
234*700637cbSDimitry Andric   for (; b != e && (*b)->isBaseInitializer(); b++) {
235*700637cbSDimitry Andric     assert(!(*b)->isBaseVirtual());
236*700637cbSDimitry Andric 
237*700637cbSDimitry Andric     if (cgm.getCodeGenOpts().StrictVTablePointers &&
238*700637cbSDimitry Andric         cgm.getCodeGenOpts().OptimizationLevel > 0 &&
239*700637cbSDimitry Andric         isInitializerOfDynamicClass(*b)) {
240*700637cbSDimitry Andric       cgm.errorNYI(cd->getSourceRange(),
241*700637cbSDimitry Andric                    "emitCtorPrologue: strict vtable pointers");
242*700637cbSDimitry Andric       return;
243*700637cbSDimitry Andric     }
244*700637cbSDimitry Andric     emitBaseInitializer(getLoc(cd->getBeginLoc()), classDecl, *b);
245*700637cbSDimitry Andric   }
246*700637cbSDimitry Andric 
247*700637cbSDimitry Andric   cxxThisValue = oldThisValue;
248*700637cbSDimitry Andric 
249*700637cbSDimitry Andric   if (classDecl->isDynamicClass()) {
250*700637cbSDimitry Andric     cgm.errorNYI(cd->getSourceRange(),
251*700637cbSDimitry Andric                  "emitCtorPrologue: initialize vtable pointers");
252*700637cbSDimitry Andric     return;
253*700637cbSDimitry Andric   }
254*700637cbSDimitry Andric 
255*700637cbSDimitry Andric   // Finally, initialize class members.
256*700637cbSDimitry Andric   FieldConstructionScope fcs(*this, loadCXXThisAddress());
257*700637cbSDimitry Andric   // Classic codegen uses a special class to attempt to replace member
258*700637cbSDimitry Andric   // initializers with memcpy. We could possibly defer that to the
259*700637cbSDimitry Andric   // lowering or optimization phases to keep the memory accesses more
260*700637cbSDimitry Andric   // explicit. For now, we don't insert memcpy at all.
261*700637cbSDimitry Andric   assert(!cir::MissingFeatures::ctorMemcpyizer());
262*700637cbSDimitry Andric   for (; b != e; b++) {
263*700637cbSDimitry Andric     CXXCtorInitializer *member = (*b);
264*700637cbSDimitry Andric     assert(!member->isBaseInitializer());
265*700637cbSDimitry Andric     assert(member->isAnyMemberInitializer() &&
266*700637cbSDimitry Andric            "Delegating initializer on non-delegating constructor");
267*700637cbSDimitry Andric     emitMemberInitializer(*this, cd->getParent(), member, cd, args);
268*700637cbSDimitry Andric   }
269*700637cbSDimitry Andric }
270*700637cbSDimitry Andric 
loadCXXThisAddress()271*700637cbSDimitry Andric Address CIRGenFunction::loadCXXThisAddress() {
272*700637cbSDimitry Andric   assert(curFuncDecl && "loading 'this' without a func declaration?");
273*700637cbSDimitry Andric   assert(isa<CXXMethodDecl>(curFuncDecl));
274*700637cbSDimitry Andric 
275*700637cbSDimitry Andric   // Lazily compute CXXThisAlignment.
276*700637cbSDimitry Andric   if (cxxThisAlignment.isZero()) {
277*700637cbSDimitry Andric     // Just use the best known alignment for the parent.
278*700637cbSDimitry Andric     // TODO: if we're currently emitting a complete-object ctor/dtor, we can
279*700637cbSDimitry Andric     // always use the complete-object alignment.
280*700637cbSDimitry Andric     auto rd = cast<CXXMethodDecl>(curFuncDecl)->getParent();
281*700637cbSDimitry Andric     cxxThisAlignment = cgm.getClassPointerAlignment(rd);
282*700637cbSDimitry Andric   }
283*700637cbSDimitry Andric 
284*700637cbSDimitry Andric   return Address(loadCXXThis(), cxxThisAlignment);
285*700637cbSDimitry Andric }
286*700637cbSDimitry Andric 
emitInitializerForField(FieldDecl * field,LValue lhs,Expr * init)287*700637cbSDimitry Andric void CIRGenFunction::emitInitializerForField(FieldDecl *field, LValue lhs,
288*700637cbSDimitry Andric                                              Expr *init) {
289*700637cbSDimitry Andric   QualType fieldType = field->getType();
290*700637cbSDimitry Andric   switch (getEvaluationKind(fieldType)) {
291*700637cbSDimitry Andric   case cir::TEK_Scalar:
292*700637cbSDimitry Andric     if (lhs.isSimple())
293*700637cbSDimitry Andric       emitExprAsInit(init, field, lhs, false);
294*700637cbSDimitry Andric     else
295*700637cbSDimitry Andric       cgm.errorNYI(field->getSourceRange(),
296*700637cbSDimitry Andric                    "emitInitializerForField: non-simple scalar");
297*700637cbSDimitry Andric     break;
298*700637cbSDimitry Andric   case cir::TEK_Complex:
299*700637cbSDimitry Andric     cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: complex");
300*700637cbSDimitry Andric     break;
301*700637cbSDimitry Andric   case cir::TEK_Aggregate: {
302*700637cbSDimitry Andric     cgm.errorNYI(field->getSourceRange(), "emitInitializerForField: aggregate");
303*700637cbSDimitry Andric     break;
304*700637cbSDimitry Andric   }
305*700637cbSDimitry Andric   }
306*700637cbSDimitry Andric 
307*700637cbSDimitry Andric   // Ensure that we destroy this object if an exception is thrown later in the
308*700637cbSDimitry Andric   // constructor.
309*700637cbSDimitry Andric   QualType::DestructionKind dtorKind = fieldType.isDestructedType();
310*700637cbSDimitry Andric   (void)dtorKind;
311*700637cbSDimitry Andric   assert(!cir::MissingFeatures::requiresCleanups());
312*700637cbSDimitry Andric }
313*700637cbSDimitry Andric 
emitDelegateCXXConstructorCall(const CXXConstructorDecl * ctor,CXXCtorType ctorType,const FunctionArgList & args,SourceLocation loc)314*700637cbSDimitry Andric void CIRGenFunction::emitDelegateCXXConstructorCall(
315*700637cbSDimitry Andric     const CXXConstructorDecl *ctor, CXXCtorType ctorType,
316*700637cbSDimitry Andric     const FunctionArgList &args, SourceLocation loc) {
317*700637cbSDimitry Andric   CallArgList delegateArgs;
318*700637cbSDimitry Andric 
319*700637cbSDimitry Andric   FunctionArgList::const_iterator i = args.begin(), e = args.end();
320*700637cbSDimitry Andric   assert(i != e && "no parameters to constructor");
321*700637cbSDimitry Andric 
322*700637cbSDimitry Andric   // this
323*700637cbSDimitry Andric   Address thisAddr = loadCXXThisAddress();
324*700637cbSDimitry Andric   delegateArgs.add(RValue::get(thisAddr.getPointer()), (*i)->getType());
325*700637cbSDimitry Andric   ++i;
326*700637cbSDimitry Andric 
327*700637cbSDimitry Andric   // FIXME: The location of the VTT parameter in the parameter list is specific
328*700637cbSDimitry Andric   // to the Itanium ABI and shouldn't be hardcoded here.
329*700637cbSDimitry Andric   if (cgm.getCXXABI().needsVTTParameter(curGD)) {
330*700637cbSDimitry Andric     cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
331*700637cbSDimitry Andric     return;
332*700637cbSDimitry Andric   }
333*700637cbSDimitry Andric 
334*700637cbSDimitry Andric   // Explicit arguments.
335*700637cbSDimitry Andric   for (; i != e; ++i) {
336*700637cbSDimitry Andric     const VarDecl *param = *i;
337*700637cbSDimitry Andric     // FIXME: per-argument source location
338*700637cbSDimitry Andric     emitDelegateCallArg(delegateArgs, param, loc);
339*700637cbSDimitry Andric   }
340*700637cbSDimitry Andric 
341*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
342*700637cbSDimitry Andric 
343*700637cbSDimitry Andric   emitCXXConstructorCall(ctor, ctorType, /*ForVirtualBase=*/false,
344*700637cbSDimitry Andric                          /*Delegating=*/true, thisAddr, delegateArgs, loc);
345*700637cbSDimitry Andric }
346*700637cbSDimitry Andric 
emitImplicitAssignmentOperatorBody(FunctionArgList & args)347*700637cbSDimitry Andric void CIRGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &args) {
348*700637cbSDimitry Andric   const auto *assignOp = cast<CXXMethodDecl>(curGD.getDecl());
349*700637cbSDimitry Andric   assert(assignOp->isCopyAssignmentOperator() ||
350*700637cbSDimitry Andric          assignOp->isMoveAssignmentOperator());
351*700637cbSDimitry Andric   const Stmt *rootS = assignOp->getBody();
352*700637cbSDimitry Andric   assert(isa<CompoundStmt>(rootS) &&
353*700637cbSDimitry Andric          "Body of an implicit assignment operator should be compound stmt.");
354*700637cbSDimitry Andric   const auto *rootCS = cast<CompoundStmt>(rootS);
355*700637cbSDimitry Andric 
356*700637cbSDimitry Andric   assert(!cir::MissingFeatures::incrementProfileCounter());
357*700637cbSDimitry Andric   assert(!cir::MissingFeatures::runCleanupsScope());
358*700637cbSDimitry Andric 
359*700637cbSDimitry Andric   // Classic codegen uses a special class to attempt to replace member
360*700637cbSDimitry Andric   // initializers with memcpy. We could possibly defer that to the
361*700637cbSDimitry Andric   // lowering or optimization phases to keep the memory accesses more
362*700637cbSDimitry Andric   // explicit. For now, we don't insert memcpy at all, though in some
363*700637cbSDimitry Andric   // cases the AST contains a call to memcpy.
364*700637cbSDimitry Andric   assert(!cir::MissingFeatures::assignMemcpyizer());
365*700637cbSDimitry Andric   for (Stmt *s : rootCS->body())
366*700637cbSDimitry Andric     if (emitStmt(s, /*useCurrentScope=*/true).failed())
367*700637cbSDimitry Andric       cgm.errorNYI(s->getSourceRange(),
368*700637cbSDimitry Andric                    std::string("emitImplicitAssignmentOperatorBody: ") +
369*700637cbSDimitry Andric                        s->getStmtClassName());
370*700637cbSDimitry Andric }
371*700637cbSDimitry Andric 
emitDelegatingCXXConstructorCall(const CXXConstructorDecl * ctor,const FunctionArgList & args)372*700637cbSDimitry Andric void CIRGenFunction::emitDelegatingCXXConstructorCall(
373*700637cbSDimitry Andric     const CXXConstructorDecl *ctor, const FunctionArgList &args) {
374*700637cbSDimitry Andric   assert(ctor->isDelegatingConstructor());
375*700637cbSDimitry Andric 
376*700637cbSDimitry Andric   Address thisPtr = loadCXXThisAddress();
377*700637cbSDimitry Andric 
378*700637cbSDimitry Andric   assert(!cir::MissingFeatures::objCGC());
379*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
380*700637cbSDimitry Andric   AggValueSlot aggSlot = AggValueSlot::forAddr(
381*700637cbSDimitry Andric       thisPtr, Qualifiers(), AggValueSlot::IsDestructed,
382*700637cbSDimitry Andric       AggValueSlot::IsNotAliased, AggValueSlot::MayOverlap,
383*700637cbSDimitry Andric       AggValueSlot::IsNotZeroed);
384*700637cbSDimitry Andric 
385*700637cbSDimitry Andric   emitAggExpr(ctor->init_begin()[0]->getInit(), aggSlot);
386*700637cbSDimitry Andric 
387*700637cbSDimitry Andric   const CXXRecordDecl *classDecl = ctor->getParent();
388*700637cbSDimitry Andric   if (cgm.getLangOpts().Exceptions && !classDecl->hasTrivialDestructor()) {
389*700637cbSDimitry Andric     cgm.errorNYI(ctor->getSourceRange(),
390*700637cbSDimitry Andric                  "emitDelegatingCXXConstructorCall: exception");
391*700637cbSDimitry Andric     return;
392*700637cbSDimitry Andric   }
393*700637cbSDimitry Andric }
394*700637cbSDimitry Andric 
getAddressOfBaseClass(Address value,const CXXRecordDecl * derived,llvm::iterator_range<CastExpr::path_const_iterator> path,bool nullCheckValue,SourceLocation loc)395*700637cbSDimitry Andric Address CIRGenFunction::getAddressOfBaseClass(
396*700637cbSDimitry Andric     Address value, const CXXRecordDecl *derived,
397*700637cbSDimitry Andric     llvm::iterator_range<CastExpr::path_const_iterator> path,
398*700637cbSDimitry Andric     bool nullCheckValue, SourceLocation loc) {
399*700637cbSDimitry Andric   assert(!path.empty() && "Base path should not be empty!");
400*700637cbSDimitry Andric 
401*700637cbSDimitry Andric   if ((*path.begin())->isVirtual()) {
402*700637cbSDimitry Andric     // The implementation here is actually complete, but let's flag this
403*700637cbSDimitry Andric     // as an error until the rest of the virtual base class support is in place.
404*700637cbSDimitry Andric     cgm.errorNYI(loc, "getAddrOfBaseClass: virtual base");
405*700637cbSDimitry Andric     return Address::invalid();
406*700637cbSDimitry Andric   }
407*700637cbSDimitry Andric 
408*700637cbSDimitry Andric   // Compute the static offset of the ultimate destination within its
409*700637cbSDimitry Andric   // allocating subobject (the virtual base, if there is one, or else
410*700637cbSDimitry Andric   // the "complete" object that we see).
411*700637cbSDimitry Andric   CharUnits nonVirtualOffset =
412*700637cbSDimitry Andric       cgm.computeNonVirtualBaseClassOffset(derived, path);
413*700637cbSDimitry Andric 
414*700637cbSDimitry Andric   // Get the base pointer type.
415*700637cbSDimitry Andric   mlir::Type baseValueTy = convertType((path.end()[-1])->getType());
416*700637cbSDimitry Andric   assert(!cir::MissingFeatures::addressSpace());
417*700637cbSDimitry Andric 
418*700637cbSDimitry Andric   // The if statement here is redundant now, but it will be needed when we add
419*700637cbSDimitry Andric   // support for virtual base classes.
420*700637cbSDimitry Andric   // If there is no virtual base, use cir.base_class_addr.  It takes care of
421*700637cbSDimitry Andric   // the adjustment and the null pointer check.
422*700637cbSDimitry Andric   if (nonVirtualOffset.isZero()) {
423*700637cbSDimitry Andric     assert(!cir::MissingFeatures::sanitizers());
424*700637cbSDimitry Andric     return builder.createBaseClassAddr(getLoc(loc), value, baseValueTy, 0,
425*700637cbSDimitry Andric                                        /*assumeNotNull=*/true);
426*700637cbSDimitry Andric   }
427*700637cbSDimitry Andric 
428*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
429*700637cbSDimitry Andric 
430*700637cbSDimitry Andric   // Apply the offset
431*700637cbSDimitry Andric   value = builder.createBaseClassAddr(getLoc(loc), value, baseValueTy,
432*700637cbSDimitry Andric                                       nonVirtualOffset.getQuantity(),
433*700637cbSDimitry Andric                                       /*assumeNotNull=*/true);
434*700637cbSDimitry Andric 
435*700637cbSDimitry Andric   // Cast to the destination type.
436*700637cbSDimitry Andric   value = value.withElementType(builder, baseValueTy);
437*700637cbSDimitry Andric 
438*700637cbSDimitry Andric   return value;
439*700637cbSDimitry Andric }
440*700637cbSDimitry Andric 
emitCXXConstructorCall(const clang::CXXConstructorDecl * d,clang::CXXCtorType type,bool forVirtualBase,bool delegating,AggValueSlot thisAVS,const clang::CXXConstructExpr * e)441*700637cbSDimitry Andric void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
442*700637cbSDimitry Andric                                             clang::CXXCtorType type,
443*700637cbSDimitry Andric                                             bool forVirtualBase,
444*700637cbSDimitry Andric                                             bool delegating,
445*700637cbSDimitry Andric                                             AggValueSlot thisAVS,
446*700637cbSDimitry Andric                                             const clang::CXXConstructExpr *e) {
447*700637cbSDimitry Andric   CallArgList args;
448*700637cbSDimitry Andric   Address thisAddr = thisAVS.getAddress();
449*700637cbSDimitry Andric   QualType thisType = d->getThisType();
450*700637cbSDimitry Andric   mlir::Value thisPtr = thisAddr.getPointer();
451*700637cbSDimitry Andric 
452*700637cbSDimitry Andric   assert(!cir::MissingFeatures::addressSpace());
453*700637cbSDimitry Andric 
454*700637cbSDimitry Andric   args.add(RValue::get(thisPtr), thisType);
455*700637cbSDimitry Andric 
456*700637cbSDimitry Andric   // In LLVM Codegen: If this is a trivial constructor, just emit what's needed.
457*700637cbSDimitry Andric   // If this is a union copy constructor, we must emit a memcpy, because the AST
458*700637cbSDimitry Andric   // does not model that copy.
459*700637cbSDimitry Andric   assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
460*700637cbSDimitry Andric 
461*700637cbSDimitry Andric   const FunctionProtoType *fpt = d->getType()->castAs<FunctionProtoType>();
462*700637cbSDimitry Andric 
463*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
464*700637cbSDimitry Andric 
465*700637cbSDimitry Andric   emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
466*700637cbSDimitry Andric                /*ParamsToSkip=*/0);
467*700637cbSDimitry Andric 
468*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
469*700637cbSDimitry Andric   emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
470*700637cbSDimitry Andric                          e->getExprLoc());
471*700637cbSDimitry Andric }
472*700637cbSDimitry Andric 
emitCXXConstructorCall(const CXXConstructorDecl * d,CXXCtorType type,bool forVirtualBase,bool delegating,Address thisAddr,CallArgList & args,SourceLocation loc)473*700637cbSDimitry Andric void CIRGenFunction::emitCXXConstructorCall(
474*700637cbSDimitry Andric     const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
475*700637cbSDimitry Andric     bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
476*700637cbSDimitry Andric 
477*700637cbSDimitry Andric   const CXXRecordDecl *crd = d->getParent();
478*700637cbSDimitry Andric 
479*700637cbSDimitry Andric   // If this is a call to a trivial default constructor:
480*700637cbSDimitry Andric   // In LLVM: do nothing.
481*700637cbSDimitry Andric   // In CIR: emit as a regular call, other later passes should lower the
482*700637cbSDimitry Andric   // ctor call into trivial initialization.
483*700637cbSDimitry Andric   assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
484*700637cbSDimitry Andric 
485*700637cbSDimitry Andric   assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
486*700637cbSDimitry Andric 
487*700637cbSDimitry Andric   bool passPrototypeArgs = true;
488*700637cbSDimitry Andric 
489*700637cbSDimitry Andric   // Check whether we can actually emit the constructor before trying to do so.
490*700637cbSDimitry Andric   if (d->getInheritedConstructor()) {
491*700637cbSDimitry Andric     cgm.errorNYI(d->getSourceRange(),
492*700637cbSDimitry Andric                  "emitCXXConstructorCall: inherited constructor");
493*700637cbSDimitry Andric     return;
494*700637cbSDimitry Andric   }
495*700637cbSDimitry Andric 
496*700637cbSDimitry Andric   // Insert any ABI-specific implicit constructor arguments.
497*700637cbSDimitry Andric   assert(!cir::MissingFeatures::implicitConstructorArgs());
498*700637cbSDimitry Andric 
499*700637cbSDimitry Andric   // Emit the call.
500*700637cbSDimitry Andric   auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
501*700637cbSDimitry Andric   const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
502*700637cbSDimitry Andric       args, d, type, passPrototypeArgs);
503*700637cbSDimitry Andric   CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, type));
504*700637cbSDimitry Andric   cir::CIRCallOpInterface c;
505*700637cbSDimitry Andric   emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
506*700637cbSDimitry Andric 
507*700637cbSDimitry Andric   if (cgm.getCodeGenOpts().OptimizationLevel != 0 && !crd->isDynamicClass() &&
508*700637cbSDimitry Andric       type != Ctor_Base && cgm.getCodeGenOpts().StrictVTablePointers)
509*700637cbSDimitry Andric     cgm.errorNYI(d->getSourceRange(), "vtable assumption loads");
510*700637cbSDimitry Andric }
511