[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 &registry) {
                   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