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