Author: Andy Kaylor
Date: 2025-09-02T09:22:05-07:00
New Revision: 9f7bb1c42c3011dab48e8de86e4d151d75747aef

URL: 
https://github.com/llvm/llvm-project/commit/9f7bb1c42c3011dab48e8de86e4d151d75747aef
DIFF: 
https://github.com/llvm/llvm-project/commit/9f7bb1c42c3011dab48e8de86e4d151d75747aef.diff

LOG: [CIR] Add support for emitting VTTs and related ojects (#155721)

This adds support for emitting virtual table tables (VTTs) and
construction vtables.

Added: 
    

Modified: 
    clang/lib/CIR/CodeGen/CIRGenCXXABI.h
    clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
    clang/lib/CIR/CodeGen/CIRGenVTables.cpp
    clang/lib/CIR/CodeGen/CIRGenVTables.h
    clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
    clang/test/CIR/CodeGen/vtt.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 7c620301499ff..32c4ef28532ea 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -107,6 +107,10 @@ class CIRGenCXXABI {
   virtual void emitVTableDefinitions(CIRGenVTables &cgvt,
                                      const CXXRecordDecl *rd) = 0;
 
+  /// Emit any tables needed to implement virtual inheritance.  For Itanium,
+  /// 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.

diff  --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index ab7a0699637b9..7e57ede3193b4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -85,6 +85,7 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
       const clang::CXXRecordDecl *nearestVBase) override;
   void emitVTableDefinitions(CIRGenVTables &cgvt,
                              const CXXRecordDecl *rd) override;
+  void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
 
   bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
     return true;
@@ -335,6 +336,13 @@ void 
CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
   }
 }
 
+void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
+    const CXXRecordDecl *rd) {
+  CIRGenVTables &vtables = cgm.getVTables();
+  cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
+  vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
+}
+
 void CIRGenItaniumCXXABI::emitDestructorCall(
     CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
     bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {

diff  --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp 
b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
index aca12aa62f55b..9fbc0f67b4b92 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp
@@ -15,6 +15,7 @@
 #include "CIRGenCXXABI.h"
 #include "CIRGenModule.h"
 #include "mlir/IR/Types.h"
+#include "clang/AST/VTTBuilder.h"
 #include "clang/AST/VTableBuilder.h"
 #include "llvm/ADT/SmallVector.h"
 
@@ -60,7 +61,7 @@ void CIRGenVTables::generateClassData(const CXXRecordDecl 
*rd) {
   assert(!cir::MissingFeatures::generateDebugInfo());
 
   if (rd->getNumVBases())
-    cgm.errorNYI(rd->getSourceRange(), "emitVirtualInheritanceTables");
+    cgm.getCXXABI().emitVirtualInheritanceTables(rd);
 
   cgm.getCXXABI().emitVTableDefinitions(*this, rd);
 }
@@ -76,12 +77,6 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
   assert(!cir::MissingFeatures::vtableRelativeLayout());
 
   switch (component.getKind()) {
-  case VTableComponent::CK_VCallOffset:
-    cgm.errorNYI("getVTableComponent: VCallOffset");
-    return mlir::Attribute();
-  case VTableComponent::CK_VBaseOffset:
-    cgm.errorNYI("getVTableComponent: VBaseOffset");
-    return mlir::Attribute();
   case VTableComponent::CK_CompleteDtorPointer:
     cgm.errorNYI("getVTableComponent: CompleteDtorPointer");
     return mlir::Attribute();
@@ -92,6 +87,14 @@ mlir::Attribute CIRGenVTables::getVTableComponent(
     cgm.errorNYI("getVTableComponent: UnusedFunctionPointer");
     return mlir::Attribute();
 
+  case VTableComponent::CK_VCallOffset:
+    return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
+                                   component.getVCallOffset().getQuantity());
+
+  case VTableComponent::CK_VBaseOffset:
+    return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
+                                   component.getVBaseOffset().getQuantity());
+
   case VTableComponent::CK_OffsetToTop:
     return builder.getConstPtrAttr(builder.getUInt8PtrTy(),
                                    component.getOffsetToTop().getQuantity());
@@ -175,6 +178,66 @@ void CIRGenVTables::createVTableInitializer(cir::GlobalOp 
&vtableOp,
   cgm.setInitializer(vtableOp, vtableAttr);
 }
 
+cir::GlobalOp CIRGenVTables::generateConstructionVTable(
+    const CXXRecordDecl *rd, const BaseSubobject &base, bool baseIsVirtual,
+    cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints) {
+  assert(!cir::MissingFeatures::generateDebugInfo());
+
+  std::unique_ptr<VTableLayout> vtLayout(
+      getItaniumVTableContext().createConstructionVTableLayout(
+          base.getBase(), base.getBaseOffset(), baseIsVirtual, rd));
+
+  // Add the address points.
+  addressPoints = vtLayout->getAddressPoints();
+
+  // Get the mangled construction vtable name.
+  SmallString<256> outName;
+  llvm::raw_svector_ostream out(outName);
+  cast<ItaniumMangleContext>(cgm.getCXXABI().getMangleContext())
+      .mangleCXXCtorVTable(rd, base.getBaseOffset().getQuantity(),
+                           base.getBase(), out);
+  SmallString<256> name(outName);
+
+  assert(!cir::MissingFeatures::vtableRelativeLayout());
+
+  cir::RecordType vtType = getVTableType(*vtLayout);
+
+  // Construction vtable symbols are not part of the Itanium ABI, so we cannot
+  // guarantee that they actually will be available externally. Instead, when
+  // emitting an available_externally VTT, we provide references to an internal
+  // linkage construction vtable. The ABI only requires complete-object vtables
+  // to be the same for all instances of a type, not construction vtables.
+  if (linkage == cir::GlobalLinkageKind::AvailableExternallyLinkage)
+    linkage = cir::GlobalLinkageKind::InternalLinkage;
+
+  llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtType);
+  mlir::Location loc = cgm.getLoc(rd->getSourceRange());
+
+  // Create the variable that will hold the construction vtable.
+  cir::GlobalOp vtable = cgm.createOrReplaceCXXRuntimeVariable(
+      loc, name, vtType, linkage, CharUnits::fromQuantity(align));
+
+  // V-tables are always unnamed_addr.
+  assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
+
+  mlir::Attribute rtti = cgm.getAddrOfRTTIDescriptor(
+      loc, cgm.getASTContext().getCanonicalTagType(base.getBase()));
+
+  // Create and set the initializer.
+  createVTableInitializer(vtable, *vtLayout, rtti,
+                          cir::isLocalLinkage(vtable.getLinkage()));
+
+  // Set properties only after the initializer has been set to ensure that the
+  // GV is treated as definition and not declaration.
+  assert(!vtable.isDeclaration() && "Shouldn't set properties on declaration");
+  cgm.setGVProperties(vtable, rd);
+
+  assert(!cir::MissingFeatures::vtableEmitMetadata());
+  assert(!cir::MissingFeatures::vtableRelativeLayout());
+
+  return vtable;
+}
+
 /// Compute the required linkage of the vtable for the given class.
 ///
 /// Note that we only call this at the end of the translation unit.
@@ -226,6 +289,109 @@ cir::GlobalLinkageKind 
CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
   return cir::GlobalLinkageKind::ExternalLinkage;
 }
 
+cir::GlobalOp CIRGenVTables::getAddrOfVTT(const CXXRecordDecl *rd) {
+  assert(rd->getNumVBases() && "Only classes with virtual bases need a VTT");
+
+  SmallString<256> outName;
+  llvm::raw_svector_ostream out(outName);
+  cast<ItaniumMangleContext>(cgm.getCXXABI().getMangleContext())
+      .mangleCXXVTT(rd, out);
+  StringRef name = outName.str();
+
+  // This will also defer the definition of the VTT.
+  (void)cgm.getCXXABI().getAddrOfVTable(rd, CharUnits());
+
+  VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/false);
+
+  auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
+                                       builder.getVTTComponents().size());
+  llvm::Align align =
+      cgm.getDataLayout().getABITypeAlign(cgm.getBuilder().getUInt8PtrTy());
+  cir::GlobalOp vtt = cgm.createOrReplaceCXXRuntimeVariable(
+      cgm.getLoc(rd->getSourceRange()), name, arrayType,
+      cir::GlobalLinkageKind::ExternalLinkage, CharUnits::fromQuantity(align));
+  cgm.setGVProperties(vtt, rd);
+  return vtt;
+}
+
+static cir::GlobalOp
+getAddrOfVTTVTable(CIRGenVTables &cgvt, CIRGenModule &cgm,
+                   const CXXRecordDecl *mostDerivedClass,
+                   const VTTVTable &vtable, cir::GlobalLinkageKind linkage,
+                   VTableLayout::AddressPointsMapTy &addressPoints) {
+  if (vtable.getBase() == mostDerivedClass) {
+    assert(vtable.getBaseOffset().isZero() &&
+           "Most derived class vtable must have a zero offset!");
+    // This is a regular vtable.
+    return cgm.getCXXABI().getAddrOfVTable(mostDerivedClass, CharUnits());
+  }
+  return cgvt.generateConstructionVTable(
+      mostDerivedClass, vtable.getBaseSubobject(), vtable.isVirtual(), linkage,
+      addressPoints);
+}
+
+/// Emit the definition of the given vtable.
+void CIRGenVTables::emitVTTDefinition(cir::GlobalOp vttOp,
+                                      cir::GlobalLinkageKind linkage,
+                                      const CXXRecordDecl *rd) {
+  VTTBuilder builder(cgm.getASTContext(), rd, /*GenerateDefinition=*/true);
+
+  mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
+
+  auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
+                                       builder.getVTTComponents().size());
+
+  SmallVector<cir::GlobalOp> vtables;
+  SmallVector<VTableAddressPointsMapTy> vtableAddressPoints;
+  for (const VTTVTable &vtt : builder.getVTTVTables()) {
+    vtableAddressPoints.push_back(VTableAddressPointsMapTy());
+    vtables.push_back(getAddrOfVTTVTable(*this, cgm, rd, vtt, linkage,
+                                         vtableAddressPoints.back()));
+  }
+
+  SmallVector<mlir::Attribute> vttComponents;
+  for (const VTTComponent &vttComponent : builder.getVTTComponents()) {
+    const VTTVTable &vttVT = builder.getVTTVTables()[vttComponent.VTableIndex];
+    cir::GlobalOp vtable = vtables[vttComponent.VTableIndex];
+    VTableLayout::AddressPointLocation addressPoint;
+    if (vttVT.getBase() == rd) {
+      // Just get the address point for the regular vtable.
+      addressPoint =
+          getItaniumVTableContext().getVTableLayout(rd).getAddressPoint(
+              vttComponent.VTableBase);
+    } else {
+      addressPoint = vtableAddressPoints[vttComponent.VTableIndex].lookup(
+          vttComponent.VTableBase);
+      assert(addressPoint.AddressPointIndex != 0 &&
+             "Did not find ctor vtable address point!");
+    }
+
+    mlir::Attribute indices[2] = {
+        cgm.getBuilder().getI32IntegerAttr(addressPoint.VTableIndex),
+        cgm.getBuilder().getI32IntegerAttr(addressPoint.AddressPointIndex),
+    };
+
+    auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
+    cir::GlobalViewAttr init = cgm.getBuilder().getGlobalViewAttr(
+        cgm.getBuilder().getUInt8PtrTy(), vtable, indicesAttr);
+
+    vttComponents.push_back(init);
+  }
+
+  auto init = cir::ConstArrayAttr::get(
+      arrayType, mlir::ArrayAttr::get(mlirContext, vttComponents));
+
+  vttOp.setInitialValueAttr(init);
+
+  // Set the correct linkage.
+  vttOp.setLinkage(linkage);
+  mlir::SymbolTable::setSymbolVisibility(
+      vttOp, CIRGenModule::getMLIRVisibility(vttOp));
+
+  if (cgm.supportsCOMDAT() && vttOp.isWeakForLinker())
+    vttOp.setComdat(true);
+}
+
 void CIRGenVTables::emitThunks(GlobalDecl gd) {
   const CXXMethodDecl *md =
       cast<CXXMethodDecl>(gd.getDecl())->getCanonicalDecl();

diff  --git a/clang/lib/CIR/CodeGen/CIRGenVTables.h 
b/clang/lib/CIR/CodeGen/CIRGenVTables.h
index 518d7d78f1737..8d352c9949109 100644
--- a/clang/lib/CIR/CodeGen/CIRGenVTables.h
+++ b/clang/lib/CIR/CodeGen/CIRGenVTables.h
@@ -30,6 +30,9 @@ class CIRGenVTables {
 
   clang::VTableContextBase *vtContext;
 
+  /// Address points for a single vtable.
+  using VTableAddressPointsMapTy = clang::VTableLayout::AddressPointsMapTy;
+
   mlir::Attribute
   getVTableComponent(const VTableLayout &layout, unsigned componentIndex,
                      mlir::Attribute rtti, unsigned &nextVTableThunkIndex,
@@ -55,6 +58,19 @@ class CIRGenVTables {
     return *llvm::cast<clang::ItaniumVTableContext>(vtContext);
   }
 
+  /// Generate a construction vtable for the given base subobject.
+  cir::GlobalOp
+  generateConstructionVTable(const CXXRecordDecl *rd, const BaseSubobject 
&base,
+                             bool baseIsVirtual, cir::GlobalLinkageKind 
linkage,
+                             VTableAddressPointsMapTy &addressPoints);
+
+  /// Get the address of the VTT for the given record decl.
+  cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *rd);
+
+  /// Emit the definition of the given vtable.
+  void emitVTTDefinition(cir::GlobalOp vttOp, cir::GlobalLinkageKind linkage,
+                         const CXXRecordDecl *rd);
+
   /// Emit the associated thunks for the given global decl.
   void emitThunks(GlobalDecl gd);
 

diff  --git a/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
index 42d45819de0f3..4635ce943b17c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
@@ -24,15 +24,6 @@ void CIRDataLayout::reset(mlir::DataLayoutSpecInterface 
spec) {
 }
 
 llvm::Align CIRDataLayout::getAlignment(mlir::Type ty, bool useABIAlign) const 
{
-  if (auto recTy = llvm::dyn_cast<cir::RecordType>(ty)) {
-    // Packed record types always have an ABI alignment of one.
-    if (recTy && recTy.getPacked() && useABIAlign)
-      return llvm::Align(1);
-
-    // Get the layout annotation... which is lazily created on demand.
-    llvm_unreachable("getAlignment()) for record type is not implemented");
-  }
-
   // FIXME(cir): This does not account for 
diff ernt address spaces, and relies
   // on CIR's data layout to give the proper alignment.
   assert(!cir::MissingFeatures::addressSpace());

diff  --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp
index 631aab428840a..fcbfc07324c6d 100644
--- a/clang/test/CIR/CodeGen/vtt.cpp
+++ b/clang/test/CIR/CodeGen/vtt.cpp
@@ -1,8 +1,8 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-rtti -fclangir 
-emit-cir %s -o %t.cir
 // RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-rtti -fclangir 
-emit-llvm %s -o %t-cir.ll
 // RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll  %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-rtti -emit-llvm %s -o 
%t.ll
 // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll  %s
 
 // Note: This test will be expanded to verify VTT emission and VTT implicit
@@ -11,7 +11,7 @@
 class A {
 public:
   int a;
-  virtual void v() {}
+  virtual void v();
 };
 
 class B : public virtual A {
@@ -23,23 +23,146 @@ class B : public virtual A {
 class C : public virtual A {
 public:
   long c;
-  virtual void x() {}
+  virtual void x();
 };
 
 class D : public B, public C {
 public:
   long d;
-  virtual void y() {}
+  virtual void y();
 };
 
 // This is just here to force the record types to be emitted.
 void f(D *d) {}
 
+// Trigger vtable and VTT emission for D.
+void D::y() {}
+
 // CIR: !rec_A2Ebase = !cir.record<struct "A.base" packed {!cir.vptr, !s32i}>
 // CIR: !rec_B2Ebase = !cir.record<struct "B.base" packed {!cir.vptr, !s32i}>
 // CIR: !rec_C2Ebase = !cir.record<struct "C.base" {!cir.vptr, !s64i}>
+// CIR: !rec_A = !cir.record<class "A" packed padded {!cir.vptr, !s32i, 
!cir.array<!u8i x 4>}>
+// CIR: !rec_B = !cir.record<class "B" packed padded {!cir.vptr, !s32i, 
!cir.array<!u8i x 4>, !rec_A2Ebase, !cir.array<!u8i x 4>}>
+// CIR: !rec_C = !cir.record<class "C" {!cir.vptr, !s64i, !rec_A2Ebase}>
 // CIR: !rec_D = !cir.record<class "D" {!rec_B2Ebase, !rec_C2Ebase, !s64i, 
!rec_A2Ebase}>
 
-// Nothing interesting to see here yet.
-// LLVM: define{{.*}} void @_Z1fP1D
-// OGCG: define{{.*}} void @_Z1fP1D
+// CIR: !rec_anon_struct = !cir.record<struct  {!cir.array<!cir.ptr<!u8i> x 
5>, !cir.array<!cir.ptr<!u8i> x 4>, !cir.array<!cir.ptr<!u8i> x 4>}>
+// CIR: !rec_anon_struct1 = !cir.record<struct  {!cir.array<!cir.ptr<!u8i> x 
4>, !cir.array<!cir.ptr<!u8i> x 4>}>
+
+// Vtable for D
+// CIR:      cir.global{{.*}} @_ZTV1D = #cir.vtable<{
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<40 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1B1wEv> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1D1yEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 5>,
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<24 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<-16 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1C1xEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>,
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<-40 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1A1vEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>
+// CIR-SAME: }> : !rec_anon_struct {alignment = 8 : i64}
+
+// LLVM:      @_ZTV1D = global { [5 x ptr], [4 x ptr], [4 x ptr] } {
+// LLVM-SAME:   [5 x ptr] [ptr inttoptr (i64 40 to ptr), ptr null, ptr null, 
ptr @_ZN1B1wEv, ptr @_ZN1D1yEv],
+// LLVM-SAME:   [4 x ptr] [ptr inttoptr (i64 24 to ptr), ptr inttoptr (i64 -16 
to ptr), ptr null, ptr @_ZN1C1xEv],
+// LLVM-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -40 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// LLVM-SAME: }, align 8
+
+// OGCG:      @_ZTV1D = unnamed_addr constant { [5 x ptr], [4 x ptr], [4 x 
ptr] } {
+// OGCG-SAME:   [5 x ptr] [ptr inttoptr (i64 40 to ptr), ptr null, ptr null, 
ptr @_ZN1B1wEv, ptr @_ZN1D1yEv],
+// OGCG-SAME:   [4 x ptr] [ptr inttoptr (i64 24 to ptr), ptr inttoptr (i64 -16 
to ptr), ptr null, ptr @_ZN1C1xEv],
+// OGCG-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -40 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// OGCG-SAME: }, align 8
+
+// VTT for D
+// CIR:      cir.global{{.*}} @_ZTT1D = #cir.const_array<[
+// CIR-SAME:   #cir.global_view<@_ZTV1D, [0 : i32, 3 : i32]> : !cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTC1D0_1B, [0 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTC1D0_1B, [1 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTC1D16_1C, [0 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTC1D16_1C, [1 : i32, 3 : i32]> : 
!cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTV1D, [2 : i32, 3 : i32]> : !cir.ptr<!u8i>,
+// CIR-SAME:   #cir.global_view<@_ZTV1D, [1 : i32, 3 : i32]> : !cir.ptr<!u8i>
+// CIR-SAME: ]> : !cir.array<!cir.ptr<!u8i> x 7> {alignment = 8 : i64}
+
+// LLVM:      @_ZTT1D = global [7 x ptr] [
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 24),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D0_1B, i64 24),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D0_1B, i64 56),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D16_1C, i64 24),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTC1D16_1C, i64 56),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 96),
+// LLVM-SAME:   ptr getelementptr inbounds nuw (i8, ptr @_ZTV1D, i64 64)
+// LLVM-SAME: ], align 8
+
+// OGCG:      @_ZTT1D = unnamed_addr constant [7 x ptr] [
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x 
ptr], [4 x ptr] }, ptr @_ZTV1D, i32 0, i32 0, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [4 x 
ptr] }, ptr @_ZTC1D0_1B, i32 0, i32 0, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [4 x 
ptr] }, ptr @_ZTC1D0_1B, i32 0, i32 1, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [4 x 
ptr] }, ptr @_ZTC1D16_1C, i32 0, i32 0, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [4 x ptr], [4 x 
ptr] }, ptr @_ZTC1D16_1C, i32 0, i32 1, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x 
ptr], [4 x ptr] }, ptr @_ZTV1D, i32 0, i32 2, i32 3),
+// OGCG-SAME:   ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x 
ptr], [4 x ptr] }, ptr @_ZTV1D, i32 0, i32 1, i32 3)
+// OGCG-SAME: ], align 8
+
+// Construction vtable for B-in-D
+// CIR:      cir.global{{.*}} @_ZTC1D0_1B = #cir.vtable<{
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<40 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1B1wEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>,
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<-40 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1A1vEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>
+// CIR-SAME: }> : !rec_anon_struct1 {alignment = 8 : i64}
+
+// LLVM:      @_ZTC1D0_1B = global { [4 x ptr], [4 x ptr] } {
+// LLVM-SAME:   [4 x ptr] [ptr inttoptr (i64 40 to ptr), ptr null, ptr null, 
ptr @_ZN1B1wEv],
+// LLVM-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -40 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// LLVM-SAME: }, align 8
+
+// OGCG:      @_ZTC1D0_1B = unnamed_addr constant { [4 x ptr], [4 x ptr] } {
+// OGCG-SAME:   [4 x ptr] [ptr inttoptr (i64 40 to ptr), ptr null, ptr null, 
ptr @_ZN1B1wEv],
+// OGCG-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -40 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// OGCG-SAME: }, align 8
+
+// Construction vtable for C-in-D
+// CIR:      cir.global{{.*}} @_ZTC1D16_1C = #cir.vtable<{
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<24 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1C1xEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>,
+// CIR-SAME:   #cir.const_array<[
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<-24 : i64> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.ptr<null> : !cir.ptr<!u8i>,
+// CIR-SAME:     #cir.global_view<@_ZN1A1vEv> : !cir.ptr<!u8i>
+// CIR-SAME:   ]> : !cir.array<!cir.ptr<!u8i> x 4>
+// CIR-SAME: }> : !rec_anon_struct1 {alignment = 8 : i64}
+
+// LLVM:      @_ZTC1D16_1C = global { [4 x ptr], [4 x ptr] } {
+// LLVM-SAME:   [4 x ptr] [ptr inttoptr (i64 24 to ptr), ptr null, ptr null, 
ptr @_ZN1C1xEv],
+// LLVM-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -24 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// LLVM-SAME: }, align 8
+
+// OGCG:      @_ZTC1D16_1C = unnamed_addr constant { [4 x ptr], [4 x ptr] } {
+// OGCG-SAME:   [4 x ptr] [ptr inttoptr (i64 24 to ptr), ptr null, ptr null, 
ptr @_ZN1C1xEv],
+// OGCG-SAME:   [4 x ptr] [ptr null, ptr inttoptr (i64 -24 to ptr), ptr null, 
ptr @_ZN1A1vEv]
+// OGCG-SAME: }, align 8


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

Reply via email to