blob: aed6fcc94296c22daa02f7124c5b5dbf12f3d307 [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 Lattnerac591f12018-07-22 21:02:26 -070024#include "mlir/IR/Statements.h"
Chris Lattner7121b802018-07-04 20:45:39 -070025using namespace mlir;
26
Chris Lattner55315d52018-07-18 19:06:45 -070027Operation::Operation(Identifier name, bool isInstruction,
28 ArrayRef<NamedAttribute> attrs, MLIRContext *context)
29 : nameAndIsInstruction(name, isInstruction) {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070030 this->attrs = AttributeListStorage::get(attrs, context);
31
Chris Lattner7121b802018-07-04 20:45:39 -070032#ifndef NDEBUG
33 for (auto elt : attrs)
34 assert(elt.second != nullptr && "Attributes cannot have null entries");
35#endif
36}
37
Chris Lattnerac591f12018-07-22 21:02:26 -070038Operation::~Operation() {}
39
Chris Lattner95865062018-08-01 10:18:59 -070040/// Return the context this operation is associated with.
41MLIRContext *Operation::getContext() const {
42 if (auto *inst = dyn_cast<OperationInst>(this))
43 return inst->getContext();
44 return cast<OperationStmt>(this)->getContext();
45}
46
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070047/// Return the function this operation is defined in.
48Function *Operation::getOperationFunction() {
49 if (auto *inst = dyn_cast<OperationInst>(this))
50 return inst->getFunction();
51 return cast<OperationStmt>(this)->findFunction();
52}
53
Chris Lattnerac591f12018-07-22 21:02:26 -070054/// Return the number of operands this operation has.
55unsigned Operation::getNumOperands() const {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070056 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070057 return inst->getNumOperands();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070058
59 return cast<OperationStmt>(this)->getNumOperands();
Chris Lattnerac591f12018-07-22 21:02:26 -070060}
61
62SSAValue *Operation::getOperand(unsigned idx) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070063 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070064 return inst->getOperand(idx);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070065
66 return cast<OperationStmt>(this)->getOperand(idx);
Chris Lattnerac591f12018-07-22 21:02:26 -070067}
68
Chris Lattner68a3fd02018-07-23 10:08:00 -070069void Operation::setOperand(unsigned idx, SSAValue *value) {
70 if (auto *inst = dyn_cast<OperationInst>(this)) {
71 inst->setOperand(idx, cast<CFGValue>(value));
72 } else {
73 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070074 stmt->setOperand(idx, cast<MLValue>(value));
Chris Lattner68a3fd02018-07-23 10:08:00 -070075 }
76}
77
Chris Lattnerac591f12018-07-22 21:02:26 -070078/// Return the number of results this operation has.
79unsigned Operation::getNumResults() const {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070080 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070081 return inst->getNumResults();
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070082
83 return cast<OperationStmt>(this)->getNumResults();
Chris Lattnerac591f12018-07-22 21:02:26 -070084}
85
86/// Return the indicated result.
87SSAValue *Operation::getResult(unsigned idx) {
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070088 if (auto *inst = dyn_cast<OperationInst>(this))
Chris Lattnerac591f12018-07-22 21:02:26 -070089 return inst->getResult(idx);
Chris Lattnerea5c3dc2018-08-21 08:42:19 -070090
91 return cast<OperationStmt>(this)->getResult(idx);
Chris Lattner7121b802018-07-04 20:45:39 -070092}
93
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070094ArrayRef<NamedAttribute> Operation::getAttrs() const {
95 if (!attrs)
96 return {};
97 return attrs->getElements();
98}
99
Chris Lattnerff0d5902018-07-05 09:12:11 -0700100/// If an attribute exists with the specified name, change it to the new
101/// value. Otherwise, add a new attribute with the specified name/value.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700102void Operation::setAttr(Identifier name, Attribute *value) {
Chris Lattnerff0d5902018-07-05 09:12:11 -0700103 assert(value && "attributes may never be null");
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700104 auto origAttrs = getAttrs();
105
106 SmallVector<NamedAttribute, 8> newAttrs(origAttrs.begin(), origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700107 auto *context = getContext();
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700108
Chris Lattnerff0d5902018-07-05 09:12:11 -0700109 // If we already have this attribute, replace it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700110 for (auto &elt : newAttrs)
Chris Lattnerff0d5902018-07-05 09:12:11 -0700111 if (elt.first == name) {
112 elt.second = value;
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700113 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700114 return;
115 }
116
117 // Otherwise, add it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700118 newAttrs.push_back({name, value});
119 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700120}
121
122/// Remove the attribute with the specified name if it exists. The return
123/// value indicates whether the attribute was present or not.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700124auto Operation::removeAttr(Identifier name) -> RemoveResult {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700125 auto origAttrs = getAttrs();
126 for (unsigned i = 0, e = origAttrs.size(); i != e; ++i) {
127 if (origAttrs[i].first == name) {
128 SmallVector<NamedAttribute, 8> newAttrs;
129 newAttrs.reserve(origAttrs.size() - 1);
130 newAttrs.append(origAttrs.begin(), origAttrs.begin() + i);
131 newAttrs.append(origAttrs.begin() + i + 1, origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700132 attrs = AttributeListStorage::get(newAttrs, getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700133 return RemoveResult::Removed;
134 }
135 }
136 return RemoveResult::NotFound;
137}
Chris Lattner95865062018-08-01 10:18:59 -0700138
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700139/// Emit a note about this operation, reporting up to any diagnostic
140/// handlers that may be listening.
141void Operation::emitNote(const Twine &message) const {
142 getContext()->emitDiagnostic(getAttr(":location"), message,
143 MLIRContext::DiagnosticKind::Note);
144}
145
Chris Lattner95865062018-08-01 10:18:59 -0700146/// Emit a warning about this operation, reporting up to any diagnostic
147/// handlers that may be listening.
148void Operation::emitWarning(const Twine &message) const {
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700149 getContext()->emitDiagnostic(getAttr(":location"), message,
150 MLIRContext::DiagnosticKind::Warning);
Chris Lattner95865062018-08-01 10:18:59 -0700151}
152
153/// Emit an error about fatal conditions with this operation, reporting up to
154/// any diagnostic handlers that may be listening. NOTE: This may terminate
155/// the containing application, only use when the IR is in an inconsistent
156/// state.
157void Operation::emitError(const Twine &message) const {
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700158 getContext()->emitDiagnostic(getAttr(":location"), message,
159 MLIRContext::DiagnosticKind::Error);
Chris Lattner95865062018-08-01 10:18:59 -0700160}