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

>From 5e3ab0b4e314b970eb1f1d61aa2d05a0de2cfc55 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Thu, 7 Aug 2025 17:15:17 -0700
Subject: [PATCH 1/2] [CIR] Add lowering for the cir.vtable.address_point
 operation

This adds support for lowering the cir.vtable.address_point
operation to the LLVM dialect, as well as type converter support
for the cir.vptr type.
---
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 47 ++++++++++++++++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   | 10 ++++
 .../CIR/CodeGen/virtual-function-calls.cpp    | 26 +++++++++-
 3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ad5f52034f92a..f9486addcb4ac 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2083,6 +2083,10 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
 
     return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS);
   });
+  converter.addConversion([&](cir::VPtrType type) -> mlir::Type {
+    assert(!cir::MissingFeatures::addressSpace());
+    return mlir::LLVM::LLVMPointerType::get(type.getContext());
+  });
   converter.addConversion([&](cir::ArrayType type) -> mlir::Type {
     mlir::Type ty =
         convertTypeForMemory(converter, dataLayout, type.getElementType());
@@ -2314,6 +2318,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMSwitchFlatOpLowering,
                CIRToLLVMTrapOpLowering,
                CIRToLLVMUnaryOpLowering,
+               CIRToLLVMUnreachableOpLowering,
                CIRToLLVMVecCmpOpLowering,
                CIRToLLVMVecCreateOpLowering,
                CIRToLLVMVecExtractOpLowering,
@@ -2322,7 +2327,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMVecShuffleOpLowering,
                CIRToLLVMVecSplatOpLowering,
                CIRToLLVMVecTernaryOpLowering,
-               CIRToLLVMUnreachableOpLowering
+               CIRToLLVMVTableAddrPointOpLowering
+      // clang-format on
       >(converter, patterns.getContext());
 
   processCIRAttrs(module);
@@ -2400,6 +2406,45 @@ mlir::LogicalResult 
CIRToLLVMTrapOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+static mlir::Value
+getValueForVTableSymbol(mlir::Operation *op,
+                        mlir::ConversionPatternRewriter &rewriter,
+                        const mlir::TypeConverter *converter,
+                        mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) 
{
+  auto module = op->getParentOfType<mlir::ModuleOp>();
+  mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, 
nameAttr);
+  if (auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol))
+    eltType = llvmSymbol.getType();
+  else if (auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol))
+    eltType = converter->convertType(cirSymbol.getSymType());
+
+  return mlir::LLVM::AddressOfOp::create(
+      rewriter, op->getLoc(),
+      mlir::LLVM::LLVMPointerType::get(op->getContext()), nameAttr.getValue());
+}
+
+mlir::LogicalResult CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
+    cir::VTableAddrPointOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  const mlir::TypeConverter *converter = getTypeConverter();
+  mlir::Type targetType = converter->convertType(op.getType());
+  llvm::SmallVector<mlir::LLVM::GEPArg> offsets;
+  mlir::Type eltType;
+  mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
+                                                op.getNameAttr(), eltType);
+  offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{
+      0, op.getAddressPointAttr().getIndex(),
+      op.getAddressPointAttr().getOffset()};
+
+  assert(eltType && "Shouldn't ever be missing an eltType here");
+  mlir::LLVM::GEPNoWrapFlags inboundsNuw =
+      mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
+  rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
+                                                 symAddr, offsets, 
inboundsNuw);
+
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMStackSaveOpLowering::matchAndRewrite(
     cir::StackSaveOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index a6d2d6559005b..6fbe0079b90d0 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -457,6 +457,16 @@ class CIRToLLVMBaseClassAddrOpLowering
                   mlir::ConversionPatternRewriter &) const override;
 };
 
+class CIRToLLVMVTableAddrPointOpLowering
+    : public mlir::OpConversionPattern<cir::VTableAddrPointOp> {
+public:
+  using mlir::OpConversionPattern<cir::VTableAddrPointOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(cir::VTableAddrPointOp op, OpAdaptor,
+                  mlir::ConversionPatternRewriter &) const override;
+};
+
 class CIRToLLVMStackSaveOpLowering
     : public mlir::OpConversionPattern<cir::StackSaveOp> {
 public:
diff --git a/clang/test/CIR/CodeGen/virtual-function-calls.cpp 
b/clang/test/CIR/CodeGen/virtual-function-calls.cpp
index f3b134b135c85..004b6dab30563 100644
--- a/clang/test/CIR/CodeGen/virtual-function-calls.cpp
+++ b/clang/test/CIR/CodeGen/virtual-function-calls.cpp
@@ -1,5 +1,9 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-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 -mconstructor-aliases 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
 
 struct A {
   A();
@@ -14,7 +18,11 @@ A::A() {}
 
 // CIR: cir.global "private" external @_ZTV1A : !rec_anon_struct
 
-// CIR: cir.func dso_local @_ZN1AC2Ev(%arg0: !cir.ptr<!rec_A> {{.*}})
+// LLVM: @_ZTV1A = external global { [3 x ptr] }
+
+// OGCG: @_ZTV1A = external unnamed_addr constant { [3 x ptr] }
+
+// CIR: cir.func{{.*}} @_ZN1AC2Ev(%arg0: !cir.ptr<!rec_A> {{.*}})
 // CIR:    %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, 
!cir.ptr<!cir.ptr<!rec_A>>, ["this", init]
 // CIR:    cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_A>, 
!cir.ptr<!cir.ptr<!rec_A>>
 // CIR:    %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : 
!cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
@@ -22,3 +30,19 @@ A::A() {}
 // CIR:    %[[THIS_VPTR_PTR:.*]] = cir.cast(bitcast, %[[THIS]] : 
!cir.ptr<!rec_A>), !cir.ptr<!cir.vptr>
 // CIR:    cir.store align(8) %[[VPTR]], %[[THIS_VPTR_PTR]] : !cir.vptr, 
!cir.ptr<!cir.vptr>
 // CIR:    cir.return
+
+// LLVM: define{{.*}} void @_ZN1AC2Ev(ptr %[[ARG0:.*]])
+// LLVM:   %[[THIS_ADDR:.*]] = alloca ptr
+// LLVM:   store ptr %[[ARG0]], ptr %[[THIS_ADDR]]
+// LLVM:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// LLVM:   store ptr getelementptr inbounds nuw (i8, ptr @_ZTV1A, i64 16), ptr 
%[[THIS]]
+
+// OGCG: define{{.*}} void @_ZN1AC2Ev(ptr {{.*}} %[[ARG0:.*]])
+// OGCG:   %[[THIS_ADDR:.*]] = alloca ptr
+// OGCG:   store ptr %[[ARG0]], ptr %[[THIS_ADDR]]
+// OGCG:   %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+// OGCG:   store ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, 
ptr @_ZTV1A, i32 0, i32 0, i32 2), ptr %[[THIS]]
+
+// NOTE: The GEP in OGCG looks very different from the one generated with CIR,
+//       but it is equivalent. The OGCG GEP indexes by base pointer, then
+//       structure, then array, whereas the CIR GEP indexes by byte offset.

>From 7ac51e76d5a41ec77b95e3ef4b2470b99e1661fc Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akay...@nvidia.com>
Date: Wed, 13 Aug 2025 16:52:07 -0700
Subject: [PATCH 2/2] Address feedback

---
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f9486addcb4ac..c3715c28f6890 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2413,10 +2413,14 @@ getValueForVTableSymbol(mlir::Operation *op,
                         mlir::FlatSymbolRefAttr nameAttr, mlir::Type &eltType) 
{
   auto module = op->getParentOfType<mlir::ModuleOp>();
   mlir::Operation *symbol = mlir::SymbolTable::lookupSymbolIn(module, 
nameAttr);
-  if (auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol))
+  if (auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(symbol)) {
     eltType = llvmSymbol.getType();
-  else if (auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol))
+  } else if (auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(symbol)) {
     eltType = converter->convertType(cirSymbol.getSymType());
+  } else {
+    op->emitError() << "unexpected symbol type for " << symbol;
+    return {};
+  }
 
   return mlir::LLVM::AddressOfOp::create(
       rewriter, op->getLoc(),
@@ -2432,6 +2436,9 @@ mlir::LogicalResult 
CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
   mlir::Type eltType;
   mlir::Value symAddr = getValueForVTableSymbol(op, rewriter, converter,
                                                 op.getNameAttr(), eltType);
+  if (!symAddr)
+    return op.emitError() << "Unable to get value for vtable symbol";
+
   offsets = llvm::SmallVector<mlir::LLVM::GEPArg>{
       0, op.getAddressPointAttr().getIndex(),
       op.getAddressPointAttr().getOffset()};
@@ -2441,7 +2448,6 @@ mlir::LogicalResult 
CIRToLLVMVTableAddrPointOpLowering::matchAndRewrite(
       mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
   rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, targetType, eltType,
                                                  symAddr, offsets, 
inboundsNuw);
-
   return mlir::success();
 }
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to