239 lines · cpp
1//===- BuiltinDialect.cpp - MLIR Builtin Dialect --------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Builtin dialect that contains all of the attributes,10// operations, and types that are necessary for the validity of the IR.11//12//===----------------------------------------------------------------------===//13 14#include "mlir/IR/BuiltinDialect.h"15#include "BuiltinDialectBytecode.h"16#include "mlir/IR/Builders.h"17#include "mlir/IR/BuiltinOps.h"18#include "mlir/IR/BuiltinTypes.h"19#include "mlir/IR/DialectResourceBlobManager.h"20#include "mlir/IR/OpImplementation.h"21#include "mlir/IR/TypeRange.h"22 23using namespace mlir;24 25//===----------------------------------------------------------------------===//26// TableGen'erated dialect27//===----------------------------------------------------------------------===//28 29#include "mlir/IR/BuiltinDialect.cpp.inc"30 31//===----------------------------------------------------------------------===//32// BuiltinBlobManagerInterface33//===----------------------------------------------------------------------===//34 35using BuiltinBlobManagerInterface =36 ResourceBlobManagerDialectInterfaceBase<DenseResourceElementsHandle>;37 38//===----------------------------------------------------------------------===//39// BuiltinOpAsmDialectInterface40//===----------------------------------------------------------------------===//41 42namespace {43struct BuiltinOpAsmDialectInterface : public OpAsmDialectInterface {44 BuiltinOpAsmDialectInterface(Dialect *dialect,45 BuiltinBlobManagerInterface &mgr)46 : OpAsmDialectInterface(dialect), blobManager(mgr) {}47 48 AliasResult getAlias(Attribute attr, raw_ostream &os) const override {49 if (llvm::isa<LocationAttr>(attr)) {50 os << "loc";51 return AliasResult::OverridableAlias;52 }53 if (auto distinct = llvm::dyn_cast<DistinctAttr>(attr))54 if (!llvm::isa<UnitAttr>(distinct.getReferencedAttr())) {55 os << "distinct";56 return AliasResult::OverridableAlias;57 }58 return AliasResult::NoAlias;59 }60 61 AliasResult getAlias(Type type, raw_ostream &os) const final {62 if (auto tupleType = llvm::dyn_cast<TupleType>(type)) {63 if (tupleType.size() > 16) {64 os << "tuple";65 return AliasResult::OverridableAlias;66 }67 }68 return AliasResult::NoAlias;69 }70 71 //===------------------------------------------------------------------===//72 // Resources73 //===------------------------------------------------------------------===//74 75 std::string76 getResourceKey(const AsmDialectResourceHandle &handle) const override {77 return cast<DenseResourceElementsHandle>(handle).getKey().str();78 }79 FailureOr<AsmDialectResourceHandle>80 declareResource(StringRef key) const final {81 return blobManager.insert(key);82 }83 LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {84 FailureOr<AsmResourceBlob> blob = entry.parseAsBlob();85 if (failed(blob))86 return failure();87 88 // Update the blob for this entry.89 blobManager.update(entry.getKey(), std::move(*blob));90 return success();91 }92 void93 buildResources(Operation *op,94 const SetVector<AsmDialectResourceHandle> &referencedResources,95 AsmResourceBuilder &provider) const final {96 blobManager.buildResources(provider, referencedResources.getArrayRef());97 }98 99private:100 /// The blob manager for the dialect.101 BuiltinBlobManagerInterface &blobManager;102};103} // namespace104 105void BuiltinDialect::initialize() {106 registerTypes();107 registerAttributes();108 registerLocationAttributes();109 addOperations<110#define GET_OP_LIST111#include "mlir/IR/BuiltinOps.cpp.inc"112 >();113 114 auto &blobInterface = addInterface<BuiltinBlobManagerInterface>();115 addInterface<BuiltinOpAsmDialectInterface>(blobInterface);116 builtin_dialect_detail::addBytecodeInterface(this);117}118 119//===----------------------------------------------------------------------===//120// ModuleOp121//===----------------------------------------------------------------------===//122 123void ModuleOp::build(OpBuilder &builder, OperationState &state,124 std::optional<StringRef> name) {125 state.addRegion()->emplaceBlock();126 if (name) {127 state.attributes.push_back(builder.getNamedAttr(128 mlir::SymbolTable::getSymbolAttrName(), builder.getStringAttr(*name)));129 }130}131 132/// Construct a module from the given context.133ModuleOp ModuleOp::create(Location loc, std::optional<StringRef> name) {134 OpBuilder builder(loc->getContext());135 return ModuleOp::create(builder, loc, name);136}137 138DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() {139 // Take the first and only (if present) attribute that implements the140 // interface. This needs a linear search, but is called only once per data141 // layout object construction that is used for repeated queries.142 for (NamedAttribute attr : getOperation()->getAttrs())143 if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(attr.getValue()))144 return spec;145 return {};146}147 148TargetSystemSpecInterface ModuleOp::getTargetSystemSpec() {149 // Take the first and only (if present) attribute that implements the150 // interface. This needs a linear search, but is called only once per data151 // layout object construction that is used for repeated queries.152 for (NamedAttribute attr : getOperation()->getAttrs())153 if (auto spec = llvm::dyn_cast<TargetSystemSpecInterface>(attr.getValue()))154 return spec;155 return {};156}157 158LogicalResult ModuleOp::verify() {159 // Check that none of the attributes are non-dialect attributes, except for160 // the symbol related attributes.161 for (auto attr : (*this)->getAttrs()) {162 if (!attr.getName().strref().contains('.') &&163 !llvm::is_contained(164 ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),165 mlir::SymbolTable::getVisibilityAttrName()},166 attr.getName().strref()))167 return emitOpError() << "can only contain attributes with "168 "dialect-prefixed names, found: '"169 << attr.getName().getValue() << "'";170 }171 172 // Check that there is at most one data layout spec attribute.173 StringRef layoutSpecAttrName;174 DataLayoutSpecInterface layoutSpec;175 for (const NamedAttribute &na : (*this)->getAttrs()) {176 if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(na.getValue())) {177 if (layoutSpec) {178 InFlightDiagnostic diag =179 emitOpError() << "expects at most one data layout attribute";180 diag.attachNote() << "'" << layoutSpecAttrName181 << "' is a data layout attribute";182 diag.attachNote() << "'" << na.getName().getValue()183 << "' is a data layout attribute";184 }185 layoutSpecAttrName = na.getName().strref();186 layoutSpec = spec;187 }188 }189 190 return success();191}192 193//===----------------------------------------------------------------------===//194// UnrealizedConversionCastOp195//===----------------------------------------------------------------------===//196 197LogicalResult198UnrealizedConversionCastOp::fold(FoldAdaptor adaptor,199 SmallVectorImpl<OpFoldResult> &foldResults) {200 OperandRange operands = getInputs();201 ResultRange results = getOutputs();202 203 if (operands.getType() == results.getType()) {204 foldResults.append(operands.begin(), operands.end());205 return success();206 }207 208 if (operands.empty())209 return failure();210 211 // Check that the input is a cast with results that all feed into this212 // operation, and operand types that directly match the result types of this213 // operation.214 Value firstInput = operands.front();215 auto inputOp = firstInput.getDefiningOp<UnrealizedConversionCastOp>();216 if (!inputOp || inputOp.getResults() != operands ||217 inputOp.getOperandTypes() != results.getTypes())218 return failure();219 220 // If everything matches up, we can fold the passthrough.221 foldResults.append(inputOp->operand_begin(), inputOp->operand_end());222 return success();223}224 225LogicalResult UnrealizedConversionCastOp::verify() {226 // TODO: The verifier of external models is not called. This op verifier can227 // be removed when that is fixed.228 if (getNumResults() == 0)229 return emitOpError() << "expected at least one result for cast operation";230 return success();231}232 233//===----------------------------------------------------------------------===//234// TableGen'd op method definitions235//===----------------------------------------------------------------------===//236 237#define GET_OP_CLASSES238#include "mlir/IR/BuiltinOps.cpp.inc"239