From 4795e86e57c3c5f1c596f377438f5471949986b3 Mon Sep 17 00:00:00 2001 From: Sirui Mu Date: Sat, 20 Jan 2024 12:02:14 +0800 Subject: [PATCH] Add support for null ptr-to-data-member values --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 12 ++++++ clang/lib/CIR/CodeGen/CIRGenBuilder.h | 5 +++ clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 15 ++++++- clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 41 +++++++++++++------ .../CIR/CodeGen/pointer-to-data-member.cpp | 14 +++++++ 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 58c771e2dc7c..4ae15dc4b4c0 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -248,8 +248,20 @@ def DataMemberPtrAttr : CIR_Attr<"DataMemberPtr", "data_member_ptr", return $_get(type.getContext(), type, clsTy, IntegerAttr::get(IndexType::get(type.getContext()), memberIndex)); }]>, + AttrBuilderWithInferredContext<(ins "Type":$type), [{ + mlir::Type clsTy = type.cast().getClsTy(); + return $_get(type.getContext(), type, clsTy, + IntegerAttr::get(IndexType::get(type.getContext()), -1)); + }]>, ]; + let extraClassDeclaration = [{ + /// Determine whether the data member pointer is a null pointer value. + bool isNullValue() const { + return getMemberIndex().getValue().isNegative(); + } + }]; + let hasCustomAssemblyFormat = 1; let genVerifyDecl = 1; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index abf1e585107d..4ec02d916a53 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -226,6 +226,11 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy { return mlir::cir::DataMemberPtrAttr::get(ty, ty.getClsTy(), memberIndex); } + mlir::cir::DataMemberPtrAttr + getNullDataMemberPtrAttr(mlir::cir::MemberPtrType ty) { + return mlir::cir::DataMemberPtrAttr::get(ty); + } + mlir::TypedAttr getZeroInitAttr(mlir::Type ty) { if (ty.isa()) return mlir::cir::IntAttr::get(ty, 0); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 77878ef3cf3e..3f532bb02e41 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1422,8 +1422,19 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { mlir::cir::ConstPtrAttr::get(Builder.getContext(), Ty, 0)); } - case CK_NullToMemberPointer: - llvm_unreachable("NYI"); + case CK_NullToMemberPointer: { + if (MustVisitNullValue(E)) + CGF.buildIgnoredExpr(E); + + assert(!UnimplementedFeature::cxxABI()); + + const MemberPointerType *MPT = CE->getType()->getAs(); + assert(!MPT->isMemberFunctionPointerType() && "NYI"); + + auto Ty = CGF.getCIRType(DestTy).cast(); + return Builder.create( + CGF.getLoc(E->getExprLoc()), Ty, Builder.getNullDataMemberPtrAttr(Ty)); + } case CK_ReinterpretMemberPointer: llvm_unreachable("NYI"); case CK_BaseToDerivedMemberPointer: diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 75a3e16a7718..77c38a95c9bb 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -306,15 +306,21 @@ Attribute DataMemberPtrAttr::parse(AsmParser &parser, Type type) { return {}; Type clsTy; - if (parser.parseType(clsTy)) - return {}; + std::int64_t memberIndex; - if (parser.parseComma()) - return {}; + if (parser.parseOptionalKeyword("null").succeeded()) { + clsTy = type.cast().getClsTy(); + memberIndex = -1; + } else { + if (parser.parseType(clsTy)) + return {}; - std::uint64_t memberIndex; - if (parser.parseInteger(memberIndex)) - return {}; + if (parser.parseComma()) + return {}; + + if (parser.parseInteger(memberIndex)) + return {}; + } if (parser.parseGreater()) return {}; @@ -328,9 +334,15 @@ Attribute DataMemberPtrAttr::parse(AsmParser &parser, Type type) { void DataMemberPtrAttr::print(AsmPrinter &printer) const { printer << '<'; - printer.printType(getClsTy()); - printer << ", "; - printer << getMemberIndex().getValue().getZExtValue(); + + if (isNullValue()) + printer << "null"; + else { + printer.printType(getClsTy()); + printer << ", "; + printer << getMemberIndex().getValue().getZExtValue(); + } + printer << '>'; } @@ -366,12 +378,17 @@ DataMemberPtrAttr::verify(function_ref emitError, Type ty, return failure(); } - auto memberIndexValue = memberIndex.getValue().getZExtValue(); - if (memberIndexValue >= clsStructTy.getNumElements()) { + auto memberIndexValue = memberIndex.getValue().getSExtValue(); + if (memberIndexValue >= static_cast(clsStructTy.getNumElements())) { emitError() << "member index of a DataMemberPtrAttr is out of range"; return failure(); } + if (memberIndexValue < 0) { + // DataMemberPtrAttr with a negative member index represents null value. + return success(); + } + auto memberTy = clsStructTy.getMembers()[memberIndexValue]; if (memberTy != memberPtrTy.getMemberTy()) { emitError() diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp index 0f59529a6e65..c92c28d59b78 100644 --- a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp +++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp @@ -46,3 +46,17 @@ int test5(Incomplete *ic, int Incomplete::*member) { // CHECK: cir.func @_Z5test5P10IncompleteMS_i // CHECK: %{{.+}} = cir.get_indirect_member %{{.+}}[%{{.+}} : !cir.member_ptr] : !cir.ptr -> !cir.ptr // CHECK: } + +auto test_null() -> int Point::* { + return nullptr; +} +// CHECK: cir.func @_Z9test_nullv +// CHECK: %{{.+}} = cir.const(#cir.data_member_ptr : !cir.member_ptr) : !cir.member_ptr +// CHECK: } + +auto test_null_incomplete() -> int Incomplete::* { + return nullptr; +} +// CHECK: cir.func @_Z20test_null_incompletev +// CHECK: %{{.+}} = cir.const(#cir.data_member_ptr : !cir.member_ptr) : !cir.member_ptr +// CHECK: }