```mlir
!emitc.opaque<"int">
- !emitc.opaque<"float *">
+ !emitc.opaque<"mytype">
!emitc.opaque<"std::vector<std::string>">
```
}];
let parameters = (ins StringRefParameter<"the opaque value">:$value);
}
+def EmitC_PointerType : EmitC_Type<"Pointer", "ptr"> {
+ let summary = "EmitC pointer type";
+
+ let description = [{
+ A pointer data type.
+
+ Example:
+
+ ```mlir
+ // Pointer emitted as `int32_t*`
+ !emitc.ptr<i32>
+ // Pointer emitted as `float*`
+ !emitc.ptr<f32>
+ // Pointer emitted as `int*`
+ !emitc.ptr<!emitc.opaque<"int">>
+ ```
+ }];
+
+ let parameters = (ins "Type":$pointee);
+ let builders = [
+ TypeBuilderWithInferredContext<(ins "Type":$pointee), [{
+ return $_get(pointee.getContext(), pointee);
+ }]>
+ ];
+ let assemblyFormat = "`<` qualified($pointee) `>`";
+}
+
#endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES
#define GET_TYPEDEF_CLASSES
#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
+//===----------------------------------------------------------------------===//
+// OpaqueType
+//===----------------------------------------------------------------------===//
+
Type emitc::OpaqueType::parse(AsmParser &parser) {
if (parser.parseLess())
return Type();
os << oType.getValue();
return success();
}
+ if (auto pType = type.dyn_cast<emitc::PointerType>()) {
+ if (failed(emitType(loc, pType.getPointee())))
+ return failure();
+ os << "*";
+ return success();
+ }
return emitError(loc, "cannot emit type ") << type;
}
return
}
+
+// CHECK-LABEL: func @pointer_types() {
+func @pointer_types() {
+ // CHECK-NEXT: !emitc.ptr<i32>
+ emitc.call "f"() {template_args = [!emitc<"ptr<i32>">]} : () -> ()
+ // CHECK-NEXT: !emitc.ptr<i64>
+ emitc.call "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
+ // CHECK-NEXT: !emitc.ptr<f32>
+ emitc.call "f"() {template_args = [!emitc<"ptr<f32>">]} : () -> ()
+ // CHECK-NEXT: !emitc.ptr<f64>
+ emitc.call "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
+ // CHECK-NEXT: !emitc.ptr<i32>
+ %0 = emitc.call "f"() : () -> (!emitc.ptr<i32>)
+ // CHECK-NEXT: (!emitc.ptr<i32>) -> !emitc.ptr<!emitc.ptr<i32>>
+ %1 = emitc.call "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
+ // CHECK-NEXT: !emitc.ptr<!emitc.opaque<"int">>
+ emitc.call "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
+
+ return
+}
// RUN: mlir-translate -mlir-to-cpp %s | FileCheck %s
-// CHECK-LABEL: void opaque_template_args() {
-func @opaque_template_args() {
+// CHECK-LABEL: void opaque_types() {
+func @opaque_types() {
// CHECK-NEXT: f<int>();
emitc.call "f"() {template_args = [!emitc<"opaque<\"int\">">]} : () -> ()
// CHECK-NEXT: f<byte>();
return
}
+
+// CHECK-LABEL: void ptr_types() {
+func @ptr_types() {
+ // CHECK-NEXT: f<int32_t*>();
+ emitc.call "f"() {template_args = [!emitc<"ptr<i32>">]} : () -> ()
+ // CHECK-NEXT: f<int64_t*>();
+ emitc.call "f"() {template_args = [!emitc.ptr<i64>]} : () -> ()
+ // CHECK-NEXT: f<float*>();
+ emitc.call "f"() {template_args = [!emitc<"ptr<f32>">]} : () -> ()
+ // CHECK-NEXT: f<double*>();
+ emitc.call "f"() {template_args = [!emitc.ptr<f64>]} : () -> ()
+ // CHECK-NEXT: int32_t* [[V0:[^ ]*]] = f();
+ %0 = emitc.call "f"() : () -> (!emitc.ptr<i32>)
+ // CHECK-NEXT: int32_t** [[V1:[^ ]*]] = f([[V0:[^ ]*]]);
+ %1 = emitc.call "f"(%0) : (!emitc.ptr<i32>) -> (!emitc.ptr<!emitc.ptr<i32>>)
+ // CHECK-NEXT: f<int*>();
+ emitc.call "f"() {template_args = [!emitc.ptr<!emitc.opaque<"int">>]} : () -> ()
+
+ return
+}