Skip to content
Open
Show file tree
Hide file tree
Changes from all 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