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/OpImplementation.h"
21#include "mlir/IR/TypeRange.h"
22
23using namespace mlir;
24
25//===----------------------------------------------------------------------===//
26// TableGen'erated dialect
27//===----------------------------------------------------------------------===//
28
29#include "mlir/IR/BuiltinDialect.cpp.inc"
30
31//===----------------------------------------------------------------------===//
32// BuiltinBlobManagerInterface
33//===----------------------------------------------------------------------===//
34
35using BuiltinBlobManagerInterface =
36 ResourceBlobManagerDialectInterfaceBase<DenseResourceElementsHandle>;
37
38//===----------------------------------------------------------------------===//
39// BuiltinOpAsmDialectInterface
40//===----------------------------------------------------------------------===//
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>(Val: attr)) {
50 os << "loc";
51 return AliasResult::OverridableAlias;
52 }
53 if (auto distinct = llvm::dyn_cast<DistinctAttr>(Val&: attr))
54 if (!llvm::isa<UnitAttr>(Val: 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>(Val&: type)) {
63 if (tupleType.size() > 16) {
64 os << "tuple";
65 return AliasResult::OverridableAlias;
66 }
67 }
68 return AliasResult::NoAlias;
69 }
70
71 //===------------------------------------------------------------------===//
72 // Resources
73 //===------------------------------------------------------------------===//
74
75 std::string
76 getResourceKey(const AsmDialectResourceHandle &handle) const override {
77 return cast<DenseResourceElementsHandle>(Val: handle).getKey().str();
78 }
79 FailureOr<AsmDialectResourceHandle>
80 declareResource(StringRef key) const final {
81 return blobManager.insert(name: key);
82 }
83 LogicalResult parseResource(AsmParsedResourceEntry &entry) const final {
84 FailureOr<AsmResourceBlob> blob = entry.parseAsBlob();
85 if (failed(Result: blob))
86 return failure();
87
88 // Update the blob for this entry.
89 blobManager.update(name: entry.getKey(), newBlob: std::move(*blob));
90 return success();
91 }
92 void
93 buildResources(Operation *op,
94 const SetVector<AsmDialectResourceHandle> &referencedResources,
95 AsmResourceBuilder &provider) const final {
96 blobManager.buildResources(provider, referencedResources: referencedResources.getArrayRef());
97 }
98
99private:
100 /// The blob manager for the dialect.
101 BuiltinBlobManagerInterface &blobManager;
102};
103} // namespace
104
105void BuiltinDialect::initialize() {
106 registerTypes();
107 registerAttributes();
108 registerLocationAttributes();
109 addOperations<
110#define GET_OP_LIST
111#include "mlir/IR/BuiltinOps.cpp.inc"
112 >();
113
114 auto &blobInterface = addInterface<BuiltinBlobManagerInterface>();
115 addInterface<BuiltinOpAsmDialectInterface>(args&: blobInterface);
116 builtin_dialect_detail::addBytecodeInterface(dialect: this);
117}
118
119//===----------------------------------------------------------------------===//
120// ModuleOp
121//===----------------------------------------------------------------------===//
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(newAttribute: builder.getNamedAttr(
128 name: mlir::SymbolTable::getSymbolAttrName(), val: builder.getStringAttr(bytes: *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 builder.create<ModuleOp>(location: loc, args&: name);
136}
137
138DataLayoutSpecInterface ModuleOp::getDataLayoutSpec() {
139 // Take the first and only (if present) attribute that implements the
140 // interface. This needs a linear search, but is called only once per data
141 // layout object construction that is used for repeated queries.
142 for (NamedAttribute attr : getOperation()->getAttrs())
143 if (auto spec = llvm::dyn_cast<DataLayoutSpecInterface>(Val: attr.getValue()))
144 return spec;
145 return {};
146}
147
148TargetSystemSpecInterface ModuleOp::getTargetSystemSpec() {
149 // Take the first and only (if present) attribute that implements the
150 // interface. This needs a linear search, but is called only once per data
151 // layout object construction that is used for repeated queries.
152 for (NamedAttribute attr : getOperation()->getAttrs())
153 if (auto spec = llvm::dyn_cast<TargetSystemSpecInterface>(Val: attr.getValue()))
154 return spec;
155 return {};
156}
157
158LogicalResult ModuleOp::verify() {
159 // Check that none of the attributes are non-dialect attributes, except for
160 // the symbol related attributes.
161 for (auto attr : (*this)->getAttrs()) {
162 if (!attr.getName().strref().contains(C: '.') &&
163 !llvm::is_contained(
164 Range: ArrayRef<StringRef>{mlir::SymbolTable::getSymbolAttrName(),
165 mlir::SymbolTable::getVisibilityAttrName()},
166 Element: 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>(Val: na.getValue())) {
177 if (layoutSpec) {
178 InFlightDiagnostic diag =
179 emitOpError() << "expects at most one data layout attribute";
180 diag.attachNote() << "'" << layoutSpecAttrName
181 << "' 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// UnrealizedConversionCastOp
195//===----------------------------------------------------------------------===//
196
197LogicalResult
198UnrealizedConversionCastOp::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(in_start: operands.begin(), in_end: 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 this
212 // operation, and operand types that directly match the result types of this
213 // 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(in_start: inputOp->operand_begin(), in_end: inputOp->operand_end());
222 return success();
223}
224
225LogicalResult UnrealizedConversionCastOp::verify() {
226 // TODO: The verifier of external models is not called. This op verifier can
227 // 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 definitions
235//===----------------------------------------------------------------------===//
236
237#define GET_OP_CLASSES
238#include "mlir/IR/BuiltinOps.cpp.inc"
239

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