-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[CIR] Upstream basic support for ArrayType #130502
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
There will be two upcoming patches. 1 - Initializing const array and zero initializing support (Depends on upstreaming |
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesThis change adds the basic support for ArrayType Issue #130197 Full diff: https://github.com/llvm/llvm-project/pull/130502.diff 7 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
index 438fb7d09608d..1451ea47c50c8 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.h
@@ -30,6 +30,10 @@ class VarDecl;
class RecordDecl;
} // namespace clang
+namespace cir {
+class ArrayType;
+} // namespace cir
+
#define GET_ATTRDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsAttributes.h.inc"
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index a78e5eae08e33..b2bac643b62da 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -280,6 +280,25 @@ def CIR_BoolType :
}];
}
+//===----------------------------------------------------------------------===//
+// ArrayType
+//===----------------------------------------------------------------------===//
+
+def CIR_ArrayType : CIR_Type<"Array", "array",
+ [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+
+ let summary = "CIR array type";
+ let description = [{
+ `CIR.array` represents C/C++ constant arrays.
+ }];
+
+ let parameters = (ins "mlir::Type":$eltType, "uint64_t":$size);
+
+ let assemblyFormat = [{
+ `<` $eltType `x` $size `>`
+ }];
+}
+
//===----------------------------------------------------------------------===//
// FuncType
//===----------------------------------------------------------------------===//
@@ -386,7 +405,7 @@ def VoidPtr : Type<
//===----------------------------------------------------------------------===//
def CIR_AnyType : AnyTypeOf<[
- CIR_VoidType, CIR_BoolType, CIR_IntType, CIR_AnyFloat, CIR_PointerType,
+ CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_IntType, CIR_AnyFloat, CIR_PointerType,
CIR_FuncType
]>;
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 01d56963883cc..250192ec254d1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -33,6 +33,14 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
llvm_unreachable("NYI: PPC double-double format for long double");
llvm_unreachable("Unsupported format for long double");
}
+
+ bool isSized(mlir::Type ty) {
+ if (mlir::isa<cir::PointerType, cir::ArrayType, cir::BoolType,
+ cir::IntType>(ty))
+ return true;
+ assert(0 && "Unimplemented size for type");
+ return false;
+ }
};
} // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index dcfaaedc2ef57..78e894dee0071 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -202,6 +202,18 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
break;
}
+ case Type::ConstantArray: {
+ const ConstantArrayType *arrTy = cast<ConstantArrayType>(ty);
+ mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
+
+ // FIXME: In LLVM, "lower arrays of undefined struct type to arrays of
+ // i8 just to have a concrete type". Not sure this makes sense in CIR yet.
+ assert(builder.isSized(elemTy) && "not implemented");
+ resultType = cir::ArrayType::get(builder.getContext(), elemTy,
+ arrTy->getSize().getZExtValue());
+ break;
+ }
+
case Type::FunctionNoProto:
case Type::FunctionProto:
resultType = convertFunctionTypeInternal(type);
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 5ad369b40cda1..1e078e2797270 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -166,6 +166,9 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
return success();
}
+ if (mlir::isa<cir::ArrayType>(opType))
+ return success();
+
assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
return op->emitOpError("global with type ")
<< cast<TypedAttr>(attrType).getType() << " not yet supported";
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 8bdde54ad41f6..6291297492227 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -369,6 +369,22 @@ BoolType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
return 1;
}
+//===----------------------------------------------------------------------===//
+// Definitions
+//===----------------------------------------------------------------------===//
+
+llvm::TypeSize
+ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout,
+ ::mlir::DataLayoutEntryListRef params) const {
+ return getSize() * dataLayout.getTypeSizeInBits(getEltType());
+}
+
+uint64_t
+ArrayType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+ ::mlir::DataLayoutEntryListRef params) const {
+ return dataLayout.getTypeABIAlignment(getEltType());
+}
+
//===----------------------------------------------------------------------===//
// PointerType Definitions
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
new file mode 100644
index 0000000000000..3a5950ffe3d87
--- /dev/null
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
+
+int a[10];
+// CHECK: cir.global external @a : !cir.array<!cir.int<s, 32> x 10>
+
+extern int b[10];
+// CHECK: cir.global external @b : !cir.array<!cir.int<s, 32> x 10>
+
+void f() {
+ int c[10];
+ // CHECK: %[[ARR:.*]] = cir.alloca !cir.array<!cir.int<s, 32> x 10>, !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, ["c"]
+}
|
|
||
// FIXME: In LLVM, "lower arrays of undefined struct type to arrays of | ||
// i8 just to have a concrete type". Not sure this makes sense in CIR yet. | ||
assert(builder.isSized(elemTy) && "not implemented"); |
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 should probably use the cgm.errorNYI
, then just come up with a way to recover. That said, this is exactly why having isSized
assert is awkward here.
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.
Okey, thats make sense and i will try to recover with SInt32Ty
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.
Can you also add a test for lowering to LLVM IR?
@@ -386,7 +405,7 @@ def VoidPtr : Type< | |||
//===----------------------------------------------------------------------===// | |||
|
|||
def CIR_AnyType : AnyTypeOf<[ | |||
CIR_VoidType, CIR_BoolType, CIR_IntType, CIR_AnyFloat, CIR_PointerType, | |||
CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_IntType, CIR_AnyFloat, CIR_PointerType, |
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 think this line is over 80 characters. It should wrap to avoid that.
@@ -0,0 +1,12 @@ | |||
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s |
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.
Will multidimensional arrays and array function arguments work at this point? If so, can you add tests for those?
@@ -166,6 +166,9 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType, | |||
return success(); | |||
} | |||
|
|||
if (mlir::isa<cir::ArrayType>(opType)) |
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 don't see this in the incubator implementation of this function. Why is this here?
//===----------------------------------------------------------------------===// | ||
|
||
llvm::TypeSize | ||
ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, |
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.
Are these functions being called with any of the test cases? I don't see any checks that would be related to this.
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 was thinking of sizeof
operator but it's not implemented yet, is there is another way to test the size in lit test
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.
My point was that if the code isn't being called, you should leave it out until it is needed.
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.
Yes, but it's part of the DataLayoutTypeInterface
interface so we must implement it, I can test it after merging the sizeof PR #130847
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 see. Thanks for the clarification.
mlir::Type elemTy = convertTypeForMem(arrTy->getElementType()); | ||
|
||
if (!builder.isSized(elemTy)) { | ||
cgm.errorNYI(SourceLocation(), "unimplemented size for type", type); |
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 don't like the error being handled this way. If you're going to report an error about unimplemented types here, the check for the types should be here. If someone were to change the implementation of isSized(), they would have no way to know that this code needed to be updated.
@@ -33,6 +33,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { | |||
llvm_unreachable("NYI: PPC double-double format for long double"); | |||
llvm_unreachable("Unsupported format for long double"); | |||
} | |||
|
|||
bool isSized(mlir::Type ty) { | |||
return mlir::isa<cir::PointerType, cir::ArrayType, cir::BoolType, |
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 think this was better with the assert for other types. This function should handle all types that can occur in the current form of CIR. As we add new types, this function should be updated to indicate if they are sized or not. So, this isn't quite like other errorNYI
cases. An assert here is reasonable as a permanent part of the code.
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.
Yes i will update it, and i think no need for NYI or other assert when calling it because in call cases we will not need to recover
//===----------------------------------------------------------------------===// | ||
|
||
llvm::TypeSize | ||
ArrayType::getTypeSizeInBits(const ::mlir::DataLayout &dataLayout, |
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.
My point was that if the code isn't being called, you should leave it out until it is needed.
@@ -572,6 +572,10 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, | |||
|
|||
return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); | |||
}); | |||
converter.addConversion([&](cir::ArrayType type) -> mlir::Type { | |||
auto ty = convertTypeForMemory(converter, dataLayout, type.getEltType()); |
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.
auto ty = convertTypeForMemory(converter, dataLayout, type.getEltType()); | |
mlir::Type ty = convertTypeForMemory(converter, dataLayout, type.getEltType()); |
clang/test/CIR/CodeGen/array.cpp
Outdated
// CHECK: cir.global external @a : !cir.array<!cir.int<s, 32> x 10> | ||
|
||
int aa[10][10]; | ||
// CHECK: cir.global external @aa : !cir.array<!cir.array<!cir.int<s, 32> x 10> x 10> |
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.
Use different sizes for the dimensions here so we can verify that the CIR generated has them in the right order.
} | ||
|
||
void f2(int p[10]) {} | ||
// CHECK: cir.func @f2(%arg0: !cir.ptr<!cir.int<s, 32>> |
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.
Can you also check the cir.alloca
generated in this case?
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 have just one minor comment on the update. Please wait for @erichkeane to review again, but this looks good to me.
clang/test/CIR/Lowering/array.cpp
Outdated
void f() { | ||
int l[10]; | ||
} | ||
// CHECK: alloca [10 x i32], i64 1, align 16 |
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 think it's a good practice to have a check for the function name to establish that we're seeing the alloca
in the correct context.
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.
My concern is still not fixed, and Andy/Bruno still have comments here, so I don't believe this to be ready yet.
I already addressed all comments except the test for Size and it's need sizeof PR to merge, and the assert line which we need to agree on, other than that every thing is addressed :D |
Co-authored-by: Andy Kaylor <[email protected]>
cir::IntType>(ty)) | ||
return true; | ||
|
||
assert(0 && "Unexpected MLIR type"); |
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 think the
assert(0 && "Unexpected MLIR type"); | |
assert(!MissingFeatures::unsizedTypes()); |
was the suggestion here (see the other uses of MissingFeatures).
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.
Okey, i will check MissingFeatures and update it
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.
1 nit, else LGTM.
✅ With the latest revision this PR passed the C/C++ code formatter. |
This change adds the basic support for ArrayType Issue llvm#130197
This change adds the basic support for ArrayType
Issue #130197