[Mlir-commits] [mlir] 876de06 - [mlir] Add EmitC dialect
Marius Brehler
llvmlistbot at llvm.org
Sat Jun 19 00:53:00 PDT 2021
Author: Marius Brehler
Date: 2021-06-19T09:51:17+02:00
New Revision: 876de062f94650f9ded56a22b062236f711fcd18
URL: https://github.com/llvm/llvm-project/commit/876de062f94650f9ded56a22b062236f711fcd18
DIFF: https://github.com/llvm/llvm-project/commit/876de062f94650f9ded56a22b062236f711fcd18.diff
LOG: [mlir] Add EmitC dialect
This upstreams the EmitC dialect and the corresponding Cpp target, both
initially presented with [1], from [2] to MLIR core. For the related
discussion, see [3].
[1] https://reviews.llvm.org/D76571
[2] https://github.com/iml130/mlir-emitc
[3] https://llvm.discourse.group/t/emitc-generating-c-c-from-mlir/3388
Co-authored-by: Jacques Pienaar <jpienaar at google.com>
Co-authored-by: Simon Camphausen <simon.camphausen at iml.fraunhofer.de>
Co-authored-by: Oliver Scherf <oliver.scherf at iml.fraunhofer.de>
Reviewed By: rriddle
Differential Revision: https://reviews.llvm.org/D103969
Added:
mlir/include/mlir/Dialect/EmitC/CMakeLists.txt
mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt
mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td
mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
mlir/lib/Dialect/EmitC/CMakeLists.txt
mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
mlir/lib/Dialect/EmitC/IR/EmitC.cpp
mlir/test/Dialect/EmitC/invalid_ops.mlir
mlir/test/Dialect/EmitC/ops.mlir
mlir/test/Dialect/EmitC/types.mlir
Modified:
mlir/include/mlir/Dialect/CMakeLists.txt
mlir/include/mlir/InitAllDialects.h
mlir/lib/Dialect/CMakeLists.txt
mlir/test/mlir-opt/commandline.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index 2d6d04a52a9d1..44a9249cef839 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(ArmSVE)
add_subdirectory(AMX)
add_subdirectory(Complex)
add_subdirectory(DLTI)
+add_subdirectory(EmitC)
add_subdirectory(GPU)
add_subdirectory(Math)
add_subdirectory(Linalg)
diff --git a/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt b/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt
new file mode 100644
index 0000000000000..f33061b2d87cf
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt
new file mode 100644
index 0000000000000..09a9f7a2ec1c5
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_mlir_dialect(EmitC emitc)
+add_mlir_doc(EmitC EmitC Dialects/ -gen-dialect-doc)
+
+set(LLVM_TARGET_DEFINITIONS EmitCAttributes.td)
+mlir_tablegen(EmitCAttributes.h.inc -gen-attrdef-decls)
+mlir_tablegen(EmitCAttributes.cpp.inc -gen-attrdef-defs)
+add_public_tablegen_target(MLIREmitCAttributesIncGen)
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
new file mode 100644
index 0000000000000..857d1430f9418
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.h
@@ -0,0 +1,32 @@
+//===- EmitC.h - EmitC Dialect ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares EmitC in MLIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITC_H
+#define MLIR_DIALECT_EMITC_IR_EMITC_H
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+#include "mlir/Dialect/EmitC/IR/EmitCDialect.h.inc"
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.h.inc"
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitC.h.inc"
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITC_H
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
new file mode 100644
index 0000000000000..78c682a806710
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitC.td
@@ -0,0 +1,148 @@
+//===- EmitC.td - EmitC operations--------------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITC
+#define MLIR_DIALECT_EMITC_IR_EMITC
+
+include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
+include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
+
+include "mlir/Interfaces/SideEffectInterfaces.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC op definitions
+//===----------------------------------------------------------------------===//
+
+// Base class for EmitC dialect ops.
+class EmitC_Op<string mnemonic, list<OpTrait> traits = []>
+ : Op<EmitC_Dialect, mnemonic, traits> {
+ let verifier = "return ::verify(*this);";
+}
+
+def EmitC_ApplyOp : EmitC_Op<"apply", []> {
+ let summary = "Apply operation";
+ let description = [{
+ With the `apply` operation the operators & (address of) and * (contents of)
+ can be applied to a single operand.
+
+ Example:
+
+ ```mlir
+ // Custom form of applying the & operator.
+ %0 = emitc.apply "&"(%arg0) : (i32) -> !emitc.opaque<"int32_t*">
+
+ // Generic form of the same operation.
+ %0 = "emitc.apply"(%arg0) {applicableOperator = "&"}
+ : (i32) -> !emitc.opaque<"int32_t*">
+
+ ```
+ }];
+ let arguments = (ins
+ Arg<StrAttr, "the operator to apply">:$applicableOperator,
+ AnyType:$operand
+ );
+ let results = (outs AnyType:$result);
+ let assemblyFormat = [{
+ $applicableOperator `(` $operand `)` attr-dict `:` functional-type($operand, results)
+ }];
+}
+
+def EmitC_CallOp : EmitC_Op<"call", []> {
+ let summary = "Call operation";
+ let description = [{
+ The `call` operation represents a C++ function call. The call allows
+ specifying order of operands and attributes in the call as follows:
+
+ - integer value of index type refers to an operand;
+ - attribute which will get lowered to constant value in call;
+
+ Example:
+
+ ```mlir
+ // Custom form defining a call to `foo()`.
+ %0 = emitc.call "foo" () : () -> i32
+
+ // Generic form of the same operation.
+ %0 = "emitc.call"() {callee = "foo"} : () -> i32
+ ```
+ }];
+ let arguments = (ins
+ Arg<StrAttr, "the C++ function to call">:$callee,
+ Arg<OptionalAttr<ArrayAttr>, "the order of operands and further attributes">:$args,
+ Arg<OptionalAttr<ArrayAttr>, "template arguments">:$template_args,
+ Variadic<AnyType>:$operands
+ );
+ let results = (outs Variadic<AnyType>);
+ let assemblyFormat = [{
+ $callee `(` $operands `)` attr-dict `:` functional-type($operands, results)
+ }];
+}
+
+def EmitC_ConstantOp : EmitC_Op<"constant", [ConstantLike]> {
+ let summary = "Constant operation";
+ let description = [{
+ The `constant` operation produces an SSA value equal to some constant
+ specified by an attribute. This can be used to form simple integer and
+ floating point constants, as well as more exotic things like tensor
+ constants. The `constant` operation also supports the EmitC opaque
+ attribute and the EmitC opaque type.
+
+ Example:
+
+ ```mlir
+ // Integer constant
+ %0 = "emitc.constant"(){value = 42 : i32} : () -> i32
+
+ // Constant emitted as `int32_t* = NULL;`
+ %1 = "emitc.constant"()
+ {value = #emitc.opaque<"NULL"> : !emitc.opaque<"int32_t*">}
+ : () -> !emitc.opaque<"int32_t*">
+ ```
+ }];
+
+ let arguments = (ins AnyAttr:$value);
+ let results = (outs AnyType);
+
+ let hasFolder = 1;
+}
+
+def EmitC_IncludeOp
+ : EmitC_Op<"include", [NoSideEffect, HasParent<"ModuleOp">]> {
+ let summary = "Include operation";
+ let description = [{
+ The `include` operation allows to define a source file inclusion via the
+ `#include` directive.
+
+ Example:
+
+ ```mlir
+ // Custom form defining the inclusion of `<myheader>`.
+ emitc.include "myheader.h" is_standard_include
+
+ // Generic form of the same operation.
+ "emitc.include" (){include = "myheader.h", is_standard_include} : () -> ()
+
+ // Generic form defining the inclusion of `"myheader"`.
+ "emitc.include" (){include = "myheader.h"} : () -> ()
+ ```
+ }];
+ let arguments = (ins
+ Arg<StrAttr, "source file to include">:$include,
+ UnitAttr:$is_standard_include
+ );
+ let assemblyFormat = [{
+ $include attr-dict (`is_standard_include` $is_standard_include^)?
+ }];
+ let verifier = ?;
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITC
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
new file mode 100644
index 0000000000000..2dd782ba49bf2
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCAttributes.td
@@ -0,0 +1,45 @@
+//===- EmitCAttributes.td - EmitC attributes ---------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC attributes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
+#define MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
+
+include "mlir/Dialect/EmitC/IR/EmitCBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC attribute definitions
+//===----------------------------------------------------------------------===//
+
+class EmitC_Attr<string name, string attrMnemonic>
+ : AttrDef<EmitC_Dialect, name> {
+ let mnemonic = attrMnemonic;
+}
+
+def EmitC_OpaqueAttr : EmitC_Attr<"Opaque", "opaque"> {
+ let summary = "An opaque attribute";
+
+ let description = [{
+ An opaque attribute of which the value gets emitted as is.
+
+ Example:
+
+ ```mlir
+ #emitc.opaque<"">
+ #emitc.opaque<"NULL">
+ #emitc.opaque<"nullptr">
+ ```
+ }];
+
+ let parameters = (ins StringRefParameter<"the opaque value">:$value);
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCATTRIBUTES
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td
new file mode 100644
index 0000000000000..5b7e81e2833a0
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCBase.td
@@ -0,0 +1,28 @@
+//===- EmitCBase.td - EmitC dialect ------------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCBASE
+#define MLIR_DIALECT_EMITC_IR_EMITCBASE
+
+include "mlir/IR/OpBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC dialect definition
+//===----------------------------------------------------------------------===//
+
+def EmitC_Dialect : Dialect {
+ let name = "emitc";
+ let cppNamespace = "::mlir::emitc";
+ let hasConstantMaterializer = 1;
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCBASE
diff --git a/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
new file mode 100644
index 0000000000000..d6fdd0fbf82df
--- /dev/null
+++ b/mlir/include/mlir/Dialect/EmitC/IR/EmitCTypes.td
@@ -0,0 +1,46 @@
+//===- EmitCTypes.td - EmitC types -------------------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the MLIR EmitC types.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef MLIR_DIALECT_EMITC_IR_EMITCTYPES
+#define MLIR_DIALECT_EMITC_IR_EMITCTYPES
+
+include "mlir/Dialect/EmitC/IR/EmitCBase.td"
+
+//===----------------------------------------------------------------------===//
+// EmitC type definitions
+//===----------------------------------------------------------------------===//
+
+class EmitC_Type<string name, string typeMnemonic>
+ : TypeDef<EmitC_Dialect, name> {
+ let mnemonic = typeMnemonic;
+}
+
+def EmitC_OpaqueType : EmitC_Type<"Opaque", "opaque"> {
+ let summary = "An opaque type";
+
+ let description = [{
+ An opaque data type of which the value gets emitted as is.
+
+ Example:
+
+ ```mlir
+ !emitc.opaque<"int">
+ !emitc.opaque<"float *">
+ !emitc.opaque<"std::vector<std::string>">
+ ```
+ }];
+
+ let parameters = (ins StringRefParameter<"the opaque value">:$value);
+}
+
+#endif // MLIR_DIALECT_EMITC_IR_EMITCTYPES
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index e44f2e8f1ae0a..c52dae3fd1b51 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -21,6 +21,7 @@
#include "mlir/Dialect/Async/IR/Async.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/GPU/GPUDialect.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
@@ -57,6 +58,7 @@ inline void registerAllDialects(DialectRegistry ®istry) {
async::AsyncDialect,
complex::ComplexDialect,
DLTIDialect,
+ emitc::EmitCDialect,
gpu::GPUDialect,
LLVM::LLVMDialect,
linalg::LinalgDialect,
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index f5124f7d138fb..de946beef0d9f 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(Async)
add_subdirectory(AMX)
add_subdirectory(Complex)
add_subdirectory(DLTI)
+add_subdirectory(EmitC)
add_subdirectory(GPU)
add_subdirectory(Linalg)
add_subdirectory(LLVMIR)
diff --git a/mlir/lib/Dialect/EmitC/CMakeLists.txt b/mlir/lib/Dialect/EmitC/CMakeLists.txt
new file mode 100644
index 0000000000000..f33061b2d87cf
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
diff --git a/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
new file mode 100644
index 0000000000000..6283441fdadff
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/IR/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_mlir_dialect_library(MLIREmitC
+ EmitC.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/EmitC
+
+ DEPENDS
+ MLIREmitCIncGen
+ MLIREmitCAttributesIncGen
+
+ LINK_LIBS PUBLIC
+ MLIRIR
+ MLIRSideEffectInterfaces
+ )
diff --git a/mlir/lib/Dialect/EmitC/IR/EmitC.cpp b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
new file mode 100644
index 0000000000000..364c247f75e4f
--- /dev/null
+++ b/mlir/lib/Dialect/EmitC/IR/EmitC.cpp
@@ -0,0 +1,212 @@
+//===- EmitC.cpp - EmitC Dialect ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/DialectImplementation.h"
+#include "llvm/ADT/TypeSwitch.h"
+
+using namespace mlir;
+using namespace mlir::emitc;
+
+//===----------------------------------------------------------------------===//
+// EmitCDialect
+//===----------------------------------------------------------------------===//
+
+void EmitCDialect::initialize() {
+ addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
+ >();
+ addTypes<
+#define GET_TYPEDEF_LIST
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
+ >();
+ addAttributes<
+#define GET_ATTRDEF_LIST
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
+ >();
+}
+
+/// Materialize a single constant operation from a given attribute value with
+/// the desired resultant type.
+Operation *EmitCDialect::materializeConstant(OpBuilder &builder,
+ Attribute value, Type type,
+ Location loc) {
+ return builder.create<ConstantOp>(loc, type, value);
+}
+
+//===----------------------------------------------------------------------===//
+// ApplyOp
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verify(ApplyOp op) {
+ StringRef applicableOperator = op.applicableOperator();
+
+ // Applicable operator must not be empty.
+ if (applicableOperator.empty())
+ return op.emitOpError("applicable operator must not be empty");
+
+ // Only `*` and `&` are supported.
+ if (applicableOperator != "&" && applicableOperator != "*")
+ return op.emitOpError("applicable operator is illegal");
+
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// CallOp
+//===----------------------------------------------------------------------===//
+
+static LogicalResult verify(emitc::CallOp op) {
+ // Callee must not be empty.
+ if (op.callee().empty())
+ return op.emitOpError("callee must not be empty");
+
+ if (Optional<ArrayAttr> argsAttr = op.args()) {
+ for (Attribute arg : argsAttr.getValue()) {
+ if (arg.getType().isa<IndexType>()) {
+ int64_t index = arg.cast<IntegerAttr>().getInt();
+ // Args with elements of type index must be in range
+ // [0..operands.size).
+ if ((index < 0) || (index >= static_cast<int64_t>(op.getNumOperands())))
+ return op.emitOpError("index argument is out of range");
+
+ // Args with elements of type ArrayAttr must have a type.
+ } else if (arg.isa<ArrayAttr>() && arg.getType().isa<NoneType>()) {
+ return op.emitOpError("array argument has no type");
+ }
+ }
+ }
+
+ if (Optional<ArrayAttr> templateArgsAttr = op.template_args()) {
+ for (Attribute tArg : templateArgsAttr.getValue()) {
+ if (!tArg.isa<TypeAttr>() && !tArg.isa<IntegerAttr>() &&
+ !tArg.isa<FloatAttr>() && !tArg.isa<emitc::OpaqueAttr>())
+ return op.emitOpError("template argument has invalid type");
+ }
+ }
+
+ return success();
+}
+
+//===----------------------------------------------------------------------===//
+// ConstantOp
+//===----------------------------------------------------------------------===//
+
+/// The constant op requires that the attribute's type matches the return type.
+static LogicalResult verify(emitc::ConstantOp &op) {
+ Attribute value = op.value();
+ Type type = op.getType();
+ if (!value.getType().isa<NoneType>() && type != value.getType())
+ return op.emitOpError() << "requires attribute's type (" << value.getType()
+ << ") to match op's return type (" << type << ")";
+ return success();
+}
+
+OpFoldResult emitc::ConstantOp::fold(ArrayRef<Attribute> operands) {
+ assert(operands.empty() && "constant has no operands");
+ return value();
+}
+
+//===----------------------------------------------------------------------===//
+// TableGen'd op method definitions
+//===----------------------------------------------------------------------===//
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitC.cpp.inc"
+
+//===----------------------------------------------------------------------===//
+// EmitC Attributes
+//===----------------------------------------------------------------------===//
+
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCAttributes.cpp.inc"
+
+Attribute emitc::OpaqueAttr::parse(MLIRContext *context,
+ DialectAsmParser &parser, Type type) {
+ if (parser.parseLess())
+ return Attribute();
+ StringRef value;
+ llvm::SMLoc loc = parser.getCurrentLocation();
+ if (parser.parseOptionalString(&value)) {
+ parser.emitError(loc) << "expected string";
+ return Attribute();
+ }
+ if (parser.parseGreater())
+ return Attribute();
+ return get(context, value);
+}
+
+Attribute EmitCDialect::parseAttribute(DialectAsmParser &parser,
+ Type type) const {
+ llvm::SMLoc typeLoc = parser.getCurrentLocation();
+ StringRef mnemonic;
+ if (parser.parseKeyword(&mnemonic))
+ return Attribute();
+ Attribute genAttr;
+ OptionalParseResult parseResult =
+ generatedAttributeParser(getContext(), parser, mnemonic, type, genAttr);
+ if (parseResult.hasValue())
+ return genAttr;
+ parser.emitError(typeLoc, "unknown attribute in EmitC dialect");
+ return Attribute();
+}
+
+void EmitCDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {
+ if (failed(generatedAttributePrinter(attr, os)))
+ llvm_unreachable("unexpected 'EmitC' attribute kind");
+}
+
+void emitc::OpaqueAttr::print(DialectAsmPrinter &printer) const {
+ printer << "opaque<\"" << getValue() << "\">";
+}
+
+//===----------------------------------------------------------------------===//
+// EmitC Types
+//===----------------------------------------------------------------------===//
+
+#define GET_TYPEDEF_CLASSES
+#include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc"
+
+Type emitc::OpaqueType::parse(MLIRContext *context, DialectAsmParser &parser) {
+ if (parser.parseLess())
+ return Type();
+ StringRef value;
+ llvm::SMLoc loc = parser.getCurrentLocation();
+ if (parser.parseOptionalString(&value) || value.empty()) {
+ parser.emitError(loc) << "expected non empty string";
+ return Type();
+ }
+ if (parser.parseGreater())
+ return Type();
+ return get(context, value);
+}
+
+Type EmitCDialect::parseType(DialectAsmParser &parser) const {
+ llvm::SMLoc typeLoc = parser.getCurrentLocation();
+ StringRef mnemonic;
+ if (parser.parseKeyword(&mnemonic))
+ return Type();
+ Type genType;
+ OptionalParseResult parseResult =
+ generatedTypeParser(getContext(), parser, mnemonic, genType);
+ if (parseResult.hasValue())
+ return genType;
+ parser.emitError(typeLoc, "unknown type in EmitC dialect");
+ return Type();
+}
+
+void EmitCDialect::printType(Type type, DialectAsmPrinter &os) const {
+ if (failed(generatedTypePrinter(type, os)))
+ llvm_unreachable("unexpected 'EmitC' type kind");
+}
+
+void emitc::OpaqueType::print(DialectAsmPrinter &printer) const {
+ printer << "opaque<\"" << getValue() << "\">";
+}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
new file mode 100644
index 0000000000000..e86664627c368
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -0,0 +1,79 @@
+// RUN: mlir-opt %s -split-input-file -verify-diagnostics
+
+func @const_attribute_return_type_1() {
+ // expected-error @+1 {{'emitc.constant' op requires attribute's type ('i64') to match op's return type ('i32')}}
+ %c0 = "emitc.constant"(){value = 42: i64} : () -> i32
+ return
+}
+
+// -----
+
+func @const_attribute_return_type_2() {
+ // expected-error @+1 {{'emitc.constant' op requires attribute's type ('!emitc.opaque<"int32_t*">') to match op's return type ('!emitc.opaque<"int32_t">')}}
+ %c0 = "emitc.constant"(){value = "nullptr" : !emitc.opaque<"int32_t*">} : () -> !emitc.opaque<"int32_t">
+ return
+}
+
+// -----
+
+func @index_args_out_of_range_1() {
+ // expected-error @+1 {{'emitc.call' op index argument is out of range}}
+ emitc.call "test" () {args = [0 : index]} : () -> ()
+ return
+}
+
+// -----
+
+func @index_args_out_of_range_2(%arg : i32) {
+ // expected-error @+1 {{'emitc.call' op index argument is out of range}}
+ emitc.call "test" (%arg, %arg) {args = [2 : index]} : (i32, i32) -> ()
+ return
+}
+
+// -----
+
+func @empty_callee() {
+ // expected-error @+1 {{'emitc.call' op callee must not be empty}}
+ emitc.call "" () : () -> ()
+ return
+}
+
+// -----
+
+func @nonetype_arg(%arg : i32) {
+ // expected-error @+1 {{'emitc.call' op array argument has no type}}
+ emitc.call "nonetype_arg"(%arg) {args = [0 : index, [0, 1, 2]]} : (i32) -> i32
+ return
+}
+
+// -----
+
+func @array_template_arg(%arg : i32) {
+ // expected-error @+1 {{'emitc.call' op template argument has invalid type}}
+ emitc.call "nonetype_template_arg"(%arg) {template_args = [[0, 1, 2]]} : (i32) -> i32
+ return
+}
+
+// -----
+
+func @dense_template_argument(%arg : i32) {
+ // expected-error @+1 {{'emitc.call' op template argument has invalid type}}
+ emitc.call "dense_template_argument"(%arg) {template_args = [dense<[1.0, 1.0]> : tensor<2xf32>]} : (i32) -> i32
+ return
+}
+
+// -----
+
+func @empty_operator(%arg : i32) {
+ // expected-error @+1 {{'emitc.apply' op applicable operator must not be empty}}
+ %2 = emitc.apply ""(%arg) : (i32) -> !emitc.opaque<"int32_t*">
+ return
+}
+
+// -----
+
+func @illegal_operator(%arg : i32) {
+ // expected-error @+1 {{'emitc.apply' op applicable operator is illegal}}
+ %2 = emitc.apply "+"(%arg) : (i32) -> !emitc.opaque<"int32_t*">
+ return
+}
diff --git a/mlir/test/Dialect/EmitC/ops.mlir b/mlir/test/Dialect/EmitC/ops.mlir
new file mode 100644
index 0000000000000..3a48ff447e1cb
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/ops.mlir
@@ -0,0 +1,24 @@
+// RUN: mlir-opt -verify-diagnostics %s | FileCheck %s
+
+"emitc.include" (){include = "test.h", is_standard_include} : () -> ()
+emitc.include "test.h" is_standard_include
+
+// CHECK-LABEL: func @f(%{{.*}}: i32, %{{.*}}: !emitc.opaque<"int32_t">) {
+func @f(%arg0: i32, %f: !emitc.opaque<"int32_t">) {
+ %1 = "emitc.call"() {callee = "blah"} : () -> i64
+ emitc.call "foo" (%1) {args = [
+ 0 : index, dense<[0, 1]> : tensor<2xi32>, 0 : index
+ ]} : (i64) -> ()
+ return
+}
+
+func @c(%arg0: i32) {
+ %1 = "emitc.constant"(){value = 42 : i32} : () -> i32
+ return
+}
+
+func @a(%arg0: i32, %arg1: i32) {
+ %1 = "emitc.apply"(%arg0) {applicableOperator = "&"} : (i32) -> !emitc.opaque<"int32_t*">
+ %2 = emitc.apply "&"(%arg1) : (i32) -> !emitc.opaque<"int32_t*">
+ return
+}
diff --git a/mlir/test/Dialect/EmitC/types.mlir b/mlir/test/Dialect/EmitC/types.mlir
new file mode 100644
index 0000000000000..f1ffce74e4c2c
--- /dev/null
+++ b/mlir/test/Dialect/EmitC/types.mlir
@@ -0,0 +1,18 @@
+// RUN: mlir-opt -verify-diagnostics %s | FileCheck %s
+// check parser
+// RUN: mlir-opt -verify-diagnostics %s | mlir-opt -verify-diagnostics | FileCheck %s
+
+// CHECK-LABEL: func @opaque_types() {
+func @opaque_types() {
+ // CHECK-NEXT: !emitc.opaque<"int">
+ emitc.call "f"() {args = [!emitc<"opaque<\"int\">">]} : () -> ()
+ // CHECK-NEXT: !emitc.opaque<"byte">
+ emitc.call "f"() {args = [!emitc<"opaque<\"byte\">">]} : () -> ()
+ // CHECK-NEXT: !emitc.opaque<"unsigned">
+ emitc.call "f"() {args = [!emitc<"opaque<\"unsigned\">">]} : () -> ()
+ // CHECK-NEXT: !emitc.opaque<"status_t">
+ emitc.call "f"() {args = [!emitc<"opaque<\"status_t\">">]} : () -> ()
+ // CHECK-NEXT: !emitc.opaque<"std::vector<std::string>">
+ emitc.call "f"() {args = [!emitc.opaque<"std::vector<std::string>">]} : () -> ()
+ return
+}
diff --git a/mlir/test/mlir-opt/commandline.mlir b/mlir/test/mlir-opt/commandline.mlir
index 125d6b1d950b1..95c476a841633 100644
--- a/mlir/test/mlir-opt/commandline.mlir
+++ b/mlir/test/mlir-opt/commandline.mlir
@@ -8,6 +8,7 @@
// CHECK-NEXT: async
// CHECK-NEXT: complex
// CHECK-NEXT: dlti
+// CHECK-NEXT: emitc
// CHECK-NEXT: gpu
// CHECK-NEXT: linalg
// CHECK-NEXT: llvm
More information about the Mlir-commits
mailing list