Skip to content

Commit 17dab4e

Browse files
authored
[EmitC] Add ArrayType (#26)
This models a one or multi-dimensional C/C++ array. Reviewers: TinaAMD Reviewed By: TinaAMD Pull Request: #114
1 parent e5ea0c4 commit 17dab4e

File tree

4 files changed

+181
-2
lines changed

4 files changed

+181
-2
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,64 @@
1616

1717
include "mlir/IR/AttrTypeBase.td"
1818
include "mlir/Dialect/EmitC/IR/EmitCBase.td"
19+
include "mlir/IR/BuiltinTypeInterfaces.td"
1920

2021
//===----------------------------------------------------------------------===//
2122
// EmitC type definitions
2223
//===----------------------------------------------------------------------===//
2324

24-
class EmitC_Type<string name, string typeMnemonic>
25-
: TypeDef<EmitC_Dialect, name> {
25+
class EmitC_Type<string name, string typeMnemonic, list<Trait> traits = []>
26+
: TypeDef<EmitC_Dialect, name, traits> {
2627
let mnemonic = typeMnemonic;
2728
}
2829

30+
def EmitC_ArrayType : EmitC_Type<"Array", "array", [ShapedTypeInterface]> {
31+
let summary = "EmitC array type";
32+
33+
let description = [{
34+
An array data type.
35+
36+
Example:
37+
38+
```mlir
39+
// Array emitted as `int32_t[10]`
40+
!emitc.array<10xi32>
41+
// Array emitted as `float[10][20]`
42+
!emitc.ptr<10x20xf32>
43+
```
44+
}];
45+
46+
let parameters = (ins
47+
ArrayRefParameter<"int64_t">:$shape,
48+
"Type":$elementType
49+
);
50+
51+
let builders = [
52+
TypeBuilderWithInferredContext<(ins
53+
"ArrayRef<int64_t>":$shape,
54+
"Type":$elementType
55+
), [{
56+
return $_get(elementType.getContext(), shape, elementType);
57+
}]>
58+
];
59+
let extraClassDeclaration = [{
60+
/// Returns if this type is ranked (always true).
61+
bool hasRank() const { return true; }
62+
63+
/// Clone this vector type with the given shape and element type. If the
64+
/// provided shape is `std::nullopt`, the current shape of the type is used.
65+
ArrayType cloneWith(std::optional<ArrayRef<int64_t>> shape,
66+
Type elementType) const;
67+
68+
static bool isValidElementType(Type type) {
69+
return type.isIntOrIndexOrFloat() ||
70+
llvm::isa<PointerType, OpaqueType>(type);
71+
}
72+
}];
73+
let genVerifyDecl = 1;
74+
let hasCustomAssemblyFormat = 1;
75+
}
76+
2977
def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
3078
let summary = "EmitC opaque type";
3179

mlir/lib/Dialect/EmitC/IR/EmitC.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,69 @@ void emitc::OpaqueAttr::print(AsmPrinter &printer) const {
578578
#define GET_TYPEDEF_CLASSES
579579
#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
580580

581+
//===----------------------------------------------------------------------===//
582+
// ArrayType
583+
//===----------------------------------------------------------------------===//
584+
585+
Type emitc::ArrayType::parse(AsmParser &parser) {
586+
if (parser.parseLess())
587+
return Type();
588+
589+
SmallVector<int64_t, 4> dimensions;
590+
if (parser.parseDimensionList(dimensions, /*allowDynamic=*/false,
591+
/*withTrailingX=*/true))
592+
return Type();
593+
// Parse the element type.
594+
auto typeLoc = parser.getCurrentLocation();
595+
Type elementType;
596+
if (parser.parseType(elementType))
597+
return Type();
598+
599+
// Check that memref is formed from allowed types.
600+
if (!isValidElementType(elementType))
601+
return parser.emitError(typeLoc, "invalid array element type"), Type();
602+
if (parser.parseGreater())
603+
return Type();
604+
return parser.getChecked<ArrayType>(dimensions, elementType);
605+
}
606+
607+
void emitc::ArrayType::print(AsmPrinter &printer) const {
608+
printer << "<";
609+
for (int64_t dim : getShape()) {
610+
printer << dim << 'x';
611+
}
612+
printer.printType(getElementType());
613+
printer << ">";
614+
}
615+
616+
LogicalResult emitc::ArrayType::verify(
617+
::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError,
618+
::llvm::ArrayRef<int64_t> shape, Type elementType) {
619+
if (shape.empty())
620+
return emitError() << "shape must not be empty";
621+
622+
for (auto d : shape) {
623+
if (d <= 0)
624+
return emitError() << "dimensions must have positive size";
625+
}
626+
627+
if (!elementType)
628+
return emitError() << "element type must not be none";
629+
630+
if (!isValidElementType(elementType))
631+
return emitError() << "invalid array element type";
632+
633+
return success();
634+
}
635+
636+
emitc::ArrayType
637+
emitc::ArrayType::cloneWith(std::optional<ArrayRef<int64_t>> shape,
638+
Type elementType) const {
639+
if (!shape)
640+
return emitc::ArrayType::get(getShape(), elementType);
641+
return emitc::ArrayType::get(*shape, elementType);
642+
}
643+
581644
//===----------------------------------------------------------------------===//
582645
// OpaqueType
583646
//===----------------------------------------------------------------------===//

mlir/test/Dialect/EmitC/invalid_types.mlir

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,57 @@ func.func @illegal_opaque_type_2() {
1111
// expected-error @+1 {{pointer not allowed as outer type with !emitc.opaque, use !emitc.ptr instead}}
1212
%1 = "emitc.variable"(){value = "nullptr" : !emitc.opaque<"int32_t*">} : () -> !emitc.opaque<"int32_t*">
1313
}
14+
15+
// -----
16+
17+
func.func @illegal_array_missing_spec(
18+
// expected-error @+1 {{expected non-function type}}
19+
%arg0: !emitc.array<>) {
20+
}
21+
22+
// -----
23+
24+
func.func @illegal_array_missing_shape(
25+
// expected-error @+1 {{shape must not be empty}}
26+
%arg9: !emitc.array<i32>) {
27+
}
28+
29+
// -----
30+
31+
func.func @illegal_array_missing_x(
32+
// expected-error @+1 {{expected 'x' in dimension list}}
33+
%arg0: !emitc.array<10>
34+
) {
35+
}
36+
37+
// -----
38+
39+
func.func @illegal_array_non_positive_dimenson(
40+
// expected-error @+1 {{dimensions must have positive size}}
41+
%arg0: !emitc.array<0xi32>
42+
) {
43+
}
44+
45+
// -----
46+
47+
func.func @illegal_array_missing_type(
48+
// expected-error @+1 {{expected non-function type}}
49+
%arg0: !emitc.array<10x>
50+
) {
51+
}
52+
53+
// -----
54+
55+
func.func @illegal_array_dynamic_shape(
56+
// expected-error @+1 {{expected static shape}}
57+
%arg0: !emitc.array<10x?xi32>
58+
) {
59+
}
60+
61+
// -----
62+
63+
func.func @illegal_array_unranked(
64+
// expected-error @+1 {{expected non-function type}}
65+
%arg0: !emitc.array<*xi32>
66+
) {
67+
}

mlir/test/Dialect/EmitC/types.mlir

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,17 @@ func.func @pointer_types() {
3939

4040
return
4141
}
42+
43+
// CHECK-LABEL: func @array_types(
44+
func.func @array_types(
45+
// CHECK-SAME: !emitc.array<1xf32>,
46+
%arg0: !emitc.array<1xf32>,
47+
// CHECK-SAME: !emitc.array<10x20x30xi32>,
48+
%arg1: !emitc.array<10x20x30xi32>,
49+
// CHECK-SAME: !emitc.array<30x!emitc.ptr<i32>>,
50+
%arg2: !emitc.array<30x!emitc.ptr<i32>>,
51+
// CHECK-SAME: !emitc.array<30x!emitc.opaque<"int">>
52+
%arg3: !emitc.array<30x!emitc.opaque<"int">>
53+
) {
54+
return
55+
}

0 commit comments

Comments
 (0)