diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt --- a/mlir/include/mlir/Dialect/CMakeLists.txt +++ b/mlir/include/mlir/Dialect/CMakeLists.txt @@ -5,6 +5,7 @@ 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 --- /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 --- /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 --- /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 --- /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 traits = []> + : Op { + 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:$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:$callee, + Arg, "the order of operands and further attributes">:$args, + Arg, "template arguments">:$template_args, + Variadic:$operands + ); + let results = (outs Variadic); + 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 ``. + 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:$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 --- /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 + : AttrDef { + 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 --- /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 --- /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 + : TypeDef { + 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"> + ``` + }]; + + 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 --- 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 @@ 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 --- a/mlir/lib/Dialect/CMakeLists.txt +++ b/mlir/lib/Dialect/CMakeLists.txt @@ -5,6 +5,7 @@ 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 --- /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 --- /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 --- /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(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 argsAttr = op.args()) { + for (Attribute arg : argsAttr.getValue()) { + if (arg.getType().isa()) { + int64_t index = arg.cast().getInt(); + // Args with elements of type index must be in range + // [0..operands.size). + if ((index < 0) || (index >= static_cast(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() && arg.getType().isa()) { + return op.emitOpError("array argument has no type"); + } + } + } + + if (Optional templateArgsAttr = op.template_args()) { + for (Attribute tArg : templateArgsAttr.getValue()) { + if (!tArg.isa() && !tArg.isa() && + !tArg.isa() && !tArg.isa()) + 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() && 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 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 --- /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 --- /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 --- /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"> + emitc.call "f"() {args = [!emitc.opaque<"std::vector">]} : () -> () + return +} diff --git a/mlir/test/mlir-opt/commandline.mlir b/mlir/test/mlir-opt/commandline.mlir --- 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