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

source code of mlir/lib/IR/BuiltinDialect.cpp