@@ -53,19 +53,133 @@ bool CIRGenFunction::isConstructorDelegationValid(
5353 return true ;
5454}
5555
56+ static void emitLValueForAnyFieldInitialization (CIRGenFunction &cgf,
57+ CXXCtorInitializer *memberInit,
58+ LValue &lhs) {
59+ FieldDecl *field = memberInit->getAnyMember ();
60+ if (memberInit->isIndirectMemberInitializer ()) {
61+ // If we are initializing an anonymous union field, drill down to the field.
62+ IndirectFieldDecl *indirectField = memberInit->getIndirectMember ();
63+ for (const auto *nd : indirectField->chain ()) {
64+ auto *fd = cast<clang::FieldDecl>(nd);
65+ lhs = cgf.emitLValueForFieldInitialization (lhs, fd, fd->getName ());
66+ }
67+ } else {
68+ lhs = cgf.emitLValueForFieldInitialization (lhs, field, field->getName ());
69+ }
70+ }
71+
72+ static void emitMemberInitializer (CIRGenFunction &cgf,
73+ const CXXRecordDecl *classDecl,
74+ CXXCtorInitializer *memberInit,
75+ const CXXConstructorDecl *constructor,
76+ FunctionArgList &args) {
77+ assert (memberInit->isAnyMemberInitializer () &&
78+ " Mush have member initializer!" );
79+ assert (memberInit->getInit () && " Must have initializer!" );
80+
81+ assert (!cir::MissingFeatures::generateDebugInfo ());
82+
83+ // non-static data member initializers
84+ FieldDecl *field = memberInit->getAnyMember ();
85+ QualType fieldType = field->getType ();
86+
87+ mlir::Value thisPtr = cgf.loadCXXThis ();
88+ QualType recordTy = cgf.getContext ().getTypeDeclType (classDecl);
89+
90+ // If a base constructor is being emitted, create an LValue that has the
91+ // non-virtual alignment.
92+ LValue lhs = (cgf.curGD .getCtorType () == Ctor_Base)
93+ ? cgf.makeNaturalAlignPointeeAddrLValue (thisPtr, recordTy)
94+ : cgf.makeNaturalAlignAddrLValue (thisPtr, recordTy);
95+
96+ emitLValueForAnyFieldInitialization (cgf, memberInit, lhs);
97+
98+ // Special case: If we are in a copy or move constructor, and we are copying
99+ // an array off PODs or classes with trivial copy constructors, ignore the AST
100+ // and perform the copy we know is equivalent.
101+ // FIXME: This is hacky at best... if we had a bit more explicit information
102+ // in the AST, we could generalize it more easily.
103+ const ConstantArrayType *array =
104+ cgf.getContext ().getAsConstantArrayType (fieldType);
105+ if (array && constructor->isDefaulted () &&
106+ constructor->isCopyOrMoveConstructor ()) {
107+ QualType baseElementTy = cgf.getContext ().getBaseElementType (array);
108+ // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
109+ // whereas ClangIR wants to represent all object construction explicitly.
110+ if (!baseElementTy->isRecordType ()) {
111+ cgf.cgm .errorNYI (memberInit->getSourceRange (),
112+ " emitMemberInitializer: array of non-record type" );
113+ return ;
114+ }
115+ }
116+
117+ cgf.emitInitializerForField (field, lhs, memberInit->getInit ());
118+ }
119+
56120// / This routine generates necessary code to initialize base classes and
57121// / non-static data members belonging to this constructor.
58122void CIRGenFunction::emitCtorPrologue (const CXXConstructorDecl *cd,
59123 CXXCtorType ctorType,
60124 FunctionArgList &args) {
61- if (cd->isDelegatingConstructor ())
62- return emitDelegatingCXXConstructorCall (cd, args);
125+ if (cd->isDelegatingConstructor ()) {
126+ emitDelegatingCXXConstructorCall (cd, args);
127+ return ;
128+ }
129+
130+ // If there are no member initializers, we can just return.
131+ if (cd->getNumCtorInitializers () == 0 )
132+ return ;
63133
64- if (cd->getNumCtorInitializers () != 0 ) {
65- // There's much more to do here.
66- cgm.errorNYI (cd->getSourceRange (), " emitCtorPrologue: any initializer" );
134+ const CXXRecordDecl *classDecl = cd->getParent ();
135+
136+ // This code doesn't use range-based iteration because we may need to emit
137+ // code between the virtual base initializers and the non-virtual base or
138+ // between the non-virtual base initializers and the member initializers.
139+ CXXConstructorDecl::init_const_iterator b = cd->init_begin (),
140+ e = cd->init_end ();
141+
142+ // Virtual base initializers first, if any. They aren't needed if:
143+ // - This is a base ctor variant
144+ // - There are no vbases
145+ // - The class is abstract, so a complete object of it cannot be constructed
146+ //
147+ // The check for an abstract class is necessary because sema may not have
148+ // marked virtual base destructors referenced.
149+ bool constructVBases = ctorType != Ctor_Base &&
150+ classDecl->getNumVBases () != 0 &&
151+ !classDecl->isAbstract ();
152+ if (constructVBases) {
153+ cgm.errorNYI (cd->getSourceRange (), " emitCtorPrologue: virtual base" );
67154 return ;
68155 }
156+
157+ if ((*b)->isBaseInitializer ()) {
158+ cgm.errorNYI (cd->getSourceRange (),
159+ " emitCtorPrologue: non-virtual base initializer" );
160+ return ;
161+ }
162+
163+ if (classDecl->isDynamicClass ()) {
164+ cgm.errorNYI (cd->getSourceRange (),
165+ " emitCtorPrologue: initialize vtable pointers" );
166+ return ;
167+ }
168+
169+ // Finally, initialize class members.
170+ FieldConstructionScope fcs (*this , loadCXXThisAddress ());
171+ // Classic codegen uses a special class to attempt to replace member
172+ // initializers with memcpy. We could possibly defer that to the
173+ // lowering or optimization phases to keep the memory accesses more
174+ // explicit. For now, we don't insert memcpy at all.
175+ assert (!cir::MissingFeatures::ctorMemcpyizer ());
176+ for (; b != e; b++) {
177+ CXXCtorInitializer *member = (*b);
178+ assert (!member->isBaseInitializer ());
179+ assert (member->isAnyMemberInitializer () &&
180+ " Delegating initializer on non-delegating constructor" );
181+ emitMemberInitializer (*this , cd->getParent (), member, cd, args);
182+ }
69183}
70184
71185Address CIRGenFunction::loadCXXThisAddress () {
@@ -84,6 +198,33 @@ Address CIRGenFunction::loadCXXThisAddress() {
84198 return Address (loadCXXThis (), cxxThisAlignment);
85199}
86200
201+ void CIRGenFunction::emitInitializerForField (FieldDecl *field, LValue lhs,
202+ Expr *init) {
203+ QualType fieldType = field->getType ();
204+ switch (getEvaluationKind (fieldType)) {
205+ case cir::TEK_Scalar:
206+ if (lhs.isSimple ())
207+ emitExprAsInit (init, field, lhs, false );
208+ else
209+ cgm.errorNYI (field->getSourceRange (),
210+ " emitInitializerForField: non-simple scalar" );
211+ break ;
212+ case cir::TEK_Complex:
213+ cgm.errorNYI (field->getSourceRange (), " emitInitializerForField: complex" );
214+ break ;
215+ case cir::TEK_Aggregate: {
216+ cgm.errorNYI (field->getSourceRange (), " emitInitializerForField: aggregate" );
217+ break ;
218+ }
219+ }
220+
221+ // Ensure that we destroy this object if an exception is thrown later in the
222+ // constructor.
223+ QualType::DestructionKind dtorKind = fieldType.isDestructedType ();
224+ (void )dtorKind;
225+ assert (!cir::MissingFeatures::requiresCleanups ());
226+ }
227+
87228void CIRGenFunction::emitDelegateCXXConstructorCall (
88229 const CXXConstructorDecl *ctor, CXXCtorType ctorType,
89230 const FunctionArgList &args, SourceLocation loc) {
0 commit comments