Skip to content

Commit e91f537

Browse files
committed
[CIR] Upstream TypeInfo attribute
1 parent 8009a5b commit e91f537

File tree

4 files changed

+101
-2
lines changed

4 files changed

+101
-2
lines changed

clang/include/clang/CIR/Dialect/IR/CIRAttrs.td

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,4 +779,52 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", "address_point"> {
779779
}];
780780
}
781781

782+
//===----------------------------------------------------------------------===//
783+
// TypeInfoAttr
784+
//===----------------------------------------------------------------------===//
785+
786+
def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
787+
let summary = "Represents a typeinfo used for RTTI";
788+
let description = [{
789+
The typeinfo data for a given class is stored into an ArrayAttr. The
790+
layout is determined by the C++ ABI used (clang only implements
791+
itanium on CIRGen).
792+
793+
The verifier enforces that the output type is always a `!cir.record`,
794+
and that the ArrayAttr element types match the equivalent member type
795+
for the resulting record, i.e, a GlobalViewAttr for symbol reference or
796+
an IntAttr for flags.
797+
798+
Example:
799+
800+
```
801+
cir.global "private" external @_ZTVN10__cxxabiv120__si_class_type_infoE : !cir.ptr<i32>
802+
803+
!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
804+
805+
cir.global constant external @type_info = #cir.typeinfo<{
806+
#cir.global_view<@_ZTVN10__cxxabiv120__si_class_type_infoE, [2 : i32]>
807+
: !cir.ptr<!u8i>, #cir.global_view<@_ZTS1B> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A>
808+
: !cir.ptr<!u8i>}> : !rec_anon_struct
809+
```
810+
}];
811+
812+
let parameters = (ins AttributeSelfTypeParameter<"">:$type,
813+
"mlir::ArrayAttr":$data);
814+
815+
let builders = [
816+
AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
817+
"mlir::ArrayAttr":$data), [{
818+
return $_get(type.getContext(), type, data);
819+
}]>
820+
];
821+
822+
// Checks record element types should match the array for every equivalent
823+
// element type.
824+
let genVerifyDecl = 1;
825+
let assemblyFormat = [{
826+
`<` custom<RecordMembers>($data) `>`
827+
}];
828+
}
829+
782830
#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
342342

343343
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
344344
cir::ConstComplexAttr, cir::ConstRecordAttr,
345-
cir::GlobalViewAttr, cir::PoisonAttr, cir::VTableAttr>(
346-
attrType))
345+
cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
346+
cir::VTableAttr>(attrType))
347347
return success();
348348

349349
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
@@ -2741,6 +2741,25 @@ LogicalResult cir::AtomicCmpXchg::verify() {
27412741
return success();
27422742
}
27432743

2744+
//===----------------------------------------------------------------------===//
2745+
// TypeInfoAttr
2746+
//===----------------------------------------------------------------------===//
2747+
2748+
LogicalResult cir::TypeInfoAttr::verify(
2749+
::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
2750+
::mlir::Type type, ::mlir::ArrayAttr typeinfoData) {
2751+
2752+
if (cir::ConstRecordAttr::verify(emitError, type, typeinfoData).failed())
2753+
return failure();
2754+
2755+
for (auto &member : typeinfoData) {
2756+
if (llvm::isa<GlobalViewAttr, IntAttr>(member))
2757+
continue;
2758+
return emitError() << "expected GlobalViewAttr or IntAttr attribute";
2759+
}
2760+
return success();
2761+
}
2762+
27442763
//===----------------------------------------------------------------------===//
27452764
// TableGen'd op method definitions
27462765
//===----------------------------------------------------------------------===//

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ class CIRAttrToValue {
235235
mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
236236
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
237237
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
238+
mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
238239
mlir::Value visitCirAttr(cir::VTableAttr attr);
239240
mlir::Value visitCirAttr(cir::ZeroAttr attr);
240241

@@ -521,6 +522,20 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
521522
llvm_unreachable("Expecting pointer or integer type for GlobalViewAttr");
522523
}
523524

525+
// TypeInfoAttr visitor.
526+
mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeinfoArr) {
527+
mlir::Type llvmTy = converter->convertType(typeinfoArr.getType());
528+
mlir::Location loc = parentOp->getLoc();
529+
mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
530+
531+
for (auto [idx, elt] : llvm::enumerate(typeinfoArr.getData())) {
532+
mlir::Value init = visit(elt);
533+
result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
534+
}
535+
536+
return result;
537+
}
538+
524539
// VTableAttr visitor.
525540
mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
526541
mlir::Type llvmTy = converter->convertType(vtableArr.getType());
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: cir-opt %s -verify-diagnostics -split-input-file
2+
3+
!u8i = !cir.int<u, 8>
4+
5+
!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
6+
7+
// expected-error @below {{expected !cir.record type}}
8+
cir.global constant external @type_info = #cir.typeinfo<{#cir.global_view<@_ZTVN10__cxxabiv120__si_class_type_infoE, [2 : i32]> : !cir.ptr<!u8i>, #cir.global_view<@_ZTS1B> : !cir.ptr<!u8i>, #cir.global_view<@_ZTI1A> : !cir.ptr<!u8i>}> : !u8i
9+
10+
// -----
11+
12+
!u8i = !cir.int<u, 8>
13+
14+
!rec_anon_struct = !cir.record<struct {!u8i, !u8i, !u8i}>
15+
16+
// expected-error @below {{expected GlobalViewAttr or IntAttr attribute}}
17+
cir.global constant external @type_info = #cir.typeinfo<{ #cir.undef : !u8i, #cir.int<1> : !u8i, #cir.int<1> : !u8i}> : !rec_anon_struct

0 commit comments

Comments
 (0)