[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor closed 
https://github.com/llvm/llvm-project/pull/143579
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/143579

>From 844b07e53937d3496405fd2c58148bd03c1f7407 Mon Sep 17 00:00:00 2001
From: Andy Kaylor 
Date: Mon, 9 Jun 2025 09:38:55 -0700
Subject: [PATCH 1/3] [CIR] Upstream support for calling constructors

This change adds support for calling C++ constructors. The support for
actually defining a constructor is still missing and will be added in
a later change.
---
 clang/include/clang/CIR/MissingFeatures.h |  3 +
 clang/lib/CIR/CodeGen/CIRGenCall.cpp  | 99 +--
 clang/lib/CIR/CodeGen/CIRGenClass.cpp | 74 ++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  | 51 ++
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |  6 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h| 13 +++
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 54 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  | 19 
 clang/lib/CIR/CodeGen/CIRGenTypes.h   |  6 ++
 clang/test/CIR/CodeGen/ctor.cpp   | 19 
 10 files changed, 336 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/ctor.cpp

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..f89d386378e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -222,6 +222,9 @@ struct MissingFeatures {
   static bool instrumentation() { return false; }
   static bool cleanupAfterErrorDiags() { return false; }
   static bool cxxRecordStaticMembers() { return false; }
+  static bool isMemcpyEquivalentSpecialMember() { return false; }
+  static bool isTrivialCtorOrDtor() { return false; }
+  static bool implicitConstructorArgs() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..9d25eea9e413d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,13 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   return *this;
 }
 
+/// Returns the canonical formal type of the given C++ method.
+static CanQual getFormalType(const CXXMethodDecl *md) {
+  return md->getType()
+  ->getCanonicalTypeUnqualified()
+  .getAs();
+}
+
 /// Adds the formal parameters in FPT to the given prefix. If any parameter in
 /// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
 /// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;
+
+  if (auto *cd = dyn_cast(md)) {
+// A base class inheriting constructor doesn't get forwarded arguments
+// needed to construct a virtual base (or base class thereof)
+if (cd->getInheritedConstructor())
+  cgm.errorNYI(cd->getSourceRange(),
+   "arrangeCXXStructorDeclaration: inheriting constructor");
+  }
+
+  CanQual fpt = getFormalType(md);
+
+  if (passParams)
+appendParameterTypes(*this, argTypes, fpt);
+
+  assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+  RequiredArgs required =
+  (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+  : RequiredArgs::All);
+
+  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+   : theCXXABI.hasMostDerivedReturn(gd)
+   ? astContext.VoidPtrTy
+   : astContext.VoidTy;
+
+  assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
 /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
 /// qualification. Either or both of `rd` and `md` may be null. A null `rd`
 /// indicates that there is no meaningful 'this' type, and a null `md` can 
occur
@@ -103,13 +152,13 @@ CanQualType CIRGenTypes::deriveThisType(const 
CXXRecordDecl *rd,
 /// top of any implicit parameters already stored.
 static const CIRGenFunctionInfo &
 arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl &prefix,
-   CanQual ftp) {
+   CanQual fpt) {
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   RequiredArgs required =
-  RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
+  RequiredArgs::getFromProtoWithExtraSlots(f

[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits


@@ -1393,6 +1393,57 @@ RValue CIRGenFunction::emitCXXMemberCallExpr(const 
CXXMemberCallExpr *ce,
   ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
 }
 
+void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,
+  AggValueSlot dest) {
+  assert(!dest.isIgnored() && "Must have a destination!");
+  const CXXConstructorDecl *cd = e->getConstructor();
+
+  // If we require zero initialization before (or instead of) calling the
+  // constructor, as can be the case with a non-user-provided default
+  // constructor, emit the zero initialization now, unless destination is
+  // already zeroed.
+  if (e->requiresZeroInitialization() && !dest.isZeroed()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: requires initialization");
+return;
+  }
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+
+  // Elide the constructor if we're constructing from a temporary
+  if (getLangOpts().ElideConstructors && e->isElidable()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: elidable constructor");
+return;
+  }
+
+  if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
+cgm.errorNYI(e->getSourceRange(), "emitCXXConstructExpr: array type");
+return;
+  } else {
+clang::CXXCtorType type = Ctor_Complete;

andykaylor wrote:

That's just a clang-tidy warning, right? 

I was going to say that I'd prefer not to restructure the code that way since 
the missing code represented by the errorNYI doesn't return in the incubator, 
but I just looked again, and there is no reason that it couldn't return and 
that would save a level of indenting on the rest of the code, so I'll go ahead 
with the suggested change.

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Amr Hesham via cfe-commits


@@ -1393,6 +1393,57 @@ RValue CIRGenFunction::emitCXXMemberCallExpr(const 
CXXMemberCallExpr *ce,
   ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
 }
 
+void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,
+  AggValueSlot dest) {
+  assert(!dest.isIgnored() && "Must have a destination!");
+  const CXXConstructorDecl *cd = e->getConstructor();
+
+  // If we require zero initialization before (or instead of) calling the
+  // constructor, as can be the case with a non-user-provided default
+  // constructor, emit the zero initialization now, unless destination is
+  // already zeroed.
+  if (e->requiresZeroInitialization() && !dest.isZeroed()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: requires initialization");
+return;
+  }
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+
+  // Elide the constructor if we're constructing from a temporary
+  if (getLangOpts().ElideConstructors && e->isElidable()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: elidable constructor");
+return;
+  }
+
+  if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {

AmrDeveloper wrote:

NIT: `arrayType` variable will be unused

I think it can be

```
if (getContext().getAsArrayType(e->getType()))
```

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Amr Hesham via cfe-commits

https://github.com/AmrDeveloper edited 
https://github.com/llvm/llvm-project/pull/143579
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Amr Hesham via cfe-commits

https://github.com/AmrDeveloper approved this pull request.


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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Amr Hesham via cfe-commits


@@ -1393,6 +1393,57 @@ RValue CIRGenFunction::emitCXXMemberCallExpr(const 
CXXMemberCallExpr *ce,
   ce, md, returnValue, hasQualifier, qualifier, isArrow, base);
 }
 
+void CIRGenFunction::emitCXXConstructExpr(const CXXConstructExpr *e,
+  AggValueSlot dest) {
+  assert(!dest.isIgnored() && "Must have a destination!");
+  const CXXConstructorDecl *cd = e->getConstructor();
+
+  // If we require zero initialization before (or instead of) calling the
+  // constructor, as can be the case with a non-user-provided default
+  // constructor, emit the zero initialization now, unless destination is
+  // already zeroed.
+  if (e->requiresZeroInitialization() && !dest.isZeroed()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: requires initialization");
+return;
+  }
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+
+  // Elide the constructor if we're constructing from a temporary
+  if (getLangOpts().ElideConstructors && e->isElidable()) {
+cgm.errorNYI(e->getSourceRange(),
+ "emitCXXConstructExpr: elidable constructor");
+return;
+  }
+
+  if (const ArrayType *arrayType = getContext().getAsArrayType(e->getType())) {
+cgm.errorNYI(e->getSourceRange(), "emitCXXConstructExpr: array type");
+return;
+  } else {
+clang::CXXCtorType type = Ctor_Complete;

AmrDeveloper wrote:

NIT: To eliminate “Do not use else after return” warning, should we remove the 
else branch?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor updated 
https://github.com/llvm/llvm-project/pull/143579

>From 844b07e53937d3496405fd2c58148bd03c1f7407 Mon Sep 17 00:00:00 2001
From: Andy Kaylor 
Date: Mon, 9 Jun 2025 09:38:55 -0700
Subject: [PATCH 1/2] [CIR] Upstream support for calling constructors

This change adds support for calling C++ constructors. The support for
actually defining a constructor is still missing and will be added in
a later change.
---
 clang/include/clang/CIR/MissingFeatures.h |  3 +
 clang/lib/CIR/CodeGen/CIRGenCall.cpp  | 99 +--
 clang/lib/CIR/CodeGen/CIRGenClass.cpp | 74 ++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  | 51 ++
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |  6 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h| 13 +++
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 54 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  | 19 
 clang/lib/CIR/CodeGen/CIRGenTypes.h   |  6 ++
 clang/test/CIR/CodeGen/ctor.cpp   | 19 
 10 files changed, 336 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/ctor.cpp

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..f89d386378e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -222,6 +222,9 @@ struct MissingFeatures {
   static bool instrumentation() { return false; }
   static bool cleanupAfterErrorDiags() { return false; }
   static bool cxxRecordStaticMembers() { return false; }
+  static bool isMemcpyEquivalentSpecialMember() { return false; }
+  static bool isTrivialCtorOrDtor() { return false; }
+  static bool implicitConstructorArgs() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..9d25eea9e413d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,13 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   return *this;
 }
 
+/// Returns the canonical formal type of the given C++ method.
+static CanQual getFormalType(const CXXMethodDecl *md) {
+  return md->getType()
+  ->getCanonicalTypeUnqualified()
+  .getAs();
+}
+
 /// Adds the formal parameters in FPT to the given prefix. If any parameter in
 /// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
 /// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;
+
+  if (auto *cd = dyn_cast(md)) {
+// A base class inheriting constructor doesn't get forwarded arguments
+// needed to construct a virtual base (or base class thereof)
+if (cd->getInheritedConstructor())
+  cgm.errorNYI(cd->getSourceRange(),
+   "arrangeCXXStructorDeclaration: inheriting constructor");
+  }
+
+  CanQual fpt = getFormalType(md);
+
+  if (passParams)
+appendParameterTypes(*this, argTypes, fpt);
+
+  assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+  RequiredArgs required =
+  (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+  : RequiredArgs::All);
+
+  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+   : theCXXABI.hasMostDerivedReturn(gd)
+   ? astContext.VoidPtrTy
+   : astContext.VoidTy;
+
+  assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
 /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
 /// qualification. Either or both of `rd` and `md` may be null. A null `rd`
 /// indicates that there is no meaningful 'this' type, and a null `md` can 
occur
@@ -103,13 +152,13 @@ CanQualType CIRGenTypes::deriveThisType(const 
CXXRecordDecl *rd,
 /// top of any implicit parameters already stored.
 static const CIRGenFunctionInfo &
 arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl &prefix,
-   CanQual ftp) {
+   CanQual fpt) {
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   RequiredArgs required =
-  RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
+  RequiredArgs::getFromProtoWithExtraSlots(f

[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -63,3 +66,74 @@ Address CIRGenFunction::getAddressOfBaseClass(
 
   return value;
 }
+
+void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+clang::CXXCtorType type,
+bool forVirtualBase,
+bool delegating,
+AggValueSlot thisAVS,
+const clang::CXXConstructExpr *e) {
+  CallArgList args;
+  Address thisAddr = thisAVS.getAddress();
+  QualType thisType = d->getThisType();
+  mlir::Value thisPtr = thisAddr.getPointer();
+
+  assert(!cir::MissingFeatures::addressSpace());
+
+  args.add(RValue::get(thisPtr), thisType);
+
+  // In LLVM Codegen: If this is a trivial constructor, just emit what's 
needed.
+  // If this is a union copy constructor, we must emit a memcpy, because the 
AST
+  // does not model that copy.
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  const FunctionProtoType *fpt = d->getType()->castAs();
+
+  assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
+
+  emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+   /*ParamsToSkip=*/0);
+
+  assert(!cir::MissingFeatures::sanitizers());
+  emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
+ e->getExprLoc());
+}
+
+void CIRGenFunction::emitCXXConstructorCall(
+const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
+bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
+
+  const auto *cd = d->getParent();
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+  assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
+
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  bool passPrototypeArgs = true;

erichkeane wrote:

Can we set this anyway?  Alternatively, just set it to 
`!d->getInheritedConstructor`?   Its at least easier here, since we don't need 
a cast to get the info we need.

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -141,6 +190,44 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
 }
 
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// passProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
+const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
+bool passProtoArgs) {
+
+  // FIXME: Kill copy.

erichkeane wrote:

Ah... Its kind of frustrating to see these FIXME's last as long as they do, 
then get propagated into the new lowering like this.  I guess I can live with 
it (as we have for years), but we gotta stop letting these FIXMEs last as long 
as they do:/

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;

erichkeane wrote:

Ah, hrmph... Can we set it there ANYWAY, despite doing an NYI?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits


@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;

andykaylor wrote:

It will be set to false by the code that is missing on line 99.

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits


@@ -63,3 +66,74 @@ Address CIRGenFunction::getAddressOfBaseClass(
 
   return value;
 }
+
+void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+clang::CXXCtorType type,
+bool forVirtualBase,
+bool delegating,
+AggValueSlot thisAVS,
+const clang::CXXConstructExpr *e) {
+  CallArgList args;
+  Address thisAddr = thisAVS.getAddress();
+  QualType thisType = d->getThisType();
+  mlir::Value thisPtr = thisAddr.getPointer();
+
+  assert(!cir::MissingFeatures::addressSpace());
+
+  args.add(RValue::get(thisPtr), thisType);
+
+  // In LLVM Codegen: If this is a trivial constructor, just emit what's 
needed.
+  // If this is a union copy constructor, we must emit a memcpy, because the 
AST
+  // does not model that copy.
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  const FunctionProtoType *fpt = d->getType()->castAs();
+
+  assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
+
+  emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+   /*ParamsToSkip=*/0);
+
+  assert(!cir::MissingFeatures::sanitizers());
+  emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
+ e->getExprLoc());
+}
+
+void CIRGenFunction::emitCXXConstructorCall(
+const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
+bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
+
+  const auto *cd = d->getParent();
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+  assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
+
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  bool passPrototypeArgs = true;

andykaylor wrote:

This will be set by the missing code on line 120.

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits


@@ -141,6 +190,44 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
 }
 
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// passProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
+const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
+bool passProtoArgs) {
+
+  // FIXME: Kill copy.

andykaylor wrote:

This is one of those comments that was brought over from classic codegen. It 
appears six times in both classic codegen and the CIR incubator codegen, always 
in conjunction with a call to arrangeLLVMFunctionInfo/arrangeCIRFunctionInfo. 
The problem is that one of the places it occurs (the static version of 
arrangeLLVMFunctionInfo/arrangeCIRFunctionInfo) takes a list of types from the 
caller but then appends additional types based on 
FunctionProtoType::getExtParameterInfos().

I definitely want to leave it alone for now. It may be a solvable problem, but 
the priority of solving it appears to be very low.

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -63,3 +66,74 @@ Address CIRGenFunction::getAddressOfBaseClass(
 
   return value;
 }
+
+void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+clang::CXXCtorType type,
+bool forVirtualBase,
+bool delegating,
+AggValueSlot thisAVS,
+const clang::CXXConstructExpr *e) {
+  CallArgList args;
+  Address thisAddr = thisAVS.getAddress();
+  QualType thisType = d->getThisType();
+  mlir::Value thisPtr = thisAddr.getPointer();
+
+  assert(!cir::MissingFeatures::addressSpace());
+
+  args.add(RValue::get(thisPtr), thisType);
+
+  // In LLVM Codegen: If this is a trivial constructor, just emit what's 
needed.
+  // If this is a union copy constructor, we must emit a memcpy, because the 
AST
+  // does not model that copy.
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  const FunctionProtoType *fpt = d->getType()->castAs();
+
+  assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
+
+  emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+   /*ParamsToSkip=*/0);
+
+  assert(!cir::MissingFeatures::sanitizers());
+  emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
+ e->getExprLoc());
+}
+
+void CIRGenFunction::emitCXXConstructorCall(
+const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
+bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
+
+  const auto *cd = d->getParent();
+
+  // If this is a call to a trivial default constructor:
+  // In LLVM: do nothing.
+  // In CIR: emit as a regular call, other later passes should lower the
+  // ctor call into trivial initialization.
+  assert(!cir::MissingFeatures::isTrivialCtorOrDtor());
+
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  bool passPrototypeArgs = true;

erichkeane wrote:

Read, but never set?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -141,6 +190,44 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, CIRGenModule 
&cgm,
   return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
 }
 
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// passProtoArgs indicates whether `args` has args for the parameters in the
+/// given CXXConstructorDecl.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXConstructorCall(
+const CallArgList &args, const CXXConstructorDecl *d, CXXCtorType ctorKind,
+bool passProtoArgs) {
+
+  // FIXME: Kill copy.

erichkeane wrote:

The only idea I have for us to do something like this, would be to have 
`arrangeCIRFunctionInfo` to have a optional `arg-transform` function.  So it 
becomes:

`arrangeCIRFunctionInfo(resultType, argTypes, [&](auto *arg) { 
astContext.getCanonicalParamType(arg.ty);});`

Alternatively, have it take some sort of mutating range, which does the work 
for us?  

Or maybe build that into CallArgList, and have `arrangeCIRFunctionInfo` take a 
`CallArgList` and use a `arg.getCanonicalParamType()` on CallArg's object.  
WDYT?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -63,3 +66,74 @@ Address CIRGenFunction::getAddressOfBaseClass(
 
   return value;
 }
+
+void CIRGenFunction::emitCXXConstructorCall(const clang::CXXConstructorDecl *d,
+clang::CXXCtorType type,
+bool forVirtualBase,
+bool delegating,
+AggValueSlot thisAVS,
+const clang::CXXConstructExpr *e) {
+  CallArgList args;
+  Address thisAddr = thisAVS.getAddress();
+  QualType thisType = d->getThisType();
+  mlir::Value thisPtr = thisAddr.getPointer();
+
+  assert(!cir::MissingFeatures::addressSpace());
+
+  args.add(RValue::get(thisPtr), thisType);
+
+  // In LLVM Codegen: If this is a trivial constructor, just emit what's 
needed.
+  // If this is a union copy constructor, we must emit a memcpy, because the 
AST
+  // does not model that copy.
+  assert(!cir::MissingFeatures::isMemcpyEquivalentSpecialMember());
+
+  const FunctionProtoType *fpt = d->getType()->castAs();
+
+  assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
+
+  emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+   /*ParamsToSkip=*/0);
+
+  assert(!cir::MissingFeatures::sanitizers());
+  emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
+ e->getExprLoc());
+}
+
+void CIRGenFunction::emitCXXConstructorCall(
+const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
+bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
+
+  const auto *cd = d->getParent();

erichkeane wrote:

Don't use auto here?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Erich Keane via cfe-commits


@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;

erichkeane wrote:

I see this is checked, but never set to false?

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


[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread Andy Kaylor via cfe-commits

https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/143579

This change adds support for calling C++ constructors. The support for actually 
defining a constructor is still missing and will be added in a later change.

>From 844b07e53937d3496405fd2c58148bd03c1f7407 Mon Sep 17 00:00:00 2001
From: Andy Kaylor 
Date: Mon, 9 Jun 2025 09:38:55 -0700
Subject: [PATCH] [CIR] Upstream support for calling constructors

This change adds support for calling C++ constructors. The support for
actually defining a constructor is still missing and will be added in
a later change.
---
 clang/include/clang/CIR/MissingFeatures.h |  3 +
 clang/lib/CIR/CodeGen/CIRGenCall.cpp  | 99 +--
 clang/lib/CIR/CodeGen/CIRGenClass.cpp | 74 ++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  | 51 ++
 clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp |  6 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h| 13 +++
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 54 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  | 19 
 clang/lib/CIR/CodeGen/CIRGenTypes.h   |  6 ++
 clang/test/CIR/CodeGen/ctor.cpp   | 19 
 10 files changed, 336 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/ctor.cpp

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..f89d386378e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -222,6 +222,9 @@ struct MissingFeatures {
   static bool instrumentation() { return false; }
   static bool cleanupAfterErrorDiags() { return false; }
   static bool cxxRecordStaticMembers() { return false; }
+  static bool isMemcpyEquivalentSpecialMember() { return false; }
+  static bool isTrivialCtorOrDtor() { return false; }
+  static bool implicitConstructorArgs() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..9d25eea9e413d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,13 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   return *this;
 }
 
+/// Returns the canonical formal type of the given C++ method.
+static CanQual getFormalType(const CXXMethodDecl *md) {
+  return md->getType()
+  ->getCanonicalTypeUnqualified()
+  .getAs();
+}
+
 /// Adds the formal parameters in FPT to the given prefix. If any parameter in
 /// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
 /// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;
+
+  if (auto *cd = dyn_cast(md)) {
+// A base class inheriting constructor doesn't get forwarded arguments
+// needed to construct a virtual base (or base class thereof)
+if (cd->getInheritedConstructor())
+  cgm.errorNYI(cd->getSourceRange(),
+   "arrangeCXXStructorDeclaration: inheriting constructor");
+  }
+
+  CanQual fpt = getFormalType(md);
+
+  if (passParams)
+appendParameterTypes(*this, argTypes, fpt);
+
+  assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+  RequiredArgs required =
+  (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+  : RequiredArgs::All);
+
+  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+   : theCXXABI.hasMostDerivedReturn(gd)
+   ? astContext.VoidPtrTy
+   : astContext.VoidTy;
+
+  assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
 /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
 /// qualification. Either or both of `rd` and `md` may be null. A null `rd`
 /// indicates that there is no meaningful 'this' type, and a null `md` can 
occur
@@ -103,13 +152,13 @@ CanQualType CIRGenTypes::deriveThisType(const 
CXXRecordDecl *rd,
 /// top of any implicit parameters already stored.
 static const CIRGenFunctionInfo &
 arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl &prefix,
-   CanQual ftp) {
+   CanQual fpt) {
   assert(!cir::MissingFeatures::opCallFnInf

[clang] [CIR] Upstream support for calling constructors (PR #143579)

2025-06-10 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)


Changes

This change adds support for calling C++ constructors. The support for actually 
defining a constructor is still missing and will be added in a later change.

---

Patch is 22.10 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/143579.diff


10 Files Affected:

- (modified) clang/include/clang/CIR/MissingFeatures.h (+3) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+93-6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenClass.cpp (+74) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+51) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+13) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+52-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.h (+19) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+6) 
- (added) clang/test/CIR/CodeGen/ctor.cpp (+19) 


``diff
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 72d882beb2244..f89d386378e51 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -222,6 +222,9 @@ struct MissingFeatures {
   static bool instrumentation() { return false; }
   static bool cleanupAfterErrorDiags() { return false; }
   static bool cxxRecordStaticMembers() { return false; }
+  static bool isMemcpyEquivalentSpecialMember() { return false; }
+  static bool isTrivialCtorOrDtor() { return false; }
+  static bool implicitConstructorArgs() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index b194a8670bfb9..9d25eea9e413d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -60,6 +60,13 @@ CIRGenCallee 
CIRGenCallee::prepareConcreteCallee(CIRGenFunction &cgf) const {
   return *this;
 }
 
+/// Returns the canonical formal type of the given C++ method.
+static CanQual getFormalType(const CXXMethodDecl *md) {
+  return md->getType()
+  ->getCanonicalTypeUnqualified()
+  .getAs();
+}
+
 /// Adds the formal parameters in FPT to the given prefix. If any parameter in
 /// FPT has pass_object_size_attrs, then we'll add parameters for those, too.
 /// TODO(cir): this should be shared with LLVM codegen
@@ -76,6 +83,48 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
+  auto *md = cast(gd.getDecl());
+
+  llvm::SmallVector argTypes;
+  argTypes.push_back(deriveThisType(md->getParent(), md));
+
+  bool passParams = true;
+
+  if (auto *cd = dyn_cast(md)) {
+// A base class inheriting constructor doesn't get forwarded arguments
+// needed to construct a virtual base (or base class thereof)
+if (cd->getInheritedConstructor())
+  cgm.errorNYI(cd->getSourceRange(),
+   "arrangeCXXStructorDeclaration: inheriting constructor");
+  }
+
+  CanQual fpt = getFormalType(md);
+
+  if (passParams)
+appendParameterTypes(*this, argTypes, fpt);
+
+  assert(!cir::MissingFeatures::implicitConstructorArgs());
+
+  RequiredArgs required =
+  (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
+  : RequiredArgs::All);
+
+  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+   : theCXXABI.hasMostDerivedReturn(gd)
+   ? astContext.VoidPtrTy
+   : astContext.VoidTy;
+
+  assert(!theCXXABI.hasThisReturn(gd) &&
+ "Please send PR with a test and remove this");
+
+  assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+  return arrangeCIRFunctionInfo(resultType, argTypes, required);
+}
+
 /// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
 /// qualification. Either or both of `rd` and `md` may be null. A null `rd`
 /// indicates that there is no meaningful 'this' type, and a null `md` can 
occur
@@ -103,13 +152,13 @@ CanQualType CIRGenTypes::deriveThisType(const 
CXXRecordDecl *rd,
 /// top of any implicit parameters already stored.
 static const CIRGenFunctionInfo &
 arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl &prefix,
-   CanQual ftp) {
+   CanQual fpt) {
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
   RequiredArgs required =
-  RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
+  RequiredArgs::getFromProtoWithExtraSlots(fpt, prefix.size());
   assert(!cir::MissingFeatures::opCallExtParameterInfo());
-  appendParameterTypes(cgt, prefix, ftp);
-  CanQualType resultType = ftp->g