Skip to content

Commit

Permalink
Add support for null ptr-to-data-member values
Browse files Browse the repository at this point in the history
  • Loading branch information
Lancern committed Jan 20, 2024
1 parent c2e33c5 commit 4795e86
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 14 deletions.
12 changes: 12 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::MemberPtrType>().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;
}
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::IntType>())
return mlir::cir::IntAttr::get(ty, 0);
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MemberPointerType>();
assert(!MPT->isMemberFunctionPointerType() && "NYI");

auto Ty = CGF.getCIRType(DestTy).cast<mlir::cir::MemberPtrType>();
return Builder.create<mlir::cir::ConstantOp>(
CGF.getLoc(E->getExprLoc()), Ty, Builder.getNullDataMemberPtrAttr(Ty));
}
case CK_ReinterpretMemberPointer:
llvm_unreachable("NYI");
case CK_BaseToDerivedMemberPointer:
Expand Down
41 changes: 29 additions & 12 deletions clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<mlir::cir::MemberPtrType>().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 {};
Expand All @@ -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 << '>';
}

Expand Down Expand Up @@ -366,12 +378,17 @@ DataMemberPtrAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type ty,
return failure();
}

auto memberIndexValue = memberIndex.getValue().getZExtValue();
if (memberIndexValue >= clsStructTy.getNumElements()) {
auto memberIndexValue = memberIndex.getValue().getSExtValue();
if (memberIndexValue >= static_cast<int64_t>(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()
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CIR/CodeGen/pointer-to-data-member.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,17 @@ int test5(Incomplete *ic, int Incomplete::*member) {
// CHECK: cir.func @_Z5test5P10IncompleteMS_i
// CHECK: %{{.+}} = cir.get_indirect_member %{{.+}}[%{{.+}} : !cir.member_ptr<!s32i in !ty_22Incomplete22>] : !cir.ptr<!ty_22Incomplete22> -> !cir.ptr<!s32i>
// CHECK: }

auto test_null() -> int Point::* {
return nullptr;
}
// CHECK: cir.func @_Z9test_nullv
// CHECK: %{{.+}} = cir.const(#cir.data_member_ptr<null> : !cir.member_ptr<!s32i in !ty_22Point22>) : !cir.member_ptr<!s32i in !ty_22Point22>
// CHECK: }

auto test_null_incomplete() -> int Incomplete::* {
return nullptr;
}
// CHECK: cir.func @_Z20test_null_incompletev
// CHECK: %{{.+}} = cir.const(#cir.data_member_ptr<null> : !cir.member_ptr<!s32i in !ty_22Incomplete22>) : !cir.member_ptr<!s32i in !ty_22Incomplete22>
// CHECK: }

0 comments on commit 4795e86

Please sign in to comment.