-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[CIR] Upstream TypeInfo attribute #159426
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for TypeInfoAttr which is needed later for RTTI in exceptions Issue #154992 Full diff: https://github.com/llvm/llvm-project/pull/159426.diff 4 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 16b818f851e1c..10afd7133eed3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -779,4 +779,52 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", "address_point"> {
}];
}
+//===----------------------------------------------------------------------===//
+// TypeInfoAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
+ let summary = "Represents a typeinfo used for RTTI";
+ let description = [{
+ The typeinfo data for a given class is stored into an ArrayAttr. The
+ layout is determined by the C++ ABI used (clang only implements
+ itanium on CIRGen).
+
+ The verifier enforces that the output type is always a `!cir.record`,
+ and that the ArrayAttr element types match the equivalent member type
+ for the resulting record, i.e, a GlobalViewAttr for symbol reference or
+ an IntAttr for flags.
+
+ Example:
+
+ ```
+ cir.global "private" external @_ZTVN10__cxxabiv120__si_class_type_infoE : !cir.ptr<i32>
+
+ !rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
+
+ 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>}> : !rec_anon_struct
+ ```
+ }];
+
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+ "mlir::ArrayAttr":$data);
+
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
+ "mlir::ArrayAttr":$data), [{
+ return $_get(type.getContext(), type, data);
+ }]>
+ ];
+
+ // Checks record element types should match the array for every equivalent
+ // element type.
+ let genVerifyDecl = 1;
+ let assemblyFormat = [{
+ `<` custom<RecordMembers>($data) `>`
+ }];
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8918eb4cbb1ad..3fcc0aad9b11b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -342,8 +342,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
- cir::GlobalViewAttr, cir::PoisonAttr, cir::VTableAttr>(
- attrType))
+ cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
+ cir::VTableAttr>(attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
@@ -2741,6 +2741,25 @@ LogicalResult cir::AtomicCmpXchg::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// TypeInfoAttr
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::TypeInfoAttr::verify(
+ ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
+ ::mlir::Type type, ::mlir::ArrayAttr typeinfoData) {
+
+ if (cir::ConstRecordAttr::verify(emitError, type, typeinfoData).failed())
+ return failure();
+
+ for (auto &member : typeinfoData) {
+ if (llvm::isa<GlobalViewAttr, IntAttr>(member))
+ continue;
+ return emitError() << "expected GlobalViewAttr or IntAttr attribute";
+ }
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 1d7e3df1430ac..0c0c28a5cc379 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -235,6 +235,7 @@ class CIRAttrToValue {
mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
+ mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
mlir::Value visitCirAttr(cir::VTableAttr attr);
mlir::Value visitCirAttr(cir::ZeroAttr attr);
@@ -521,6 +522,20 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
llvm_unreachable("Expecting pointer or integer type for GlobalViewAttr");
}
+// TypeInfoAttr visitor.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeinfoArr) {
+ mlir::Type llvmTy = converter->convertType(typeinfoArr.getType());
+ mlir::Location loc = parentOp->getLoc();
+ mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
+
+ for (auto [idx, elt] : llvm::enumerate(typeinfoArr.getData())) {
+ mlir::Value init = visit(elt);
+ result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
+ }
+
+ return result;
+}
+
// VTableAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
mlir::Type llvmTy = converter->convertType(vtableArr.getType());
diff --git a/clang/test/CIR/IR/invalid-type-info.cir b/clang/test/CIR/IR/invalid-type-info.cir
new file mode 100644
index 0000000000000..9a6c0d7234021
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-type-info.cir
@@ -0,0 +1,17 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!u8i = !cir.int<u, 8>
+
+!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
+
+// expected-error @below {{expected !cir.record type}}
+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
+
+// -----
+
+!u8i = !cir.int<u, 8>
+
+!rec_anon_struct = !cir.record<struct {!u8i, !u8i, !u8i}>
+
+// expected-error @below {{expected GlobalViewAttr or IntAttr attribute}}
+cir.global constant external @type_info = #cir.typeinfo<{ #cir.undef : !u8i, #cir.int<1> : !u8i, #cir.int<1> : !u8i}> : !rec_anon_struct
|
@llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) ChangesThis change adds support for TypeInfoAttr which is needed later for RTTI in exceptions Issue #154992 Full diff: https://github.com/llvm/llvm-project/pull/159426.diff 4 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 16b818f851e1c..10afd7133eed3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -779,4 +779,52 @@ def CIR_AddressPointAttr : CIR_Attr<"AddressPoint", "address_point"> {
}];
}
+//===----------------------------------------------------------------------===//
+// TypeInfoAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_TypeInfoAttr : CIR_Attr<"TypeInfo", "typeinfo", [TypedAttrInterface]> {
+ let summary = "Represents a typeinfo used for RTTI";
+ let description = [{
+ The typeinfo data for a given class is stored into an ArrayAttr. The
+ layout is determined by the C++ ABI used (clang only implements
+ itanium on CIRGen).
+
+ The verifier enforces that the output type is always a `!cir.record`,
+ and that the ArrayAttr element types match the equivalent member type
+ for the resulting record, i.e, a GlobalViewAttr for symbol reference or
+ an IntAttr for flags.
+
+ Example:
+
+ ```
+ cir.global "private" external @_ZTVN10__cxxabiv120__si_class_type_infoE : !cir.ptr<i32>
+
+ !rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
+
+ 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>}> : !rec_anon_struct
+ ```
+ }];
+
+ let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+ "mlir::ArrayAttr":$data);
+
+ let builders = [
+ AttrBuilderWithInferredContext<(ins "mlir::Type":$type,
+ "mlir::ArrayAttr":$data), [{
+ return $_get(type.getContext(), type, data);
+ }]>
+ ];
+
+ // Checks record element types should match the array for every equivalent
+ // element type.
+ let genVerifyDecl = 1;
+ let assemblyFormat = [{
+ `<` custom<RecordMembers>($data) `>`
+ }];
+}
+
#endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 8918eb4cbb1ad..3fcc0aad9b11b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -342,8 +342,8 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
if (mlir::isa<cir::ConstArrayAttr, cir::ConstVectorAttr,
cir::ConstComplexAttr, cir::ConstRecordAttr,
- cir::GlobalViewAttr, cir::PoisonAttr, cir::VTableAttr>(
- attrType))
+ cir::GlobalViewAttr, cir::PoisonAttr, cir::TypeInfoAttr,
+ cir::VTableAttr>(attrType))
return success();
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
@@ -2741,6 +2741,25 @@ LogicalResult cir::AtomicCmpXchg::verify() {
return success();
}
+//===----------------------------------------------------------------------===//
+// TypeInfoAttr
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::TypeInfoAttr::verify(
+ ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
+ ::mlir::Type type, ::mlir::ArrayAttr typeinfoData) {
+
+ if (cir::ConstRecordAttr::verify(emitError, type, typeinfoData).failed())
+ return failure();
+
+ for (auto &member : typeinfoData) {
+ if (llvm::isa<GlobalViewAttr, IntAttr>(member))
+ continue;
+ return emitError() << "expected GlobalViewAttr or IntAttr attribute";
+ }
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// TableGen'd op method definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 1d7e3df1430ac..0c0c28a5cc379 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -235,6 +235,7 @@ class CIRAttrToValue {
mlir::Value visitCirAttr(cir::ConstRecordAttr attr);
mlir::Value visitCirAttr(cir::ConstVectorAttr attr);
mlir::Value visitCirAttr(cir::GlobalViewAttr attr);
+ mlir::Value visitCirAttr(cir::TypeInfoAttr attr);
mlir::Value visitCirAttr(cir::VTableAttr attr);
mlir::Value visitCirAttr(cir::ZeroAttr attr);
@@ -521,6 +522,20 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) {
llvm_unreachable("Expecting pointer or integer type for GlobalViewAttr");
}
+// TypeInfoAttr visitor.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeinfoArr) {
+ mlir::Type llvmTy = converter->convertType(typeinfoArr.getType());
+ mlir::Location loc = parentOp->getLoc();
+ mlir::Value result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
+
+ for (auto [idx, elt] : llvm::enumerate(typeinfoArr.getData())) {
+ mlir::Value init = visit(elt);
+ result = rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
+ }
+
+ return result;
+}
+
// VTableAttr visitor.
mlir::Value CIRAttrToValue::visitCirAttr(cir::VTableAttr vtableArr) {
mlir::Type llvmTy = converter->convertType(vtableArr.getType());
diff --git a/clang/test/CIR/IR/invalid-type-info.cir b/clang/test/CIR/IR/invalid-type-info.cir
new file mode 100644
index 0000000000000..9a6c0d7234021
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-type-info.cir
@@ -0,0 +1,17 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!u8i = !cir.int<u, 8>
+
+!rec_anon_struct = !cir.record<struct {!cir.ptr<!u8i>, !cir.ptr<!u8i>, !cir.ptr<!u8i>}>
+
+// expected-error @below {{expected !cir.record type}}
+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
+
+// -----
+
+!u8i = !cir.int<u, 8>
+
+!rec_anon_struct = !cir.record<struct {!u8i, !u8i, !u8i}>
+
+// expected-error @below {{expected GlobalViewAttr or IntAttr attribute}}
+cir.global constant external @type_info = #cir.typeinfo<{ #cir.undef : !u8i, #cir.int<1> : !u8i, #cir.int<1> : !u8i}> : !rec_anon_struct
|
for (auto &member : typeinfoData) { | ||
if (llvm::isa<GlobalViewAttr, IntAttr>(member)) | ||
continue; | ||
return emitError() << "expected GlobalViewAttr or IntAttr attribute"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be chacked with ArrayOfAttr
as constriant in the definition
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did it, it was very nice to learn how to do it, thanks 👍🏻
Note: I used TypedArrayAttrBase
with either Int or GV, if ArrayOfAttr is better i can switch to it and build constraints with it
@@ -521,6 +522,20 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::GlobalViewAttr globalAttr) { | |||
llvm_unreachable("Expecting pointer or integer type for GlobalViewAttr"); | |||
} | |||
|
|||
// TypeInfoAttr visitor. | |||
mlir::Value CIRAttrToValue::visitCirAttr(cir::TypeInfoAttr typeinfoArr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename typeinfoArr
to typeInfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we rename it to typeInfo
or typeInfoAttr
similar to other parameters in visitors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah typeInfoAttr
is probably even better :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm % minor nits
564f6ba
to
25e2f3a
Compare
This change adds support for TypeInfoAttr which is needed later for RTTI in exceptions
Issue #154992