blob: af937bc1ad7b5bc5175b4ba07b564aaa1b50fcce [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 Lattnerac591f12018-07-22 21:02:26 -070020#include "mlir/IR/Instructions.h"
Chris Lattner95865062018-08-01 10:18:59 -070021#include "mlir/IR/MLIRContext.h"
Chris Lattnerac591f12018-07-22 21:02:26 -070022#include "mlir/IR/Statements.h"
Chris Lattner7121b802018-07-04 20:45:39 -070023using namespace mlir;
24
Chris Lattner55315d52018-07-18 19:06:45 -070025Operation::Operation(Identifier name, bool isInstruction,
26 ArrayRef<NamedAttribute> attrs, MLIRContext *context)
27 : nameAndIsInstruction(name, isInstruction) {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070028 this->attrs = AttributeListStorage::get(attrs, context);
29
Chris Lattner7121b802018-07-04 20:45:39 -070030#ifndef NDEBUG
31 for (auto elt : attrs)
32 assert(elt.second != nullptr && "Attributes cannot have null entries");
33#endif
34}
35
Chris Lattnerac591f12018-07-22 21:02:26 -070036Operation::~Operation() {}
37
Chris Lattner95865062018-08-01 10:18:59 -070038/// Return the context this operation is associated with.
39MLIRContext *Operation::getContext() const {
40 if (auto *inst = dyn_cast<OperationInst>(this))
41 return inst->getContext();
42 return cast<OperationStmt>(this)->getContext();
43}
44
Chris Lattnerac591f12018-07-22 21:02:26 -070045/// Return the number of operands this operation has.
46unsigned Operation::getNumOperands() const {
47 if (auto *inst = dyn_cast<OperationInst>(this)) {
48 return inst->getNumOperands();
49 } else {
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070050 return cast<OperationStmt>(this)->getNumOperands();
Chris Lattnerac591f12018-07-22 21:02:26 -070051 }
52}
53
54SSAValue *Operation::getOperand(unsigned idx) {
55 if (auto *inst = dyn_cast<OperationInst>(this)) {
56 return inst->getOperand(idx);
57 } else {
58 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070059 return stmt->getOperand(idx);
Chris Lattnerac591f12018-07-22 21:02:26 -070060 }
61}
62
Chris Lattner68a3fd02018-07-23 10:08:00 -070063void Operation::setOperand(unsigned idx, SSAValue *value) {
64 if (auto *inst = dyn_cast<OperationInst>(this)) {
65 inst->setOperand(idx, cast<CFGValue>(value));
66 } else {
67 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070068 stmt->setOperand(idx, cast<MLValue>(value));
Chris Lattner68a3fd02018-07-23 10:08:00 -070069 }
70}
71
Chris Lattnerac591f12018-07-22 21:02:26 -070072/// Return the number of results this operation has.
73unsigned Operation::getNumResults() const {
74 if (auto *inst = dyn_cast<OperationInst>(this)) {
75 return inst->getNumResults();
76 } else {
77 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070078 return stmt->getNumResults();
Chris Lattnerac591f12018-07-22 21:02:26 -070079 }
80}
81
82/// Return the indicated result.
83SSAValue *Operation::getResult(unsigned idx) {
84 if (auto *inst = dyn_cast<OperationInst>(this)) {
85 return inst->getResult(idx);
86 } else {
87 auto *stmt = cast<OperationStmt>(this);
Tatiana Shpeisman60bf7be2018-07-26 18:09:20 -070088 return stmt->getResult(idx);
Chris Lattnerac591f12018-07-22 21:02:26 -070089 }
Chris Lattner7121b802018-07-04 20:45:39 -070090}
91
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -070092ArrayRef<NamedAttribute> Operation::getAttrs() const {
93 if (!attrs)
94 return {};
95 return attrs->getElements();
96}
97
Chris Lattnerff0d5902018-07-05 09:12:11 -070098/// If an attribute exists with the specified name, change it to the new
99/// value. Otherwise, add a new attribute with the specified name/value.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700100void Operation::setAttr(Identifier name, Attribute *value) {
Chris Lattnerff0d5902018-07-05 09:12:11 -0700101 assert(value && "attributes may never be null");
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700102 auto origAttrs = getAttrs();
103
104 SmallVector<NamedAttribute, 8> newAttrs(origAttrs.begin(), origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700105 auto *context = getContext();
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700106
Chris Lattnerff0d5902018-07-05 09:12:11 -0700107 // If we already have this attribute, replace it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700108 for (auto &elt : newAttrs)
Chris Lattnerff0d5902018-07-05 09:12:11 -0700109 if (elt.first == name) {
110 elt.second = value;
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700111 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700112 return;
113 }
114
115 // Otherwise, add it.
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700116 newAttrs.push_back({name, value});
117 attrs = AttributeListStorage::get(newAttrs, context);
Chris Lattnerff0d5902018-07-05 09:12:11 -0700118}
119
120/// Remove the attribute with the specified name if it exists. The return
121/// value indicates whether the attribute was present or not.
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700122auto Operation::removeAttr(Identifier name) -> RemoveResult {
Chris Lattnerdf1a2fc2018-07-05 21:20:59 -0700123 auto origAttrs = getAttrs();
124 for (unsigned i = 0, e = origAttrs.size(); i != e; ++i) {
125 if (origAttrs[i].first == name) {
126 SmallVector<NamedAttribute, 8> newAttrs;
127 newAttrs.reserve(origAttrs.size() - 1);
128 newAttrs.append(origAttrs.begin(), origAttrs.begin() + i);
129 newAttrs.append(origAttrs.begin() + i + 1, origAttrs.end());
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700130 attrs = AttributeListStorage::get(newAttrs, getContext());
Chris Lattner7121b802018-07-04 20:45:39 -0700131 return RemoveResult::Removed;
132 }
133 }
134 return RemoveResult::NotFound;
135}
Chris Lattner95865062018-08-01 10:18:59 -0700136
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700137/// Emit a note about this operation, reporting up to any diagnostic
138/// handlers that may be listening.
139void Operation::emitNote(const Twine &message) const {
140 getContext()->emitDiagnostic(getAttr(":location"), message,
141 MLIRContext::DiagnosticKind::Note);
142}
143
Chris Lattner95865062018-08-01 10:18:59 -0700144/// Emit a warning about this operation, reporting up to any diagnostic
145/// handlers that may be listening.
146void Operation::emitWarning(const Twine &message) const {
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700147 getContext()->emitDiagnostic(getAttr(":location"), message,
148 MLIRContext::DiagnosticKind::Warning);
Chris Lattner95865062018-08-01 10:18:59 -0700149}
150
151/// Emit an error about fatal conditions with this operation, reporting up to
152/// any diagnostic handlers that may be listening. NOTE: This may terminate
153/// the containing application, only use when the IR is in an inconsistent
154/// state.
155void Operation::emitError(const Twine &message) const {
Chris Lattnerf7bdf952018-08-05 21:12:29 -0700156 getContext()->emitDiagnostic(getAttr(":location"), message,
157 MLIRContext::DiagnosticKind::Error);
Chris Lattner95865062018-08-01 10:18:59 -0700158}