https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/171950
>From 1004aaf830081691d16ffe6eb93677f5a6d7c41f Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Tue, 9 Dec 2025 15:46:54 -0800 Subject: [PATCH 1/5] [CIR] Upstream handling for data member pointer casts This adds the CIR basic handling for casts of data member pointers. Cast to bool and null, as well as member function pointer casts will be handled in followup PRs. --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 52 +++++++++ clang/include/clang/CIR/MissingFeatures.h | 2 + clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 34 ++++++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 32 +++++ .../Transforms/TargetLowering/CIRCXXABI.h | 12 ++ .../Transforms/TargetLowering/CMakeLists.txt | 1 + .../TargetLowering/LowerItaniumCXXABI.cpp | 51 ++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 +++ .../CodeGen/pointer-to-data-member-cast.cpp | 110 ++++++++++++++++++ 9 files changed, 312 insertions(+) create mode 100644 clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index e2b582c5c55df..a57b4275ebf25 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4176,6 +4176,58 @@ def CIR_DerivedClassAddrOp : CIR_Op<"derived_class_addr"> { }]; } +//===----------------------------------------------------------------------===// +// BaseDataMemberOp & DerivedDataMemberOp +//===----------------------------------------------------------------------===// + +def CIR_BaseDataMemberOp : CIR_Op<"base_data_member", [Pure]> { + let summary = + "Cast a derived class data member pointer to a base class data member " + "pointer"; + let description = [{ + The `cir.base_data_member` operation casts a data member pointer of type + `T Derived::*` to a data member pointer of type `T Base::*`, where `Base` + is an accessible non-ambiguous non-virtual base class of `Derived`. + + The `offset` parameter gives the offset in bytes of the `Base` base class + subobject within a `Derived` object. + }]; + + let arguments = (ins CIR_DataMemberType:$src, IndexAttr:$offset); + let results = (outs CIR_DataMemberType:$result); + + let assemblyFormat = [{ + $src `:` qualified(type($src)) + ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict + }]; + + let hasVerifier = 1; +} + +def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { + let summary = + "Cast a base class data member pointer to a derived class data member " + "pointer"; + let description = [{ + The `cir.derived_data_member` operation casts a data member pointer of type + `T Base::*` to a data member pointer of type `T Derived::*`, where `Base` + is an accessible non-ambiguous non-virtual base class of `Derived`. + + The `offset` parameter gives the offset in bytes of the `Base` base class + subobject within a `Derived` object. + }]; + + let arguments = (ins CIR_DataMemberType:$src, IndexAttr:$offset); + let results = (outs CIR_DataMemberType:$result); + + let assemblyFormat = [{ + $src `:` qualified(type($src)) + ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict + }]; + + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // ComplexCreateOp //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index acfc937a11993..51c8de3c98a23 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -302,6 +302,8 @@ struct MissingFeatures { static bool makeTripleAlwaysPresent() { return false; } static bool maybeHandleStaticInExternC() { return false; } static bool mergeAllConstants() { return false; } + static bool memberFuncPtrAuthInfo() { return false; } + static bool memberFuncPtrCast() { return false; } static bool metaDataNode() { return false; } static bool moduleNameHash() { return false; } static bool msabi() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 70be8977af37a..1fa9195224b79 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2243,6 +2243,40 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) { return builder.getNullDataMemberPtr(ty, cgf.getLoc(subExpr->getExprLoc())); } + case CK_BaseToDerivedMemberPointer: + case CK_DerivedToBaseMemberPointer: { + mlir::Value src = Visit(subExpr); + + assert(!cir::MissingFeatures::memberFuncPtrAuthInfo()); + + QualType derivedTy = + kind == CK_DerivedToBaseMemberPointer ? subExpr->getType() : destTy; + const auto *mpType = derivedTy->castAs<MemberPointerType>(); + NestedNameSpecifier qualifier = mpType->getQualifier(); + assert(qualifier && "member pointer without class qualifier"); + const Type *qualifierType = qualifier.getAsType(); + assert(qualifierType && "member pointer qualifier is not a type"); + const CXXRecordDecl *derivedClass = qualifierType->getAsCXXRecordDecl(); + CharUnits offset = cgf.cgm.computeNonVirtualBaseClassOffset( + derivedClass, ce->path()); + + mlir::Location loc = cgf.getLoc(subExpr->getExprLoc()); + mlir::Type resultTy = cgf.convertType(destTy); + mlir::IntegerAttr offsetAttr = builder.getIndexAttr(offset.getQuantity()); + + if (subExpr->getType()->isMemberFunctionPointerType()) { + cgf.cgm.errorNYI(subExpr->getSourceRange(), + "VisitCastExpr: member function pointer"); + return {}; + } + + if (kind == CK_BaseToDerivedMemberPointer) + return cir::DerivedDataMemberOp::create(builder, loc, resultTy, src, + offsetAttr); + return cir::BaseDataMemberOp::create(builder, loc, resultTy, src, + offsetAttr); + } + case CK_LValueToRValue: assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), destTy)); assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!"); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 063896b00a5a5..e21469b168d78 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2481,6 +2481,38 @@ OpFoldResult cir::UnaryOp::fold(FoldAdaptor adaptor) { return {}; } + +//===----------------------------------------------------------------------===// +// BaseDataMemberOp & DerivedDataMemberOp +//===----------------------------------------------------------------------===// + +static LogicalResult verifyMemberPtrCast(Operation *op, mlir::Value src, + mlir::Type resultTy) { + // Let the operand type be T1 C1::*, let the result type be T2 C2::*. + // Verify that T1 and T2 are the same type. + mlir::Type inputMemberTy; + mlir::Type resultMemberTy; + if (mlir::isa<cir::DataMemberType>(src.getType())) { + inputMemberTy = + mlir::cast<cir::DataMemberType>(src.getType()).getMemberTy(); + resultMemberTy = mlir::cast<cir::DataMemberType>(resultTy).getMemberTy(); + } + assert(!cir::MissingFeatures::memberFuncPtrCast()); + if (inputMemberTy != resultMemberTy) + return op->emitOpError() + << "member types of the operand and the result do not match"; + + return mlir::success(); +} + +LogicalResult cir::BaseDataMemberOp::verify() { + return verifyMemberPtrCast(getOperation(), getSrc(), getType()); +} + +LogicalResult cir::DerivedDataMemberOp::verify() { + return verifyMemberPtrCast(getOperation(), getSrc(), getType()); +} + //===----------------------------------------------------------------------===// // AwaitOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h index edfe29f1471cb..6c166b3aed5d6 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.h @@ -59,6 +59,18 @@ class CIRCXXABI { lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy, mlir::Value loweredAddr, mlir::Value loweredMember, mlir::OpBuilder &builder) const = 0; + + /// Lower the given cir.base_data_member op to a sequence of more "primitive" + /// CIR operations that act on the ABI types. + virtual mlir::Value lowerBaseDataMember(cir::BaseDataMemberOp op, + mlir::Value loweredSrc, + mlir::OpBuilder &builder) const = 0; + + /// Lower the given cir.derived_data_member op to a sequence of more + /// "primitive" CIR operations that act on the ABI types. + virtual mlir::Value + lowerDerivedDataMember(cir::DerivedDataMemberOp op, mlir::Value loweredSrc, + mlir::OpBuilder &builder) const = 0; }; /// Creates an Itanium-family ABI. diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt index 158c42e729536..3a1ab34cea4d9 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt @@ -17,4 +17,5 @@ add_clang_library(MLIRCIRTargetLowering MLIRDLTIDialect MLIRCIR MLIRCIRInterfaces + MLIRLLVMDialect ) diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp index 323ecc46909d4..21dc202602e15 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp @@ -51,6 +51,14 @@ class LowerItaniumCXXABI : public CIRCXXABI { lowerGetRuntimeMember(cir::GetRuntimeMemberOp op, mlir::Type loweredResultTy, mlir::Value loweredAddr, mlir::Value loweredMember, mlir::OpBuilder &builder) const override; + + mlir::Value lowerBaseDataMember(cir::BaseDataMemberOp op, + mlir::Value loweredSrc, + mlir::OpBuilder &builder) const override; + + mlir::Value lowerDerivedDataMember(cir::DerivedDataMemberOp op, + mlir::Value loweredSrc, + mlir::OpBuilder &builder) const override; }; } // namespace @@ -133,4 +141,47 @@ mlir::Operation *LowerItaniumCXXABI::lowerGetRuntimeMember( cir::CastKind::bitcast, memberBytesPtr); } +static mlir::Value lowerDataMemberCast(mlir::Operation *op, + mlir::Value loweredSrc, + std::int64_t offset, + bool isDerivedToBase, + mlir::OpBuilder &builder) { + if (offset == 0) + return loweredSrc; + mlir::Location loc = op->getLoc(); + mlir::Type ty = loweredSrc.getType(); + + auto nullValue = mlir::LLVM::ConstantOp::create( + builder, loc, ty, mlir::IntegerAttr::get(ty, -1)); + + auto isNull = mlir::LLVM::ICmpOp::create( + builder, loc, mlir::LLVM::ICmpPredicate::eq, loweredSrc, nullValue); + + auto offsetValue = mlir::LLVM::ConstantOp::create( + builder, loc, ty, mlir::IntegerAttr::get(ty, offset)); + mlir::Value adjustedPtr; + if (isDerivedToBase) + adjustedPtr = mlir::LLVM::SubOp::create(builder, loc, loweredSrc, offsetValue, mlir::LLVM::IntegerOverflowFlags::nsw); + else + adjustedPtr = mlir::LLVM::AddOp::create(builder, loc, loweredSrc, offsetValue, mlir::LLVM::IntegerOverflowFlags::nsw); + + return mlir::LLVM::SelectOp::create(builder, loc, isNull, loweredSrc, adjustedPtr); +} + +mlir::Value +LowerItaniumCXXABI::lowerBaseDataMember(cir::BaseDataMemberOp op, + mlir::Value loweredSrc, + mlir::OpBuilder &builder) const { + return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(), + /*isDerivedToBase=*/true, builder); +} + +mlir::Value +LowerItaniumCXXABI::lowerDerivedDataMember(cir::DerivedDataMemberOp op, + mlir::Value loweredSrc, + mlir::OpBuilder &builder) const { + return lowerDataMemberCast(op, loweredSrc, op.getOffset().getSExtValue(), + /*isDerivedToBase=*/false, builder); +} + } // namespace cir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 914233d8f6b8f..5331d461d76d5 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1528,6 +1528,24 @@ mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMBaseDataMemberOpLowering::matchAndRewrite( + cir::BaseDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = + lowerMod->getCXXABI().lowerBaseDataMember(op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRToLLVMDerivedDataMemberOpLowering::matchAndRewrite( + cir::DerivedDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerMod->getCXXABI().lowerDerivedDataMember( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite( cir::ATanOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp new file mode 100644 index 0000000000000..e5c673d031a2e --- /dev/null +++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll --check-prefix=OGCG %s + +struct Base1 { + int base1_data; +}; + +struct Base2 { + int base2_data; +}; + +struct Derived : Base1, Base2 { + int derived_data; +}; + +auto base_to_derived(int Base2::*ptr) -> int Derived::* { + return ptr; +} + +// CIR: cir.func {{.*}} @_Z15base_to_derivedM5Base2i +// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base2> [4] -> !cir.data_member<!s32i in !rec_Derived> + +// LLVM: define {{.*}} i64 @_Z15base_to_derivedM5Base2i +// LLVM: %[[PTR:.*]] = load i64, ptr %{{.*}} +// LLVM: %[[IS_NULL:.*]] = icmp eq i64 %[[PTR]], -1 +// LLVM: %[[DERIVED:.*]] = add nsw i64 %[[PTR]], 4 +// LLVM: %[[RET:.*]] = select i1 %[[IS_NULL]], i64 %[[PTR]], i64 %[[DERIVED]] + +// OGCG: define {{.*}} i64 @_Z15base_to_derivedM5Base2i +// OGCG: %[[PTR:.*]] = load i64, ptr %{{.*}} +// OGCG: %[[DERIVED:.*]] = add nsw i64 %[[PTR]], 4 +// OGCG: %[[IS_NULL:.*]] = icmp eq i64 %[[PTR]], -1 +// OGCG: %[[RET:.*]] = select i1 %[[IS_NULL]], i64 %[[PTR]], i64 %[[DERIVED]] + +auto derived_to_base(int Derived::*ptr) -> int Base2::* { + return static_cast<int Base2::*>(ptr); +} + +// CIR: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi +// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [4] -> !cir.data_member<!s32i in !rec_Base2> + +// LLVM: define {{.*}} i64 @_Z15derived_to_baseM7Derivedi +// LLVM: %[[PTR:.*]] = load i64, ptr %{{.*}} +// LLVM: %[[IS_NULL:.*]] = icmp eq i64 %[[PTR]], -1 +// LLVM: %[[BASE:.*]] = sub nsw i64 %[[PTR]], 4 +// LLVM: %[[RET:.*]] = select i1 %[[IS_NULL]], i64 %[[PTR]], i64 %[[BASE]] + +// OGCG: define {{.*}} i64 @_Z15derived_to_baseM7Derivedi +// OGCG: %[[PTR:.*]] = load i64, ptr %{{.*}} +// OGCG: %[[BASE:.*]] = sub nsw i64 %[[PTR]], 4 +// OGCG: %[[IS_NULL:.*]] = icmp eq i64 %[[PTR]], -1 +// OGCG: %[[RET:.*]] = select i1 %[[IS_NULL]], i64 %[[PTR]], i64 %[[BASE]] + +auto base_to_derived_zero_offset(int Base1::*ptr) -> int Derived::* { + return ptr; +} + +// CIR: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i +// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base1> [0] -> !cir.data_member<!s32i in !rec_Derived> + +// No LLVM instructions emitted for performing a zero-offset cast. + +// LLVM: define {{.*}} i64 @_Z27base_to_derived_zero_offsetM5Base1i +// LLVM-NEXT: %[[PTR_ADDR:.*]] = alloca i64 +// LLVM-NEXT: %[[RETVAL:.*]] = alloca i64 +// LLVM-NEXT: store i64 %{{.*}}, ptr %[[PTR_ADDR]] +// LLVM-NEXT: %[[TEMP:.*]] = load i64, ptr %[[PTR_ADDR]] +// LLVM-NEXT: store i64 %[[TEMP]], ptr %[[RETVAL]] +// LLVM-NEXT: %[[RET:.*]] = load i64, ptr %[[RETVAL]] +// LLVM-NEXT: ret i64 %[[RET]] + +// OGCG: define {{.*}} i64 @_Z27base_to_derived_zero_offsetM5Base1i +// OGCG-NEXT: entry: +// OGCG-NEXT: %[[PTR_ADDR:.*]] = alloca i64 +// OGCG-NEXT: store i64 %{{.*}}, ptr %[[PTR_ADDR]] +// OGCG-NEXT: %[[RET:.*]] = load i64, ptr %[[PTR_ADDR]] +// OGCG-NEXT: ret i64 %[[RET]] + +auto derived_to_base_zero_offset(int Derived::*ptr) -> int Base1::* { + return static_cast<int Base1::*>(ptr); +} + +// CIR: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi +// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [0] -> !cir.data_member<!s32i in !rec_Base1> + +// No LLVM instructions emitted for performing a zero-offset cast. + +// LLVM: define {{.*}} i64 @_Z27derived_to_base_zero_offsetM7Derivedi +// LLVM-NEXT: %[[PTR_ADDR:.*]] = alloca i64 +// LLVM-NEXT: %[[RETVAL:.*]] = alloca i64 +// LLVM-NEXT: store i64 %{{.*}}, ptr %[[PTR_ADDR]] +// LLVM-NEXT: %[[TEMP:.*]] = load i64, ptr %[[PTR_ADDR]] +// LLVM-NEXT: store i64 %[[TEMP]], ptr %[[RETVAL]] +// LLVM-NEXT: %[[RET:.*]] = load i64, ptr %[[RETVAL]] +// LLVM-NEXT: ret i64 %[[RET]] + +// OGCG: define {{.*}} i64 @_Z27derived_to_base_zero_offsetM7Derivedi +// OGCG-NEXT: entry: +// OGCG-NEXT: %[[PTR_ADDR:.*]] = alloca i64 +// OGCG-NEXT: store i64 %{{.*}}, ptr %[[PTR_ADDR]] +// OGCG-NEXT: %[[RET:.*]] = load i64, ptr %[[PTR_ADDR]] +// OGCG-NEXT: ret i64 %[[RET]] >From d643aeb3c8616fd589a32aee7f947aedbc602b8f Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Fri, 12 Dec 2025 09:20:22 -0800 Subject: [PATCH 2/5] Fix formatting --- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 4 ++-- .../Transforms/TargetLowering/LowerItaniumCXXABI.cpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 1fa9195224b79..3574cd356e9ce 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -2257,8 +2257,8 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) { const Type *qualifierType = qualifier.getAsType(); assert(qualifierType && "member pointer qualifier is not a type"); const CXXRecordDecl *derivedClass = qualifierType->getAsCXXRecordDecl(); - CharUnits offset = cgf.cgm.computeNonVirtualBaseClassOffset( - derivedClass, ce->path()); + CharUnits offset = + cgf.cgm.computeNonVirtualBaseClassOffset(derivedClass, ce->path()); mlir::Location loc = cgf.getLoc(subExpr->getExprLoc()); mlir::Type resultTy = cgf.convertType(destTy); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp index 21dc202602e15..20b09e8a5d52a 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp @@ -161,11 +161,16 @@ static mlir::Value lowerDataMemberCast(mlir::Operation *op, builder, loc, ty, mlir::IntegerAttr::get(ty, offset)); mlir::Value adjustedPtr; if (isDerivedToBase) - adjustedPtr = mlir::LLVM::SubOp::create(builder, loc, loweredSrc, offsetValue, mlir::LLVM::IntegerOverflowFlags::nsw); + adjustedPtr = + mlir::LLVM::SubOp::create(builder, loc, loweredSrc, offsetValue, + mlir::LLVM::IntegerOverflowFlags::nsw); else - adjustedPtr = mlir::LLVM::AddOp::create(builder, loc, loweredSrc, offsetValue, mlir::LLVM::IntegerOverflowFlags::nsw); + adjustedPtr = + mlir::LLVM::AddOp::create(builder, loc, loweredSrc, offsetValue, + mlir::LLVM::IntegerOverflowFlags::nsw); - return mlir::LLVM::SelectOp::create(builder, loc, isNull, loweredSrc, adjustedPtr); + return mlir::LLVM::SelectOp::create(builder, loc, isNull, loweredSrc, + adjustedPtr); } mlir::Value >From 0a07692ba130afb73c0c5afb10d64b9b22cc0f59 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Thu, 18 Dec 2025 16:13:14 -0800 Subject: [PATCH 3/5] Move lowering to cxxabi lowering pass --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 + .../CIR/Dialect/Transforms/CXXABILowering.cpp | 21 +++++++- .../TargetLowering/LowerItaniumCXXABI.cpp | 36 ++++++------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 ------- .../CodeGen/pointer-to-data-member-cast.cpp | 53 ++++++++++++++----- 5 files changed, 77 insertions(+), 53 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index a57b4275ebf25..8b4ed2bdb444f 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4202,6 +4202,7 @@ def CIR_BaseDataMemberOp : CIR_Op<"base_data_member", [Pure]> { }]; let hasVerifier = 1; + let hasLLVMLowering = false; } def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { @@ -4226,6 +4227,7 @@ def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { }]; let hasVerifier = 1; + let hasLLVMLowering = false; } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp index d586a3bf8974d..d2417de0d0ea3 100644 --- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp @@ -57,7 +57,8 @@ class CIRGenericCXXABILoweringPattern : public mlir::ConversionPattern { matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands, mlir::ConversionPatternRewriter &rewriter) const override { // Do not match on operations that have dedicated ABI lowering rewrite rules - if (llvm::isa<cir::AllocaOp, cir::ConstantOp, cir::FuncOp, + if (llvm::isa<cir::AllocaOp, cir::BaseDataMemberOp, cir::ConstantOp, + cir::DerivedDataMemberOp, cir::FuncOp, cir::GetRuntimeMemberOp, cir::GlobalOp>(op)) return mlir::failure(); @@ -209,6 +210,24 @@ mlir::LogicalResult CIRGlobalOpABILowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRBaseDataMemberOpABILowering::matchAndRewrite( + cir::BaseDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerModule->getCXXABI().lowerBaseDataMember( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + +mlir::LogicalResult CIRDerivedDataMemberOpABILowering::matchAndRewrite( + cir::DerivedDataMemberOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::Value loweredResult = lowerModule->getCXXABI().lowerDerivedDataMember( + op, adaptor.getSrc(), rewriter); + rewriter.replaceOp(op, loweredResult); + return mlir::success(); +} + mlir::LogicalResult CIRGetRuntimeMemberOpABILowering::matchAndRewrite( cir::GetRuntimeMemberOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp index 20b09e8a5d52a..c58e6c4f224f8 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerItaniumCXXABI.cpp @@ -151,26 +151,22 @@ static mlir::Value lowerDataMemberCast(mlir::Operation *op, mlir::Location loc = op->getLoc(); mlir::Type ty = loweredSrc.getType(); - auto nullValue = mlir::LLVM::ConstantOp::create( - builder, loc, ty, mlir::IntegerAttr::get(ty, -1)); - - auto isNull = mlir::LLVM::ICmpOp::create( - builder, loc, mlir::LLVM::ICmpPredicate::eq, loweredSrc, nullValue); - - auto offsetValue = mlir::LLVM::ConstantOp::create( - builder, loc, ty, mlir::IntegerAttr::get(ty, offset)); - mlir::Value adjustedPtr; - if (isDerivedToBase) - adjustedPtr = - mlir::LLVM::SubOp::create(builder, loc, loweredSrc, offsetValue, - mlir::LLVM::IntegerOverflowFlags::nsw); - else - adjustedPtr = - mlir::LLVM::AddOp::create(builder, loc, loweredSrc, offsetValue, - mlir::LLVM::IntegerOverflowFlags::nsw); - - return mlir::LLVM::SelectOp::create(builder, loc, isNull, loweredSrc, - adjustedPtr); + auto getConstantInt = [&](int64_t value) -> cir::ConstantOp { + return cir::ConstantOp::create(builder, loc, cir::IntAttr::get(ty, value)); + }; + + cir::ConstantOp nullValue = getConstantInt(-1); + auto isNull = cir::CmpOp::create(builder, loc, cir::CmpOpKind::eq, loweredSrc, + nullValue); + + cir::ConstantOp offsetValue = getConstantInt(offset); + auto binOpKind = isDerivedToBase ? cir::BinOpKind::Sub : cir::BinOpKind::Add; + cir::BinOp adjustedPtr = + cir::BinOp::create(builder, loc, ty, binOpKind, loweredSrc, offsetValue); + adjustedPtr.setNoSignedWrap(true); + + return cir::SelectOp::create(builder, loc, ty, isNull, loweredSrc, + adjustedPtr); } mlir::Value diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 5331d461d76d5..914233d8f6b8f 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1528,24 +1528,6 @@ mlir::LogicalResult CIRToLLVMDerivedClassAddrOpLowering::matchAndRewrite( return mlir::success(); } -mlir::LogicalResult CIRToLLVMBaseDataMemberOpLowering::matchAndRewrite( - cir::BaseDataMemberOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = - lowerMod->getCXXABI().lowerBaseDataMember(op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - -mlir::LogicalResult CIRToLLVMDerivedDataMemberOpLowering::matchAndRewrite( - cir::DerivedDataMemberOp op, OpAdaptor adaptor, - mlir::ConversionPatternRewriter &rewriter) const { - mlir::Value loweredResult = lowerMod->getCXXABI().lowerDerivedDataMember( - op, adaptor.getSrc(), rewriter); - rewriter.replaceOp(op, loweredResult); - return mlir::success(); -} - mlir::LogicalResult CIRToLLVMATanOpLowering::matchAndRewrite( cir::ATanOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp index e5c673d031a2e..db0012e51d2f9 100644 --- a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp +++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir %s -o %t.cir -// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-cir -mmlir -mlir-print-ir-before=cir-cxxabi-lowering %s -o %t.cir 2> %t-before.cir +// RUN: FileCheck --check-prefix=CIR-BEFORE --input-file=%t-before.cir %s +// RUN: FileCheck --check-prefix=CIR-AFTER --input-file=%t.cir %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -emit-llvm %s -o %t.ll @@ -21,9 +22,17 @@ auto base_to_derived(int Base2::*ptr) -> int Derived::* { return ptr; } -// CIR: cir.func {{.*}} @_Z15base_to_derivedM5Base2i -// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base2> [4] -> !cir.data_member<!s32i in !rec_Derived> +// CIR-BEFORE: cir.func {{.*}} @_Z15base_to_derivedM5Base2i +// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base2> [4] -> !cir.data_member<!s32i in !rec_Derived> + +// CIR-AFTER: cir.func {{.*}} @_Z15base_to_derivedM5Base2i +// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i +// CIR-AFTER: %[[NULL_VALUE:.*]] = cir.const #cir.int<-1> : !s64i +// CIR-AFTER: %[[IS_NULL:.*]] = cir.cmp(eq, %[[PTR]], %[[NULL_VALUE]]) +// CIR-AFTER: %[[OFFSET_VALUE:.*]] = cir.const #cir.int<4> : !s64i +// CIR-AFTER: %[[BINOP_KIND:.*]] = cir.binop(add, %[[PTR]], %[[OFFSET_VALUE]]) nsw : !s64i +// CIR-AFTER: %[[SELECT:.*]] = cir.select if %[[IS_NULL]] then %[[PTR]] else %[[BINOP_KIND]] // LLVM: define {{.*}} i64 @_Z15base_to_derivedM5Base2i // LLVM: %[[PTR:.*]] = load i64, ptr %{{.*}} @@ -41,9 +50,17 @@ auto derived_to_base(int Derived::*ptr) -> int Base2::* { return static_cast<int Base2::*>(ptr); } -// CIR: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi -// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [4] -> !cir.data_member<!s32i in !rec_Base2> +// CIR-BEFORE: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi +// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [4] -> !cir.data_member<!s32i in !rec_Base2> + +// CIR-AFTER: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi +// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i +// CIR-AFTER: %[[NULL_VALUE:.*]] = cir.const #cir.int<-1> : !s64i +// CIR-AFTER: %[[IS_NULL:.*]] = cir.cmp(eq, %[[PTR]], %[[NULL_VALUE]]) +// CIR-AFTER: %[[OFFSET_VALUE:.*]] = cir.const #cir.int<4> : !s64i +// CIR-AFTER: %[[BINOP_KIND:.*]] = cir.binop(sub, %[[PTR]], %[[OFFSET_VALUE]]) nsw : !s64i +// CIR-AFTER: %[[SELECT:.*]] = cir.select if %[[IS_NULL]] then %[[PTR]] else %[[BINOP_KIND]] // LLVM: define {{.*}} i64 @_Z15derived_to_baseM7Derivedi // LLVM: %[[PTR:.*]] = load i64, ptr %{{.*}} @@ -61,9 +78,13 @@ auto base_to_derived_zero_offset(int Base1::*ptr) -> int Derived::* { return ptr; } -// CIR: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i -// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base1> [0] -> !cir.data_member<!s32i in !rec_Derived> +// CIR-BEFORE: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i +// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base1> [0] -> !cir.data_member<!s32i in !rec_Derived> + +// CIR-AFTER: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i +// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i +// CIR-AFTER: cir.store %[[PTR]], %{{.*}} : !s64i, !cir.ptr<!s64i> // No LLVM instructions emitted for performing a zero-offset cast. @@ -87,9 +108,13 @@ auto derived_to_base_zero_offset(int Derived::*ptr) -> int Base1::* { return static_cast<int Base1::*>(ptr); } -// CIR: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi -// CIR: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [0] -> !cir.data_member<!s32i in !rec_Base1> +// CIR-BEFORE: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi +// CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} +// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [0] -> !cir.data_member<!s32i in !rec_Base1> + +// CIR-AFTER: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi +// CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i +// CIR-AFTER: cir.store %[[PTR]], %{{.*}} : !s64i, !cir.ptr<!s64i> // No LLVM instructions emitted for performing a zero-offset cast. >From 11ce747defa92e748e38a5becd8a65c3a43fa87a Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Tue, 6 Jan 2026 12:22:35 -0800 Subject: [PATCH 4/5] Update assembly format --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 6 ++---- clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 8b4ed2bdb444f..380b57a71121c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4197,8 +4197,7 @@ def CIR_BaseDataMemberOp : CIR_Op<"base_data_member", [Pure]> { let results = (outs CIR_DataMemberType:$result); let assemblyFormat = [{ - $src `:` qualified(type($src)) - ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict + $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict }]; let hasVerifier = 1; @@ -4222,8 +4221,7 @@ def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { let results = (outs CIR_DataMemberType:$result); let assemblyFormat = [{ - $src `:` qualified(type($src)) - ` ` `[` $offset `]` `->` qualified(type($result)) attr-dict + $src `[` $offset `]` `:` qualified(type($src)) `->` qualified(type($result)) attr-dict }]; let hasVerifier = 1; diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp index db0012e51d2f9..91cf4b1ae5386 100644 --- a/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp +++ b/clang/test/CIR/CodeGen/pointer-to-data-member-cast.cpp @@ -24,7 +24,7 @@ auto base_to_derived(int Base2::*ptr) -> int Derived::* { // CIR-BEFORE: cir.func {{.*}} @_Z15base_to_derivedM5Base2i // CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base2> [4] -> !cir.data_member<!s32i in !rec_Derived> +// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]][4] : !cir.data_member<!s32i in !rec_Base2> -> !cir.data_member<!s32i in !rec_Derived> // CIR-AFTER: cir.func {{.*}} @_Z15base_to_derivedM5Base2i // CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i @@ -52,7 +52,7 @@ auto derived_to_base(int Derived::*ptr) -> int Base2::* { // CIR-BEFORE: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi // CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [4] -> !cir.data_member<!s32i in !rec_Base2> +// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]][4] : !cir.data_member<!s32i in !rec_Derived> -> !cir.data_member<!s32i in !rec_Base2> // CIR-AFTER: cir.func {{.*}} @_Z15derived_to_baseM7Derivedi // CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i @@ -80,7 +80,7 @@ auto base_to_derived_zero_offset(int Base1::*ptr) -> int Derived::* { // CIR-BEFORE: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i // CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Base1> [0] -> !cir.data_member<!s32i in !rec_Derived> +// CIR-BEFORE: %[[RET:.*]] = cir.derived_data_member %[[PTR]][0] : !cir.data_member<!s32i in !rec_Base1> -> !cir.data_member<!s32i in !rec_Derived> // CIR-AFTER: cir.func {{.*}} @_Z27base_to_derived_zero_offsetM5Base1i // CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i @@ -110,7 +110,7 @@ auto derived_to_base_zero_offset(int Derived::*ptr) -> int Base1::* { // CIR-BEFORE: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi // CIR-BEFORE: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} -// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]] : !cir.data_member<!s32i in !rec_Derived> [0] -> !cir.data_member<!s32i in !rec_Base1> +// CIR-BEFORE: %[[RET:.*]] = cir.base_data_member %[[PTR]][0] : !cir.data_member<!s32i in !rec_Derived> -> !cir.data_member<!s32i in !rec_Base1> // CIR-AFTER: cir.func {{.*}} @_Z27derived_to_base_zero_offsetM7Derivedi // CIR-AFTER: %[[PTR:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s64i>, !s64i >From a59cdbee563f194f97a4a825717a78910e333b71 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Fri, 9 Jan 2026 15:10:49 -0800 Subject: [PATCH 5/5] Add flags for ABI lowering in op definitions --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 380b57a71121c..b8212735a2545 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -4202,6 +4202,7 @@ def CIR_BaseDataMemberOp : CIR_Op<"base_data_member", [Pure]> { let hasVerifier = 1; let hasLLVMLowering = false; + let hasCXXABILowering = true; } def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { @@ -4226,6 +4227,7 @@ def CIR_DerivedDataMemberOp : CIR_Op<"derived_data_member", [Pure]> { let hasVerifier = 1; let hasLLVMLowering = false; + let hasCXXABILowering = true; } //===----------------------------------------------------------------------===// _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
