Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace cir {
class ArrayType;
class BoolType;
class ComplexType;
class DataMemberType;
class IntType;
class MethodType;
class PointerType;
Expand Down
51 changes: 51 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,57 @@ def CIR_ConstPtrAttr : CIR_Attr<"ConstPtr", "ptr", [TypedAttrInterface]> {
}];
}

//===----------------------------------------------------------------------===//
// DataMemberAttr
//===----------------------------------------------------------------------===//

def CIR_DataMemberAttr : CIR_Attr<"DataMember", "data_member", [
TypedAttrInterface
]> {
let summary = "Holds a constant data member pointer value";
let parameters = (ins AttributeSelfTypeParameter<
"", "cir::DataMemberType">:$type,
OptionalParameter<
"std::optional<unsigned>">:$member_index);
let description = [{
A data member attribute is a literal attribute that represents a constant
pointer-to-data-member value.

The `member_index` parameter represents the index of the pointed-to member
within its containing record. It is an optional parameter; lack of this
parameter indicates a null pointer-to-data-member value.

Example:
```
#ptr = #cir.data_member<1> : !cir.data_member<!s32i in !rec_22Point22>

#null = #cir.data_member<null> : !cir.data_member<!s32i in !rec_22Point22>
```
}];

let builders = [
AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type), [{
return $_get(type.getContext(), type, std::nullopt);
}]>,
AttrBuilderWithInferredContext<(ins "cir::DataMemberType":$type,
"unsigned":$member_index), [{
return $_get(type.getContext(), type, member_index);
}]>,
];

let genVerifyDecl = 1;

let assemblyFormat = [{
`<` ($member_index^):(`null`)? `>`
}];

let extraClassDeclaration = [{
bool isNullPtr() const {
return !getMemberIndex().has_value();
}
}];
}

//===----------------------------------------------------------------------===//
// GlobalViewAttr
//===----------------------------------------------------------------------===//
Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,13 @@ def CIR_AnyFloatOrVecOfFloatType
let cppFunctionName = "isFPOrVectorOfFPType";
}

//===----------------------------------------------------------------------===//
// Data member type predicates
//===----------------------------------------------------------------------===//

def CIR_AnyDataMemberType : CIR_TypeBase<"::cir::DataMemberType",
"data member type">;

//===----------------------------------------------------------------------===//
// VPtr type predicates
//===----------------------------------------------------------------------===//
Expand All @@ -322,7 +329,8 @@ def CIR_PtrToVPtr : CIR_PtrToType<CIR_AnyVPtrType>;
//===----------------------------------------------------------------------===//

defvar CIR_ScalarTypes = [
CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType
CIR_AnyBoolType, CIR_AnyIntType, CIR_AnyFloatType, CIR_AnyPtrType,
CIR_AnyDataMemberType, CIR_AnyVPtrType
];

def CIR_AnyScalarType : AnyTypeOf<CIR_ScalarTypes, "cir scalar type"> {
Expand Down
32 changes: 31 additions & 1 deletion clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,36 @@ def CIR_PointerType : CIR_Type<"Pointer", "ptr", [
}];
}

//===----------------------------------------------------------------------===//
// CIR_DataMemberType
//===----------------------------------------------------------------------===//

def CIR_DataMemberType : CIR_Type<"DataMember", "data_member",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]
> {
let summary = "CIR type that represents a pointer-to-data-member in C++";
let description = [{
`cir.data_member` models a pointer-to-data-member in C++. Values of this
type are essentially offsets of the pointed-to member within one of its
containing record.
}];

let parameters = (ins "mlir::Type":$member_ty,
"cir::RecordType":$class_ty);

let builders = [
TypeBuilderWithInferredContext<(ins
"mlir::Type":$member_ty, "cir::RecordType":$class_ty
), [{
return $_get(member_ty.getContext(), member_ty, class_ty);
}]>,
];

let assemblyFormat = [{
`<` $member_ty `in` $class_ty `>`
}];
}

//===----------------------------------------------------------------------===//
// CIR_VPtrType
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -693,7 +723,7 @@ def CIRRecordType : Type<
def CIR_AnyType : AnyTypeOf<[
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
CIR_AnyFloatType, CIR_PointerType, CIR_FuncType, CIR_RecordType,
CIR_ComplexType, CIR_VPtrType
CIR_ComplexType, CIR_VPtrType, CIR_DataMemberType
]>;

#endif // CLANG_CIR_DIALECT_IR_CIRTYPES_TD
5 changes: 5 additions & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ struct MissingFeatures {
static bool globalCtorLexOrder() { return false; }
static bool globalCtorAssociatedData() { return false; }

// LowerModule handling
static bool lowerModuleCodeGenOpts() { return false; }
static bool lowerModuleLangOpts() { return false; }

// Misc
static bool aarch64SIMDIntrinsics() { return false; }
static bool aarch64SMEIntrinsics() { return false; }
Expand Down Expand Up @@ -293,6 +297,7 @@ struct MissingFeatures {
static bool lowerModeOptLevel() { return false; }
static bool loweringPrepareX86CXXABI() { return false; }
static bool loweringPrepareAArch64XXABI() { return false; }
static bool makeTripleAlwaysPresent() { return false; }
static bool maybeHandleStaticInExternC() { return false; }
static bool mergeAllConstants() { return false; }
static bool metaDataNode() { return false; }
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 @@ -189,6 +189,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
return getType<cir::RecordType>(nameAttr, kind);
}

cir::DataMemberAttr getDataMemberAttr(cir::DataMemberType ty,
unsigned memberIndex) {
return cir::DataMemberAttr::get(ty, memberIndex);
}

// Return true if the value is a null constant such as null pointer, (+0.0)
// for floating-point or zero initializer
bool isNullValue(mlir::Attribute attr) const {
Expand Down
7 changes: 2 additions & 5 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,11 +640,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}

mlir::Value VisitUnaryAddrOf(const UnaryOperator *e) {
if (llvm::isa<MemberPointerType>(e->getType())) {
cgf.cgm.errorNYI(e->getSourceRange(), "Address of member pointer");
return builder.getNullPtr(cgf.convertType(e->getType()),
cgf.getLoc(e->getExprLoc()));
}
if (llvm::isa<MemberPointerType>(e->getType()))
return cgf.cgm.emitMemberPointerConstant(e);

return cgf.emitLValue(e->getSubExpr()).getPointer();
}
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1464,6 +1464,26 @@ void CIRGenModule::emitExplicitCastExprType(const ExplicitCastExpr *e,
"emitExplicitCastExprType");
}

mlir::Value CIRGenModule::emitMemberPointerConstant(const UnaryOperator *e) {
assert(!cir::MissingFeatures::cxxABI());

mlir::Location loc = getLoc(e->getSourceRange());

const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();

// A member function pointer.
if (isa<CXXMethodDecl>(decl)) {
errorNYI(e->getSourceRange(), "emitMemberPointerConstant: method pointer");
return {};
}

// Otherwise, a member data pointer.
auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
const auto *fieldDecl = cast<FieldDecl>(decl);
return cir::ConstantOp::create(
builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
}

void CIRGenModule::emitDeclContext(const DeclContext *dc) {
for (Decl *decl : dc->decls()) {
// Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ class CIRGenModule : public CIRGenTypeCache {
/// the given type. This is usually, but not always, an LLVM null constant.
mlir::TypedAttr emitNullConstantForBase(const CXXRecordDecl *record);

mlir::Value emitMemberPointerConstant(const UnaryOperator *e);

llvm::StringRef getMangledName(clang::GlobalDecl gd);

void emitTentativeDefinition(const VarDecl *d);
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,21 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
break;
}

case Type::MemberPointer: {
const auto *mpt = cast<MemberPointerType>(ty);

mlir::Type memberTy = convertType(mpt->getPointeeType());
auto clsTy = mlir::cast<cir::RecordType>(
convertType(QualType(mpt->getQualifier().getAsType(), 0)));
if (mpt->isMemberDataPointer()) {
resultType = cir::DataMemberType::get(memberTy, clsTy);
} else {
assert(!cir::MissingFeatures::methodType());
cgm.errorNYI(SourceLocation(), "MethodType");
}
break;
}

case Type::FunctionNoProto:
case Type::FunctionProto:
resultType = convertFunctionTypeInternal(type);
Expand Down
32 changes: 32 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,38 @@ ConstComplexAttr::verify(function_ref<InFlightDiagnostic()> emitError,
return success();
}

//===----------------------------------------------------------------------===//
// DataMemberAttr definitions
//===----------------------------------------------------------------------===//

LogicalResult
DataMemberAttr::verify(function_ref<InFlightDiagnostic()> emitError,
cir::DataMemberType ty,
std::optional<unsigned> memberIndex) {
// DataMemberAttr without a given index represents a null value.
if (!memberIndex.has_value())
return success();

cir::RecordType recTy = ty.getClassTy();
if (recTy.isIncomplete())
return emitError()
<< "incomplete 'cir.record' cannot be used to build a non-null "
"data member pointer";

unsigned memberIndexValue = memberIndex.value();
if (memberIndexValue >= recTy.getNumElements())
return emitError()
<< "member index of a #cir.data_member attribute is out of range";

mlir::Type memberTy = recTy.getMembers()[memberIndexValue];
if (memberTy != ty.getMemberTy())
return emitError()
<< "member type of a #cir.data_member attribute must match the "
"attribute type";

return success();
}

//===----------------------------------------------------------------------===//
// CIR ConstArrayAttr
//===----------------------------------------------------------------------===//
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}

if (isa<cir::DataMemberAttr>(attrType)) {
// More detailed type verifications are already done in
// DataMemberAttr::verify. Don't need to repeat here.
return success();
}

if (isa<cir::ZeroAttr>(attrType)) {
if (isa<cir::RecordType, cir::ArrayType, cir::VectorType, cir::ComplexType>(
opType))
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,26 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
return 1;
}

//===----------------------------------------------------------------------===//
// DataMemberType Definitions
//===----------------------------------------------------------------------===//

llvm::TypeSize
DataMemberType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
::mlir::DataLayoutEntryListRef params) const {
// FIXME: consider size differences under different ABIs
assert(!MissingFeatures::cxxABI());
return llvm::TypeSize::getFixed(64);
}

uint64_t
DataMemberType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
::mlir::DataLayoutEntryListRef params) const {
// FIXME: consider alignment differences under different ABIs
assert(!MissingFeatures::cxxABI());
return 8;
}

//===----------------------------------------------------------------------===//
// VPtrType Definitions
//===----------------------------------------------------------------------===//
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CIR/Dialect/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
add_subdirectory(TargetLowering)

add_clang_library(MLIRCIRTransforms
CIRCanonicalize.cpp
CIRSimplify.cpp
Expand All @@ -21,4 +23,5 @@ add_clang_library(MLIRCIRTransforms

MLIRCIR
MLIRCIRInterfaces
MLIRCIRTargetLowering
)
20 changes: 20 additions & 0 deletions clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRCXXABI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===- CIRCXXABI.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file partially mimics clang/lib/CodeGen/CGCXXABI.cpp. The queries are
// adapted to operate on the CIR dialect, however.
//
//===----------------------------------------------------------------------===//

#include "CIRCXXABI.h"

namespace cir {

CIRCXXABI::~CIRCXXABI() {}

} // namespace cir
Loading
Loading