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

This refactors the CGCXXABI and ItaniumCXXABI classes in LLVM IR codegen and 
their CIR codegen counterparts so that common code can be shared between the 
two.

This is a small first step towards better code sharing between LLVM IR codegen 
and CIR codegen. We should be able to expand this significantly as CIR codegen 
matures.

Note that some other code can very nearly, but not quite be shared at this 
point. For example `AddedStructorArgs` and its uses are nearly identical 
between LLVM IR and CIR codegen, but the struct contains an `llvm::Value*` 
member in LLVM IR codegen where it conatins an `mlir::Value` member in CIR 
codegen. We will need additional refactoring to handle cases like that.

>From ba2b1d6a36b0163ddc2bb99d66018e94fe8a149f Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Fri, 24 Oct 2025 16:54:26 -0700
Subject: [PATCH] [Clang][CodeGen][NFC] Refactor CGCXXABI classes for code
 sharing

This refactors the CGCXXABI and ItaniumCXXABI classes in LLVM IR codegen
and their CIR codegen counterparts so that common code can be shared
between the two.

This is a small first step towards better code sharing between LLVM IR
codegen and CIR codegen. We should be able to expand this significantly
as CIR codegen matures.

Note that some other code can very nearly, but not quite be shared at this
point. For example `AddedStructorArgs` and its uses are nearly identical
between LLVM IR and CIR codegen, but the struct contains an `llvm::Value*`
member in LLVM IR codegen where it conatins an `mlir::Value` member in
CIR codegen. We will need additional refactoring to handle cases like that.
---
 .../clang/CodeGenShared/CXXABIShared.h        |  99 +++++++++++++++
 .../clang/CodeGenShared/ItaniumCXXABIShared.h | 118 ++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenCXX.cpp           |   2 +-
 clang/lib/CIR/CodeGen/CIRGenCXXABI.h          |  52 ++------
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          |   6 +-
 clang/lib/CIR/CodeGen/CIRGenClass.cpp         |  10 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp      |   2 +-
 clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp |  56 ++-------
 clang/lib/CodeGen/CGCXXABI.cpp                |   4 -
 clang/lib/CodeGen/CGCXXABI.h                  |  59 +--------
 clang/lib/CodeGen/ItaniumCXXABI.cpp           |  90 ++-----------
 11 files changed, 259 insertions(+), 239 deletions(-)
 create mode 100644 clang/include/clang/CodeGenShared/CXXABIShared.h
 create mode 100644 clang/include/clang/CodeGenShared/ItaniumCXXABIShared.h

diff --git a/clang/include/clang/CodeGenShared/CXXABIShared.h 
b/clang/include/clang/CodeGenShared/CXXABIShared.h
new file mode 100644
index 0000000000000..957aae749c53b
--- /dev/null
+++ b/clang/include/clang/CodeGenShared/CXXABIShared.h
@@ -0,0 +1,99 @@
+//===----- CXXABIShared.h - Shared C++ ABI Base Class -----------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a base class for C++ ABI functionality that can be shared
+// between LLVM IR codegen and CIR codegen.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENSHARED_CXXABISHARED_H
+#define LLVM_CLANG_CODEGENSHARED_CXXABISHARED_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Basic/ABI.h"
+
+namespace clang {
+class ASTContext;
+
+/// Implements C++ ABI functionality that can be shared between LLVM IR codegen
+/// and CIR codegen.
+class CXXABIShared {
+protected:
+  ASTContext &Context;
+  std::unique_ptr<MangleContext> MangleCtx;
+
+  CXXABIShared(ASTContext &Context)
+      : Context(Context), MangleCtx(Context.createMangleContext()) {}
+
+public:
+  virtual ~CXXABIShared() = default;
+
+  /// Similar to AddedStructorArgs, but only notes the number of additional
+  /// arguments.
+  struct AddedStructorArgCounts {
+    unsigned Prefix = 0;
+    unsigned Suffix = 0;
+    AddedStructorArgCounts() = default;
+    AddedStructorArgCounts(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
+    static AddedStructorArgCounts prefix(unsigned N) { return {N, 0}; }
+    static AddedStructorArgCounts suffix(unsigned N) { return {0, N}; }
+  };
+
+  /// Get the AST context.
+  ASTContext &getContext() const { return Context; }
+
+  /// Gets the mangle context.
+  MangleContext &getMangleContext() { return *MangleCtx; }
+
+  /// Determine whether there's something special about the rules of
+  /// the ABI tell us that 'this' is a complete object within the
+  /// given function.  Obvious common logic like being defined on a
+  /// final class will have been taken care of by the caller.
+  virtual bool isThisCompleteObject(GlobalDecl GD) const = 0;
+
+  /// Returns true if the most-derived return value should be returned.
+  virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; }
+
+  /// Return whether the given global decl needs a VTT parameter.
+  virtual bool NeedsVTTParameter(GlobalDecl GD) const { return false; }
+
+  /// Returns true if the given constructor or destructor is one of the
+  /// kinds that the ABI says returns 'this' (only applies when called
+  /// non-virtually for destructors).
+  ///
+  /// There currently is no way to indicate if a destructor returns 'this'
+  /// when called virtually, and code generation does not support the case.
+  /// Returns true if the given constructor or destructor is one of the
+  /// kinds that the ABI says returns 'this' (only applies when called
+  /// non-virtually for destructors).
+  ///
+  /// There currently is no way to indicate if a destructor returns 'this'
+  /// when called virtually, and code generation does not support the case.
+  virtual bool HasThisReturn(GlobalDecl GD) const {
+    if (isa<CXXConstructorDecl>(GD.getDecl()) ||
+        (isa<CXXDestructorDecl>(GD.getDecl()) &&
+         GD.getDtorType() != Dtor_Deleting))
+      return constructorsAndDestructorsReturnThis();
+    return false;
+  }
+
+  /// Returns true if the given destructor type should be emitted as a linkonce
+  /// delegating thunk, regardless of whether the dtor is defined in this TU or
+  /// not.
+  virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
+                                      CXXDtorType DT) const = 0;
+
+protected:
+  virtual bool constructorsAndDestructorsReturnThis() const = 0;
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_CODEGENSHARED_CXXABISHARED_H
diff --git a/clang/include/clang/CodeGenShared/ItaniumCXXABIShared.h 
b/clang/include/clang/CodeGenShared/ItaniumCXXABIShared.h
new file mode 100644
index 0000000000000..e1f1d1242aea3
--- /dev/null
+++ b/clang/include/clang/CodeGenShared/ItaniumCXXABIShared.h
@@ -0,0 +1,118 @@
+//===--- ItaniumCXXABIShared.h - Itanium C++ ABI Shared Base ----*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides a base class for Itanium C++ ABI implementations that can
+// be shared between LLVM IR codegen and CIR codegen.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CODEGENSHARED_ITANIUMCXXABISHARED_H
+#define LLVM_CLANG_CODEGENSHARED_ITANIUMCXXABISHARED_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/Basic/ABI.h"
+#include <utility>
+
+namespace clang {
+
+template <typename BaseT> class ItaniumCXXABIShared : public BaseT {
+protected:
+  /// Constructor forwarding to the base ABI class.
+  template <typename... Args>
+  ItaniumCXXABIShared(Args &&...args) : BaseT(std::forward<Args>(args)...) {}
+
+public:
+  /// Determine whether there's something special about the rules of
+  /// the ABI tell us that 'this' is a complete object within the
+  /// given function.  Obvious common logic like being defined on a
+  /// final class will have been taken care of by the caller.
+  bool isThisCompleteObject(GlobalDecl GD) const override {
+    // The Itanium ABI has separate complete-object vs. base-object
+    // variants of both constructors and destructors.
+    if (isa<CXXDestructorDecl>(GD.getDecl())) {
+      switch (GD.getDtorType()) {
+      case Dtor_Complete:
+      case Dtor_Deleting:
+        return true;
+
+      case Dtor_Base:
+        return false;
+
+      case Dtor_Comdat:
+        llvm_unreachable("emitting dtor comdat as function?");
+      case Dtor_Unified:
+        llvm_unreachable("emitting unified dtor as function?");
+      }
+      llvm_unreachable("bad dtor kind");
+    }
+    if (isa<CXXConstructorDecl>(GD.getDecl())) {
+      switch (GD.getCtorType()) {
+      case Ctor_Complete:
+        return true;
+
+      case Ctor_Base:
+        return false;
+
+      case Ctor_CopyingClosure:
+      case Ctor_DefaultClosure:
+        llvm_unreachable("closure ctors in Itanium ABI?");
+
+      case Ctor_Comdat:
+        llvm_unreachable("emitting ctor comdat as function?");
+
+      case Ctor_Unified:
+        llvm_unreachable("emitting unified ctor as function?");
+      }
+      llvm_unreachable("bad ctor kind");
+    }
+
+    // No other kinds.
+    return false;
+  }
+
+  bool NeedsVTTParameter(GlobalDecl GD) const override {
+    const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
+
+    // We don't have any virtual bases, just return early.
+    if (!MD->getParent()->getNumVBases())
+      return false;
+
+    // Check if we have a base constructor.
+    if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
+      return true;
+
+    // Check if we have a base destructor.
+    if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
+      return true;
+
+    return false;
+  }
+
+  /// Returns true if the given destructor type should be emitted as a linkonce
+  /// delegating thunk, regardless of whether the dtor is defined in this TU or
+  /// not.
+  ///
+  /// Itanium does not emit any destructor variant as an inline thunk.
+  /// Delegating may occur as an optimization, but all variants are either
+  /// emitted with external linkage or as linkonce if they are inline and used.
+  bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
+                              CXXDtorType DT) const override {
+    return false;
+  }
+
+  /// Returns true if this ABI initializes vptrs in constructors/destructors.
+  /// For Itanium, this is always true.
+  bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
+    return true;
+  }
+};
+
+} // namespace clang
+
+#endif // LLVM_CLANG_CODEGENSHARED_ITANIUMCXXABISHARED_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
index a3e20817d2ca4..2fd6980499edd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCXX.cpp
@@ -116,7 +116,7 @@ static void emitDeclDestroy(CIRGenFunction &cgf, const 
VarDecl *vd,
   // mismatch.
   const CXXRecordDecl *record = type->getAsCXXRecordDecl();
   bool canRegisterDestructor =
-      record && (!cgm.getCXXABI().hasThisReturn(
+      record && (!cgm.getCXXABI().HasThisReturn(
                      GlobalDecl(record->getDestructor(), Dtor_Complete)) ||
                  cgm.getCXXABI().canCallMismatchedFunctionType());
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 13dc9f305945a..f292ced83259f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -19,23 +19,25 @@
 #include "CIRGenFunction.h"
 #include "CIRGenModule.h"
 
-#include "clang/AST/Mangle.h"
+#include "clang/CodeGenShared/CXXABIShared.h"
 
 namespace clang::CIRGen {
 
 /// Implements C++ ABI-specific code generation functions.
-class CIRGenCXXABI {
+class CIRGenCXXABI : public CXXABIShared {
 protected:
   CIRGenModule &cgm;
-  std::unique_ptr<clang::MangleContext> mangleContext;
+
+  CIRGenCXXABI(CIRGenModule &cgm)
+      : CXXABIShared(cgm.getASTContext()), cgm(cgm) {}
 
   virtual bool requiresArrayCookie(const CXXNewExpr *e);
 
+  bool constructorsAndDestructorsReturnThis() const override {
+    return cgm.getCodeGenOpts().CtorDtorReturnThis;
+  }
+
 public:
-  // TODO(cir): make this protected when target-specific CIRGenCXXABIs are
-  // implemented.
-  CIRGenCXXABI(CIRGenModule &cgm)
-      : cgm(cgm), mangleContext(cgm.getASTContext().createMangleContext()) {}
   virtual ~CIRGenCXXABI();
 
   void setCXXABIThisValue(CIRGenFunction &cgf, mlir::Value thisPtr);
@@ -62,17 +64,6 @@ class CIRGenCXXABI {
                                       bool isRefCast, Address src) = 0;
 
 public:
-  /// Similar to AddedStructorArgs, but only notes the number of additional
-  /// arguments.
-  struct AddedStructorArgCounts {
-    unsigned prefix = 0;
-    unsigned suffix = 0;
-    AddedStructorArgCounts() = default;
-    AddedStructorArgCounts(unsigned p, unsigned s) : prefix(p), suffix(s) {}
-    static AddedStructorArgCounts withPrefix(unsigned n) { return {n, 0}; }
-    static AddedStructorArgCounts withSuffix(unsigned n) { return {0, n}; }
-  };
-
   /// Additional implicit arguments to add to the beginning (Prefix) and end
   /// (Suffix) of a constructor / destructor arg list.
   ///
@@ -138,10 +129,6 @@ class CIRGenCXXABI {
     return md->getParent();
   }
 
-  /// Return whether the given global decl needs a VTT (virtual table table)
-  /// parameter.
-  virtual bool needsVTTParameter(clang::GlobalDecl gd) { return false; }
-
   /// Perform ABI-specific "this" argument adjustment required prior to
   /// a call of a virtual function.
   /// The "VirtualCall" argument is true iff the call itself is virtual.
@@ -214,12 +201,6 @@ class CIRGenCXXABI {
   /// this emits virtual table tables.
   virtual void emitVirtualInheritanceTables(const CXXRecordDecl *rd) = 0;
 
-  /// Returns true if the given destructor type should be emitted as a linkonce
-  /// delegating thunk, regardless of whether the dtor is defined in this TU or
-  /// not.
-  virtual bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
-                                      CXXDtorType dt) const = 0;
-
   virtual cir::GlobalLinkageKind
   getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor,
                           CXXDtorType dt) const;
@@ -262,18 +243,6 @@ class CIRGenCXXABI {
   virtual bool
   doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass) = 0;
 
-  /// Returns true if the given constructor or destructor is one of the kinds
-  /// that the ABI says returns 'this' (only applies when called non-virtually
-  /// for destructors).
-  ///
-  /// There currently is no way to indicate if a destructor returns 'this' when
-  /// called virtually, and CIR generation does not support this case.
-  virtual bool hasThisReturn(clang::GlobalDecl gd) const { return false; }
-
-  virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const {
-    return false;
-  }
-
   /// Returns true if the target allows calling a function through a pointer
   /// with a different signature than the actual function (or equivalently,
   /// bitcasting a function or function pointer to a different function type).
@@ -284,9 +253,6 @@ class CIRGenCXXABI {
   /// for all calls.
   virtual bool canCallMismatchedFunctionType() const { return true; }
 
-  /// Gets the mangle context.
-  clang::MangleContext &getMangleContext() { return *mangleContext; }
-
   clang::ImplicitParamDecl *&getStructorImplicitParamDecl(CIRGenFunction &cgf) 
{
     return cgf.cxxStructorImplicitParamDecl;
   }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 88aef89ddd2b9..f4fb20bc3368c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -206,12 +206,12 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) 
{
       (passParams && md->isVariadic() ? RequiredArgs(argTypes.size())
                                       : RequiredArgs::All);
 
-  CanQualType resultType = theCXXABI.hasThisReturn(gd) ? argTypes.front()
+  CanQualType resultType = theCXXABI.HasThisReturn(gd) ? argTypes.front()
                            : theCXXABI.hasMostDerivedReturn(gd)
                                ? astContext.VoidPtrTy
                                : astContext.VoidTy;
 
-  assert(!theCXXABI.hasThisReturn(gd) &&
+  assert(!theCXXABI.HasThisReturn(gd) &&
          "Please send PR with a test and remove this");
 
   assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
@@ -350,7 +350,7 @@ const CIRGenFunctionInfo 
&CIRGenTypes::arrangeCXXConstructorCall(
                               : RequiredArgs::All;
 
   GlobalDecl gd(d, ctorKind);
-  if (theCXXABI.hasThisReturn(gd))
+  if (theCXXABI.HasThisReturn(gd))
     cgm.errorNYI(d->getSourceRange(),
                  "arrangeCXXConstructorCall: hasThisReturn");
   if (theCXXABI.hasMostDerivedReturn(gd))
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp 
b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 5046e0945002f..067e6d29ef526 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -759,7 +759,7 @@ void CIRGenFunction::emitDelegateCXXConstructorCall(
 
   // FIXME: The location of the VTT parameter in the parameter list is specific
   // to the Itanium ABI and shouldn't be hardcoded here.
-  if (cgm.getCXXABI().needsVTTParameter(curGD)) {
+  if (cgm.getCXXABI().NeedsVTTParameter(curGD)) {
     cgm.errorNYI(loc, "emitDelegateCXXConstructorCall: VTT parameter");
     return;
   }
@@ -1068,7 +1068,7 @@ void CIRGenFunction::emitCXXDestructorCall(const 
CXXDestructorDecl *dd,
 
 mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl gd, bool forVirtualBase,
                                             bool delegating) {
-  if (!cgm.getCXXABI().needsVTTParameter(gd))
+  if (!cgm.getCXXABI().NeedsVTTParameter(gd))
     return nullptr;
 
   const CXXRecordDecl *rd = cast<CXXMethodDecl>(curCodeDecl)->getParent();
@@ -1082,7 +1082,7 @@ mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl 
gd, bool forVirtualBase,
   } else if (rd == base) {
     // If the record matches the base, this is the complete ctor/dtor
     // variant calling the base variant in a class with virtual bases.
-    assert(!cgm.getCXXABI().needsVTTParameter(curGD) &&
+    assert(!cgm.getCXXABI().NeedsVTTParameter(curGD) &&
            "doing no-op VTT offset in base dtor/ctor?");
     assert(!forVirtualBase && "Can't have same class as virtual base!");
     subVTTIndex = 0;
@@ -1097,7 +1097,7 @@ mlir::Value CIRGenFunction::getVTTParameter(GlobalDecl 
gd, bool forVirtualBase,
   }
 
   mlir::Location loc = cgm.getLoc(rd->getBeginLoc());
-  if (cgm.getCXXABI().needsVTTParameter(curGD)) {
+  if (cgm.getCXXABI().NeedsVTTParameter(curGD)) {
     // A VTT parameter was passed to the constructor, use it.
     mlir::Value vtt = loadCXXVTT();
     return builder.createVTTAddrPoint(loc, vtt.getType(), vtt, subVTTIndex);
@@ -1266,7 +1266,7 @@ void CIRGenFunction::emitCXXConstructorCall(
   // Emit the call.
   auto calleePtr = cgm.getAddrOfCXXStructor(GlobalDecl(d, type));
   const CIRGenFunctionInfo &info = cgm.getTypes().arrangeCXXConstructorCall(
-      args, d, type, extraArgs.prefix, extraArgs.suffix, passPrototypeArgs);
+      args, d, type, extraArgs.Prefix, extraArgs.Suffix, passPrototypeArgs);
   CIRGenCallee callee = CIRGenCallee::forDirect(calleePtr, GlobalDecl(d, 
type));
   cir::CIRCallOpInterface c;
   emitCall(info, callee, ReturnValueSlot(), args, &c, getLoc(loc));
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 58feb36f78f23..d1affce25e429 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -833,7 +833,7 @@ clang::QualType 
CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
 
   const auto *md = dyn_cast<CXXMethodDecl>(fd);
   if (md && md->isInstance()) {
-    if (cgm.getCXXABI().hasThisReturn(gd))
+    if (cgm.getCXXABI().HasThisReturn(gd))
       cgm.errorNYI(fd->getSourceRange(), "this return");
     else if (cgm.getCXXABI().hasMostDerivedReturn(gd))
       cgm.errorNYI(fd->getSourceRange(), "most derived return");
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index 88fedf1acc6a1..7c0732e85b0ac 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -24,6 +24,7 @@
 #include "clang/AST/GlobalDecl.h"
 #include "clang/AST/VTableBuilder.h"
 #include "clang/CIR/MissingFeatures.h"
+#include "clang/CodeGenShared/ItaniumCXXABIShared.h"
 #include "llvm/Support/ErrorHandling.h"
 
 using namespace clang;
@@ -31,13 +32,14 @@ using namespace clang::CIRGen;
 
 namespace {
 
-class CIRGenItaniumCXXABI : public CIRGenCXXABI {
+class CIRGenItaniumCXXABI : public ItaniumCXXABIShared<CIRGenCXXABI> {
 protected:
   /// All the vtables which have been defined.
   llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
 
 public:
-  CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
+  CIRGenItaniumCXXABI(CIRGenModule &cgm)
+      : ItaniumCXXABIShared<CIRGenCXXABI>(cgm) {
     assert(!cir::MissingFeatures::cxxabiUseARMMethodPtrABI());
     assert(!cir::MissingFeatures::cxxabiUseARMGuardVarABI());
   }
@@ -48,8 +50,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
                                                bool forVirtualBase,
                                                bool delegating) override;
 
-  bool needsVTTParameter(clang::GlobalDecl gd) override;
-
   AddedStructorArgCounts
   buildStructorSignature(GlobalDecl gd,
                          llvm::SmallVectorImpl<CanQualType> &argTys) override;
@@ -81,13 +81,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
   void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
   void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
 
-  bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
-                              CXXDtorType dt) const override {
-    // Itanium does not emit any destructor variant as an inline thunk.
-    // Delegating may occur as an optimization, but all variants are either
-    // emitted with external linkage or as linkonce if they are inline and 
used.
-    return false;
-  }
 
   bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
                                            CIRGenFunction::VPtr vptr) override;
@@ -119,10 +112,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
   mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
                                           QualType ty) override;
 
-  bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
-    return true;
-  }
-
   void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;
 
   mlir::Value
@@ -205,9 +194,9 @@ void 
CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
   /// 1) getThisValue is currently protected
   /// 2) in theory, an ABI could implement 'this' returns some other way;
   ///    HasThisReturn only specifies a contract, not the implementation
-  if (hasThisReturn(cgf.curGD)) {
+  if (HasThisReturn(cgf.curGD)) {
     cgf.cgm.errorNYI(cgf.curFuncDecl->getLocation(),
-                     "emitInstanceFunctionProlog: hasThisReturn");
+                     "emitInstanceFunctionProlog: HasThisReturn");
   }
 }
 
@@ -227,7 +216,7 @@ CIRGenItaniumCXXABI::buildStructorSignature(
     argTys.insert(argTys.begin() + 1,
                   astContext.getPointerType(
                       CanQualType::CreateUnsafe(astContext.VoidPtrTy)));
-    return AddedStructorArgCounts::withPrefix(1);
+    return AddedStructorArgCounts::prefix(1);
   }
 
   return AddedStructorArgCounts{};
@@ -334,7 +323,7 @@ void 
CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
   assert(isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md));
 
   // Check if we need a VTT parameter as well.
-  if (needsVTTParameter(cgf.curGD)) {
+  if (NeedsVTTParameter(cgf.curGD)) {
     ASTContext &astContext = cgm.getASTContext();
 
     // FIXME: avoid the fake decl
@@ -383,7 +372,7 @@ void CIRGenItaniumCXXABI::emitCXXDestructors(const 
CXXDestructorDecl *d) {
 CIRGenCXXABI::AddedStructorArgs 
CIRGenItaniumCXXABI::getImplicitConstructorArgs(
     CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
     bool forVirtualBase, bool delegating) {
-  if (!needsVTTParameter(GlobalDecl(d, type)))
+  if (!NeedsVTTParameter(GlobalDecl(d, type)))
     return AddedStructorArgs{};
 
   // Insert the implicit 'vtt' argument as the second argument. Make sure to
@@ -397,27 +386,6 @@ CIRGenCXXABI::AddedStructorArgs 
CIRGenItaniumCXXABI::getImplicitConstructorArgs(
   return AddedStructorArgs::withPrefix({{vtt, vttTy}});
 }
 
-/// Return whether the given global decl needs a VTT (virtual table table)
-/// parameter, which it does if it's a base constructor or destructor with
-/// virtual bases.
-bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
-  auto *md = cast<CXXMethodDecl>(gd.getDecl());
-
-  // We don't have any virtual bases, just return early.
-  if (!md->getParent()->getNumVBases())
-    return false;
-
-  // Check if we have a base constructor.
-  if (isa<CXXConstructorDecl>(md) && gd.getCtorType() == Ctor_Base)
-    return true;
-
-  // Check if we have a base destructor.
-  if (isa<CXXDestructorDecl>(md) && gd.getDtorType() == Dtor_Base)
-    return true;
-
-  return false;
-}
-
 void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
                                                 const CXXRecordDecl *rd) {
   cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
@@ -1781,7 +1749,7 @@ mlir::Value 
CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
     CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
     const CXXRecordDecl *nearestVBase) {
   assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
-         needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
+         NeedsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
 
   // Get the secondary vpointer index.
   uint64_t virtualPointerIndex =
@@ -1827,7 +1795,7 @@ mlir::Value 
CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
     clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
 
   if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
-      needsVTTParameter(cgf.curGD)) {
+      NeedsVTTParameter(cgf.curGD)) {
     return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
                                                   nearestVBase);
   }
@@ -1838,7 +1806,7 @@ bool 
CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
     CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
   if (vptr.nearestVBase == nullptr)
     return false;
-  return needsVTTParameter(cgf.curGD);
+  return NeedsVTTParameter(cgf.curGD);
 }
 
 mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 30e5dc2b6cbd9..edc49a48a5c8a 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -319,10 +319,6 @@ llvm::GlobalValue::LinkageTypes 
CGCXXABI::getCXXDestructorLinkage(
   return CGM.getLLVMLinkageForDeclarator(Dtor, Linkage);
 }
 
-bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
-  return false;
-}
-
 llvm::CallInst *
 CGCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF,
                                               llvm::Value *Exn) {
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 2dd320dbda976..394fdbc270413 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -17,6 +17,7 @@
 #include "CodeGenFunction.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/CodeGen/CodeGenABITypes.h"
+#include "clang/CodeGenShared/CXXABIShared.h"
 
 namespace llvm {
 class Constant;
@@ -31,7 +32,6 @@ class CXXConstructorDecl;
 class CXXDestructorDecl;
 class CXXMethodDecl;
 class CXXRecordDecl;
-class MangleContext;
 
 namespace CodeGen {
 class CGCallee;
@@ -40,15 +40,13 @@ class CodeGenModule;
 struct CatchTypeInfo;
 
 /// Implements C++ ABI-specific code generation functions.
-class CGCXXABI {
+class CGCXXABI : public CXXABIShared {
   friend class CodeGenModule;
 
 protected:
   CodeGenModule &CGM;
-  std::unique_ptr<MangleContext> MangleCtx;
 
-  CGCXXABI(CodeGenModule &CGM)
-    : CGM(CGM), MangleCtx(CGM.getContext().createMangleContext()) {}
+  CGCXXABI(CodeGenModule &CGM) : CXXABIShared(CGM.getContext()), CGM(CGM) {}
 
 protected:
   ImplicitParamDecl *getThisDecl(CodeGenFunction &CGF) {
@@ -78,8 +76,6 @@ class CGCXXABI {
 
   void setCXXABIThisValue(CodeGenFunction &CGF, llvm::Value *ThisPtr);
 
-  ASTContext &getContext() const { return CGM.getContext(); }
-
   bool mayNeedDestruction(const VarDecl *VD) const;
 
   /// Determine whether we will definitely emit this variable with a constant
@@ -95,13 +91,7 @@ class CGCXXABI {
   virtual bool requiresArrayCookie(const CXXDeleteExpr *E, QualType eltType);
   virtual bool requiresArrayCookie(const CXXNewExpr *E);
 
-  /// Determine whether there's something special about the rules of
-  /// the ABI tell us that 'this' is a complete object within the
-  /// given function.  Obvious common logic like being defined on a
-  /// final class will have been taken care of by the caller.
-  virtual bool isThisCompleteObject(GlobalDecl GD) const = 0;
-
-  virtual bool constructorsAndDestructorsReturnThis() const {
+  bool constructorsAndDestructorsReturnThis() const override {
     return CGM.getCodeGenOpts().CtorDtorReturnThis;
   }
 
@@ -109,27 +99,6 @@ class CGCXXABI {
 
   virtual ~CGCXXABI();
 
-  /// Gets the mangle context.
-  MangleContext &getMangleContext() {
-    return *MangleCtx;
-  }
-
-  /// Returns true if the given constructor or destructor is one of the
-  /// kinds that the ABI says returns 'this' (only applies when called
-  /// non-virtually for destructors).
-  ///
-  /// There currently is no way to indicate if a destructor returns 'this'
-  /// when called virtually, and code generation does not support the case.
-  virtual bool HasThisReturn(GlobalDecl GD) const {
-    if (isa<CXXConstructorDecl>(GD.getDecl()) ||
-        (isa<CXXDestructorDecl>(GD.getDecl()) &&
-         GD.getDtorType() != Dtor_Deleting))
-      return constructorsAndDestructorsReturnThis();
-    return false;
-  }
-
-  virtual bool hasMostDerivedReturn(GlobalDecl GD) const { return false; }
-
   virtual bool useSinitAndSterm() const { return false; }
 
   /// Returns true if the target allows calling a function through a pointer
@@ -353,17 +322,6 @@ class CGCXXABI {
     }
   };
 
-  /// Similar to AddedStructorArgs, but only notes the number of additional
-  /// arguments.
-  struct AddedStructorArgCounts {
-    unsigned Prefix = 0;
-    unsigned Suffix = 0;
-    AddedStructorArgCounts() = default;
-    AddedStructorArgCounts(unsigned P, unsigned S) : Prefix(P), Suffix(S) {}
-    static AddedStructorArgCounts prefix(unsigned N) { return {N, 0}; }
-    static AddedStructorArgCounts suffix(unsigned N) { return {0, N}; }
-  };
-
   /// Build the signature of the given constructor or destructor variant by
   /// adding any required parameters.  For convenience, ArgTys has been
   /// initialized with the type of 'this'.
@@ -371,12 +329,6 @@ class CGCXXABI {
   buildStructorSignature(GlobalDecl GD,
                          SmallVectorImpl<CanQualType> &ArgTys) = 0;
 
-  /// Returns true if the given destructor type should be emitted as a linkonce
-  /// delegating thunk, regardless of whether the dtor is defined in this TU or
-  /// not.
-  virtual bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
-                                      CXXDtorType DT) const = 0;
-
   virtual void setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
                                           const CXXDestructorDecl *Dtor,
                                           CXXDtorType DT) const;
@@ -583,9 +535,6 @@ class CGCXXABI {
                                QualType ElementType, llvm::Value *&NumElements,
                                llvm::Value *&AllocPtr, CharUnits &CookieSize);
 
-  /// Return whether the given global decl needs a VTT parameter.
-  virtual bool NeedsVTTParameter(GlobalDecl GD);
-
 protected:
   /// Returns the extra size required in order to store the array
   /// cookie for the given type.  Assumes that an array cookie is
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 65c47633bc5c4..1bbbd9384a7fd 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -30,6 +30,7 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/Type.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "clang/CodeGenShared/ItaniumCXXABIShared.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/IR/Instructions.h"
@@ -43,7 +44,7 @@ using namespace clang;
 using namespace CodeGen;
 
 namespace {
-class ItaniumCXXABI : public CodeGen::CGCXXABI {
+class ItaniumCXXABI : public ItaniumCXXABIShared<CodeGen::CGCXXABI> {
   /// VTables - All the vtables which have been defined.
   llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
 
@@ -61,12 +62,11 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   }
 
 public:
-  ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
-                bool UseARMMethodPtrABI = false,
-                bool UseARMGuardVarABI = false) :
-    CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
-    UseARMGuardVarABI(UseARMGuardVarABI),
-    Use32BitVTableOffsetABI(false) { }
+  ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool UseARMMethodPtrABI = false,
+                bool UseARMGuardVarABI = false)
+      : ItaniumCXXABIShared<CodeGen::CGCXXABI>(CGM),
+        UseARMMethodPtrABI(UseARMMethodPtrABI),
+        UseARMGuardVarABI(UseARMGuardVarABI), Use32BitVTableOffsetABI(false) {}
 
   bool classifyReturnType(CGFunctionInfo &FI) const override;
 
@@ -77,50 +77,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
     return RAA_Default;
   }
 
-  bool isThisCompleteObject(GlobalDecl GD) const override {
-    // The Itanium ABI has separate complete-object vs.  base-object
-    // variants of both constructors and destructors.
-    if (isa<CXXDestructorDecl>(GD.getDecl())) {
-      switch (GD.getDtorType()) {
-      case Dtor_Complete:
-      case Dtor_Deleting:
-        return true;
-
-      case Dtor_Base:
-        return false;
-
-      case Dtor_Comdat:
-        llvm_unreachable("emitting dtor comdat as function?");
-      case Dtor_Unified:
-        llvm_unreachable("emitting unified dtor as function?");
-      }
-      llvm_unreachable("bad dtor kind");
-    }
-    if (isa<CXXConstructorDecl>(GD.getDecl())) {
-      switch (GD.getCtorType()) {
-      case Ctor_Complete:
-        return true;
-
-      case Ctor_Base:
-        return false;
-
-      case Ctor_CopyingClosure:
-      case Ctor_DefaultClosure:
-        llvm_unreachable("closure ctors in Itanium ABI?");
-
-      case Ctor_Comdat:
-        llvm_unreachable("emitting ctor comdat as function?");
-
-      case Ctor_Unified:
-        llvm_unreachable("emitting unified ctor as function?");
-      }
-      llvm_unreachable("bad dtor kind");
-    }
-
-    // No other kinds.
-    return false;
-  }
-
   bool isZeroInitializable(const MemberPointerType *MPT) override;
 
   llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
@@ -263,13 +219,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   buildStructorSignature(GlobalDecl GD,
                          SmallVectorImpl<CanQualType> &ArgTys) override;
 
-  bool useThunkForDtorVariant(const CXXDestructorDecl *Dtor,
-                              CXXDtorType DT) const override {
-    // Itanium does not emit any destructor variant as an inline thunk.
-    // Delegating may occur as an optimization, but all variants are either
-    // emitted with external linkage or as linkonce if they are inline and 
used.
-    return false;
-  }
 
   void EmitCXXDestructors(const CXXDestructorDecl *D) override;
 
@@ -301,9 +250,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   bool isVirtualOffsetNeededForVTableField(CodeGenFunction &CGF,
                                            CodeGenFunction::VPtr Vptr) 
override;
 
-  bool doStructorsInitializeVPtrs(const CXXRecordDecl *VTableClass) override {
-    return true;
-  }
 
   llvm::Constant *
   getVTableAddressPoint(BaseSubobject Base,
@@ -396,8 +342,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
                                       QualType LValType) override;
 
-  bool NeedsVTTParameter(GlobalDecl GD) override;
-
   llvm::Constant *
   getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD);
 
@@ -3407,26 +3351,6 @@ LValue 
ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
   return LV;
 }
 
-/// Return whether the given global decl needs a VTT parameter, which it does
-/// if it's a base constructor or destructor with virtual bases.
-bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) {
-  const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
-
-  // We don't have any virtual bases, just return early.
-  if (!MD->getParent()->getNumVBases())
-    return false;
-
-  // Check if we have a base constructor.
-  if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
-    return true;
-
-  // Check if we have a base destructor.
-  if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
-    return true;
-
-  return false;
-}
-
 llvm::Constant *
 ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) 
{
   SmallString<256> MethodName;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to