blob: 0ce9c372f1ff9aff0ce6393f34c75ae37c173397 [file] [log] [blame]
Chris Lattner7121b802018-07-04 20:45:39 -07001//===- Operation.cpp - MLIR Operation Class -------------------------------===//
2//
3// Copyright 2019 The MLIR Authors.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16// =============================================================================
17
18#include "mlir/IR/Operation.h"
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070019#include "AttributeListStorage.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070020#include "mlir/IR/CFGFunction.h"
Chris Lattnerac591f12018-07-22 21:02:26 -070021#include "mlir/IR/Instructions.h"
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070022#include "mlir/IR/MLFunction.h"
Chris Lattner95865062018-08-01 10:18:59 -070023#include "mlir/IR/MLIRContext.h"
Chris Lattner015100b2018-09-09 20:40:23 -070024#include "mlir/IR/OpDefinition.h"
Chris Lattnerac591f12018-07-22 21:02:26 -070025#include "mlir/IR/Statements.h"
Chris Lattner7121b802018-07-04 20:45:39 -070026using namespace mlir;
27
Chris Lattner1628fa02018-08-23 14:32:25 -070028Operation::Operation(bool isInstruction, Identifier name,
Chris Lattner55315d52018-07-18 19:06:45 -070029 ArrayRef<NamedAttribute> attrs, MLIRContext *context)
30 : nameAndIsInstruction(name, isInstruction) {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070031 this->attrs = AttributeListStorage::get(attrs, context);
32
Chris Lattner7121b802018-07-04 20:45:39 -070033#ifndef NDEBUG
34 for (auto elt : attrs)
35 assert(elt.second != nullptr && "Attributes cannot have null entries");
36#endif
37}
38
Chris Lattnerac591f12018-07-22 21:02:26 -070039Operation::~Operation() {}
40
Chris Lattner95865062018-08-01 10:18:59 -070041/// Return the context this operation is associated with.
42MLIRContext *Operation::getContext() const {
43 if (auto *inst = dyn_cast<OperationInst>(this))
44 return inst->getContext();
45 return cast<OperationStmt>(this)->getContext();
46}
47
Chris Lattner1628fa02018-08-23 14:32:25 -070048/// The source location the operation was defined or derived from. Note that
49/// it is possible for this pointer to be null.
Chris Lattnerfc647d52018-08-27 21:05:16 -070050Location *Operation::getLoc() const {
Chris Lattner1628fa02018-08-23 14:32:25 -070051 if (auto *inst = dyn_cast<OperationInst>(this))
52 return inst->getLoc();
53 return cast<OperationStmt>(this)->getLoc();
54}
55
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070056/// Return the function this operation is defined in.
57Function *Operation::getOperationFunction() {
58 if (auto *inst = dyn_cast<OperationInst>(this))
59 return inst->getFunction();
60 return cast<OperationStmt>(this)->findFunction();
61}
62
Chris Lattnerac591f12018-07-22 21:02:26 -070063/// Return the number of operands this operation has.
64unsigned Operation::getNumOperands() const {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070065 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070066 return inst->getNumOperands();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070067
68 return cast<OperationStmt>(this)->getNumOperands();
Chris Lattnerac591f12018-07-22 21:02:26 -070069}
70
71SSAValue *Operation::getOperand(unsigned idx) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070072 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070073 return inst->getOperand(idx);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070074
75 return cast<OperationStmt>(this)->getOperand(idx);
Chris Lattnerac591f12018-07-22 21:02:26 -070076}
77
Chris Lattner68a3fd02018-07-23 10:08:00 -070078void Operation::setOperand(unsigned idx, SSAValue *value) {
79 if (auto *inst = dyn_cast<OperationInst>(this)) {
80 inst->setOperand(idx, cast<CFGValue>(value));
81 } else {
82 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070083 stmt->setOperand(idx, cast<MLValue>(value));
Chris Lattner68a3fd02018-07-23 10:08:00 -070084 }
85}
86
Chris Lattnerac591f12018-07-22 21:02:26 -070087/// Return the number of results this operation has.
88unsigned Operation::getNumResults() const {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070089 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070090 return inst->getNumResults();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070091
92 return cast<OperationStmt>(this)->getNumResults();
Chris Lattnerac591f12018-07-22 21:02:26 -070093}
94
95/// Return the indicated result.
96SSAValue *Operation::getResult(unsigned idx) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070097 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070098 return inst->getResult(idx);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070099
100 return cast<OperationStmt>(this)->getResult(idx);
Chris Lattner7121b802018-07-04 20:45:39 -0700101}
102
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700103ArrayRef<NamedAttribute> Operation::getAttrs() const {
104 if (!attrs)
105 return {};
106 return attrs->getElements();
107}
108
Chris Lattnerff0d5902018-07-05 09:12:11 -0700109/// If an attribute exists with the specified name, change it to the new
110/// value. Otherwise, add a new attribute with the specified name/value.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700111void Operation::setAttr(Identifier name, Attribute *value) {
Chris Lattnerff0d5902018-07-05 09:12:11 -0700112 assert(value && "attributes may never be null");
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700113 auto origAttrs = getAttrs();
114
115 SmallVector<NamedAttribute, 8> newAttrs(origAttrs.begin(), origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700116 auto *context = getContext();
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700117
Chris Lattnerff0d5902018-07-05 09:12:11 -0700118 // If we already have this attribute, replace it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700119 for (auto &elt : newAttrs)
Chris Lattnerff0d5902018-07-05 09:12:11 -0700120 if (elt.first == name) {
121 elt.second = value;
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700122 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700123 return;
124 }
125
126 // Otherwise, add it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700127 newAttrs.push_back({name, value});
128 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700129}
130
131/// Remove the attribute with the specified name if it exists. The return
132/// value indicates whether the attribute was present or not.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700133auto Operation::removeAttr(Identifier name) -> RemoveResult {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700134 auto origAttrs = getAttrs();
135 for (unsigned i = 0, e = origAttrs.size(); i != e; ++i) {
136 if (origAttrs[i].first == name) {
137 SmallVector<NamedAttribute, 8> newAttrs;
138 newAttrs.reserve(origAttrs.size() - 1);
139 newAttrs.append(origAttrs.begin(), origAttrs.begin() + i);
140 newAttrs.append(origAttrs.begin() + i + 1, origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700141 attrs = AttributeListStorage::get(newAttrs, getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700142 return RemoveResult::Removed;
143 }
144 }
145 return RemoveResult::NotFound;
146}
Chris Lattner95865062018-08-01 10:18:59 -0700147
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700148/// Emit a note about this operation, reporting up to any diagnostic
149/// handlers that may be listening.
150void Operation::emitNote(const Twine &message) const {
Chris Lattner1628fa02018-08-23 14:32:25 -0700151 getContext()->emitDiagnostic(getLoc(), message,
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700152 MLIRContext::DiagnosticKind::Note);
153}
154
Chris Lattner95865062018-08-01 10:18:59 -0700155/// Emit a warning about this operation, reporting up to any diagnostic
156/// handlers that may be listening.
157void Operation::emitWarning(const Twine &message) const {
Chris Lattner1628fa02018-08-23 14:32:25 -0700158 getContext()->emitDiagnostic(getLoc(), message,
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700159 MLIRContext::DiagnosticKind::Warning);
Chris Lattner95865062018-08-01 10:18:59 -0700160}
161
162/// Emit an error about fatal conditions with this operation, reporting up to
163/// any diagnostic handlers that may be listening. NOTE: This may terminate
164/// the containing application, only use when the IR is in an inconsistent
165/// state.
166void Operation::emitError(const Twine &message) const {
Chris Lattner1628fa02018-08-23 14:32:25 -0700167 getContext()->emitDiagnostic(getLoc(), message,
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700168 MLIRContext::DiagnosticKind::Error);
Chris Lattner95865062018-08-01 10:18:59 -0700169}
Chris Lattner015100b2018-09-09 20:40:23 -0700170
171/// Emit an error with the op name prefixed, like "'dim' op " which is
172/// convenient for verifiers.
173bool Operation::emitOpError(const Twine &message) const {
174 emitError(Twine('\'') + getName().str() + "' op " + message);
175 return true;
176}
177
178//===----------------------------------------------------------------------===//
179// OpBaseState trait class.
180//===----------------------------------------------------------------------===//
181
182/// Emit an error about fatal conditions with this operation, reporting up to
183/// any diagnostic handlers that may be listening. NOTE: This may terminate
184/// the containing application, only use when the IR is in an inconsistent
185/// state.
186void OpBaseState::emitError(const Twine &message) const {
187 getOperation()->emitError(message);
188}
189
190/// Emit an error with the op name prefixed, like "'dim' op " which is
191/// convenient for verifiers.
192bool OpBaseState::emitOpError(const Twine &message) const {
193 return getOperation()->emitOpError(message);
194}
195
196/// Emit a warning about this operation, reporting up to any diagnostic
197/// handlers that may be listening.
198void OpBaseState::emitWarning(const Twine &message) const {
199 getOperation()->emitWarning(message);
200}
201
202/// Emit a note about this operation, reporting up to any diagnostic
203/// handlers that may be listening.
204void OpBaseState::emitNote(const Twine &message) const {
205 getOperation()->emitNote(message);
206}