================
@@ -53,19 +53,135 @@ bool CIRGenFunction::isConstructorDelegationValid(
   return true;
 }
 
+static void emitLValueForAnyFieldInitialization(CIRGenFunction &cgf,
+                                                CXXCtorInitializer *memberInit,
+                                                LValue &lhs) {
+  FieldDecl *field = memberInit->getAnyMember();
+  if (memberInit->isIndirectMemberInitializer()) {
+    // If we are initializing an anonymous union field, drill down to the 
field.
+    IndirectFieldDecl *indirectField = memberInit->getIndirectMember();
+    for (const auto *nd : indirectField->chain()) {
+      auto *fd = cast<clang::FieldDecl>(nd);
+      lhs = cgf.emitLValueForFieldInitialization(lhs, fd, fd->getName());
+    }
+  } else {
+    lhs = cgf.emitLValueForFieldInitialization(lhs, field, field->getName());
+  }
+}
+
+static void emitMemberInitializer(CIRGenFunction &cgf,
+                                  const CXXRecordDecl *classDecl,
+                                  CXXCtorInitializer *memberInit,
+                                  const CXXConstructorDecl *constructor,
+                                  FunctionArgList &args) {
+  assert(memberInit->isAnyMemberInitializer() &&
+         "Mush have member initializer!");
+  assert(memberInit->getInit() && "Must have initializer!");
+
+  assert(!cir::MissingFeatures::generateDebugInfo());
+
+  // non-static data member initializers
+  FieldDecl *field = memberInit->getAnyMember();
+  QualType fieldType = field->getType();
+
+  mlir::Value thisPtr = cgf.loadCXXThis();
+  QualType recordTy = cgf.getContext().getTypeDeclType(classDecl);
+  LValue lhs;
+
+  // If a base constructor is being emitted, create an LValue that has the
+  // non-virtual alignment.
+  if (cgf.curGD.getCtorType() == Ctor_Base)
+    lhs = cgf.makeNaturalAlignPointeeAddrLValue(thisPtr, recordTy);
+  else
+    lhs = cgf.makeNaturalAlignAddrLValue(thisPtr, recordTy);
+
+  emitLValueForAnyFieldInitialization(cgf, memberInit, lhs);
+
+  // Special case: If we are in a copy or move constructor, and we are copying
+  // an array off PODs or classes with tirival copy constructors, ignore the 
AST
+  // and perform the copy we know is equivalent.
+  // FIXME: This is hacky at best... if we had a bit more explicit information
+  // in the AST, we could generalize it more easily.
+  const ConstantArrayType *array =
+      cgf.getContext().getAsConstantArrayType(fieldType);
+  if (array && constructor->isDefaulted() &&
+      constructor->isCopyOrMoveConstructor()) {
+    QualType baseElementTy = cgf.getContext().getBaseElementType(array);
+    // NOTE(cir): CodeGen allows record types to be memcpy'd if applicable,
+    // whereas ClangIR wants to represent all object construction explicitly.
+    if (!baseElementTy->isRecordType()) {
+      cgf.cgm.errorNYI(memberInit->getSourceRange(),
+                       "emitMemberInitializer: array of non-record type");
+      return;
+    }
+  }
+
+  cgf.emitInitializerForField(field, lhs, memberInit->getInit());
+}
+
 /// This routine generates necessary code to initialize base classes and
 /// non-static data members belonging to this constructor.
 void CIRGenFunction::emitCtorPrologue(const CXXConstructorDecl *cd,
                                       CXXCtorType ctorType,
                                       FunctionArgList &args) {
-  if (cd->isDelegatingConstructor())
-    return emitDelegatingCXXConstructorCall(cd, args);
+  if (cd->isDelegatingConstructor()) {
+    emitDelegatingCXXConstructorCall(cd, args);
+    return;
+  }
+
+  // If there are no member initializers, we can just return.
+  if (cd->getNumCtorInitializers() == 0)
+    return;
 
-  if (cd->getNumCtorInitializers() != 0) {
-    // There's much more to do here.
-    cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: any initializer");
+  const CXXRecordDecl *classDecl = cd->getParent();
+
+  // This code doesn't use range-based iteration because we may need to emit
+  // code between the virtual base initializers and the non-virtual base or
+  // between the non-virtual base initializers and the member initializers.
+  CXXConstructorDecl::init_const_iterator b = cd->init_begin(),
+                                          e = cd->init_end();
+
+  // Virtual base initializers first, if any. They aren't needed if:
+  // - This is a base ctor variant
+  // - There are no vbases
+  // - The class is abstract, so a complete object of it cannot be constructed
+  //
+  // The check for an abstract class is necessary because sema may not have
+  // marked virtual base destructors referenced.
+  bool constructVBases = ctorType != Ctor_Base &&
+                         classDecl->getNumVBases() != 0 &&
+                         !classDecl->isAbstract();
+  if (constructVBases) {
+    cgm.errorNYI(cd->getSourceRange(), "emitCtorPrologue: virtual base");
     return;
   }
+
+  if ((*b)->isBaseInitializer()) {
+    cgm.errorNYI(cd->getSourceRange(),
+                 "emitCtorPrologue: non-virtual base initializer");
+    return;
+  }
+
+  if (classDecl->isDynamicClass()) {
+    cgm.errorNYI(cd->getSourceRange(),
+                 "emitCtorPrologue: initialize vtable pointers");
+    return;
+  }
+
+  // Finally, initialize class members.
+  FieldConstructionScope fcs(*this, loadCXXThisAddress());
+  // Classic codegen uses a special class to attempt to replace member
+  // initializers with memcpy. We could possibly defer that to the
+  // lowering or optimization phases to keep the memory accesses more
+  // explicit. For now, we don't insert memcpy at all.
+  assert(!cir::MissingFeatures::ctorMemcpyizer());
----------------
bcardosolopes wrote:

nice!

https://github.com/llvm/llvm-project/pull/144583
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to