//===- 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/StringExtras.h" #include "llvm/ADT/TypeSwitch.h" using namespace mlir; using namespace mlir::emitc; #include "mlir/Dialect/EmitC/IR/EmitCDialect.cpp.inc" //===----------------------------------------------------------------------===// // 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(); } //===----------------------------------------------------------------------===// // IncludeOp //===----------------------------------------------------------------------===// static void print(OpAsmPrinter &p, IncludeOp &op) { bool standardInclude = op.is_standard_include(); p << " "; if (standardInclude) p << "<"; p << "\"" << op.include() << "\""; if (standardInclude) p << ">"; } static ParseResult parseIncludeOp(OpAsmParser &parser, OperationState &result) { bool standardInclude = !parser.parseOptionalLess(); StringAttr include; OptionalParseResult includeParseResult = parser.parseOptionalAttribute(include, "include", result.attributes); if (!includeParseResult.hasValue()) return parser.emitError(parser.getNameLoc()) << "expected string attribute"; if (standardInclude && parser.parseOptionalGreater()) return parser.emitError(parser.getNameLoc()) << "expected trailing '>' for standard include"; if (standardInclude) result.addAttribute("is_standard_include", UnitAttr::get(parser.getContext())); return success(); } //===----------------------------------------------------------------------===// // 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(AsmParser &parser, Type type) { if (parser.parseLess()) return Attribute(); std::string value; llvm::SMLoc loc = parser.getCurrentLocation(); if (parser.parseOptionalString(&value)) { parser.emitError(loc) << "expected string"; return Attribute(); } if (parser.parseGreater()) return Attribute(); return get(parser.getContext(), value); } void emitc::OpaqueAttr::print(AsmPrinter &printer) const { printer << "<\""; llvm::printEscapedString(getValue(), printer.getStream()); printer << "\">"; } //===----------------------------------------------------------------------===// // EmitC Types //===----------------------------------------------------------------------===// #define GET_TYPEDEF_CLASSES #include "mlir/Dialect/EmitC/IR/EmitCTypes.cpp.inc" Type emitc::OpaqueType::parse(AsmParser &parser) { if (parser.parseLess()) return Type(); std::string 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(parser.getContext(), value); } void emitc::OpaqueType::print(AsmPrinter &printer) const { printer << "<\""; llvm::printEscapedString(getValue(), printer.getStream()); printer << "\">"; }