-
Notifications
You must be signed in to change notification settings - Fork 15k
[CIR] Add lowering for the cir.vtable.address_point operation #153243
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/153243.diff 3 Files Affected:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 88a0fe2e1f848..25f894eba7d4f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2074,6 +2074,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());
@@ -2312,7 +2316,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMVecShuffleOpLowering,
CIRToLLVMVecSplatOpLowering,
CIRToLLVMVecTernaryOpLowering,
- CIRToLLVMUnreachableOpLowering
+ CIRToLLVMUnreachableOpLowering,
+ CIRToLLVMVTableAddrPointOpLowering
// clang-format on
>(converter, patterns.getContext());
@@ -2391,6 +2396,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 51b191af24692..c23edc0c1c2a6 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.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, minor suggestion that can be addressed (or not) as follow up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we are relying on this function clients to check if eltType is filled in (same in incubator), should we just do it here as a final else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what else this would be if it isn't a cir::GlobalOp or LLVM::GlobalOp. Maybe the else should call op.emitError()?
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.
19de64e to
7ac51e7
Compare
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.