2018-07-05 11:45:39 +08:00
|
|
|
//===- Operation.cpp - MLIR Operation Class -------------------------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
|
|
|
|
#include "mlir/IR/Operation.h"
|
2018-07-06 12:20:59 +08:00
|
|
|
#include "AttributeListStorage.h"
|
2018-07-23 12:02:26 +08:00
|
|
|
#include "mlir/IR/Instructions.h"
|
|
|
|
#include "mlir/IR/Statements.h"
|
2018-07-05 11:45:39 +08:00
|
|
|
using namespace mlir;
|
|
|
|
|
2018-07-19 10:06:45 +08:00
|
|
|
Operation::Operation(Identifier name, bool isInstruction,
|
|
|
|
ArrayRef<NamedAttribute> attrs, MLIRContext *context)
|
|
|
|
: nameAndIsInstruction(name, isInstruction) {
|
2018-07-06 12:20:59 +08:00
|
|
|
this->attrs = AttributeListStorage::get(attrs, context);
|
|
|
|
|
2018-07-05 11:45:39 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
for (auto elt : attrs)
|
|
|
|
assert(elt.second != nullptr && "Attributes cannot have null entries");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-07-23 12:02:26 +08:00
|
|
|
Operation::~Operation() {}
|
|
|
|
|
|
|
|
/// Return the number of operands this operation has.
|
|
|
|
unsigned Operation::getNumOperands() const {
|
|
|
|
if (auto *inst = dyn_cast<OperationInst>(this)) {
|
|
|
|
return inst->getNumOperands();
|
|
|
|
} else {
|
2018-07-27 09:09:20 +08:00
|
|
|
return cast<OperationStmt>(this)->getNumOperands();
|
2018-07-23 12:02:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SSAValue *Operation::getOperand(unsigned idx) {
|
|
|
|
if (auto *inst = dyn_cast<OperationInst>(this)) {
|
|
|
|
return inst->getOperand(idx);
|
|
|
|
} else {
|
|
|
|
auto *stmt = cast<OperationStmt>(this);
|
2018-07-27 09:09:20 +08:00
|
|
|
return stmt->getOperand(idx);
|
2018-07-23 12:02:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-24 01:08:00 +08:00
|
|
|
void Operation::setOperand(unsigned idx, SSAValue *value) {
|
|
|
|
if (auto *inst = dyn_cast<OperationInst>(this)) {
|
|
|
|
inst->setOperand(idx, cast<CFGValue>(value));
|
|
|
|
} else {
|
|
|
|
auto *stmt = cast<OperationStmt>(this);
|
2018-07-27 09:09:20 +08:00
|
|
|
stmt->setOperand(idx, cast<MLValue>(value));
|
2018-07-24 01:08:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-23 12:02:26 +08:00
|
|
|
/// Return the number of results this operation has.
|
|
|
|
unsigned Operation::getNumResults() const {
|
|
|
|
if (auto *inst = dyn_cast<OperationInst>(this)) {
|
|
|
|
return inst->getNumResults();
|
|
|
|
} else {
|
|
|
|
auto *stmt = cast<OperationStmt>(this);
|
2018-07-27 09:09:20 +08:00
|
|
|
return stmt->getNumResults();
|
2018-07-23 12:02:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return the indicated result.
|
|
|
|
SSAValue *Operation::getResult(unsigned idx) {
|
|
|
|
if (auto *inst = dyn_cast<OperationInst>(this)) {
|
|
|
|
return inst->getResult(idx);
|
|
|
|
} else {
|
|
|
|
auto *stmt = cast<OperationStmt>(this);
|
2018-07-27 09:09:20 +08:00
|
|
|
return stmt->getResult(idx);
|
2018-07-23 12:02:26 +08:00
|
|
|
}
|
2018-07-05 11:45:39 +08:00
|
|
|
}
|
|
|
|
|
2018-07-06 12:20:59 +08:00
|
|
|
ArrayRef<NamedAttribute> Operation::getAttrs() const {
|
|
|
|
if (!attrs)
|
|
|
|
return {};
|
|
|
|
return attrs->getElements();
|
|
|
|
}
|
|
|
|
|
2018-07-06 00:12:11 +08:00
|
|
|
/// If an attribute exists with the specified name, change it to the new
|
|
|
|
/// value. Otherwise, add a new attribute with the specified name/value.
|
2018-07-06 12:20:59 +08:00
|
|
|
void Operation::setAttr(Identifier name, Attribute *value,
|
|
|
|
MLIRContext *context) {
|
2018-07-06 00:12:11 +08:00
|
|
|
assert(value && "attributes may never be null");
|
2018-07-06 12:20:59 +08:00
|
|
|
auto origAttrs = getAttrs();
|
|
|
|
|
|
|
|
SmallVector<NamedAttribute, 8> newAttrs(origAttrs.begin(), origAttrs.end());
|
|
|
|
|
2018-07-06 00:12:11 +08:00
|
|
|
// If we already have this attribute, replace it.
|
2018-07-06 12:20:59 +08:00
|
|
|
for (auto &elt : newAttrs)
|
2018-07-06 00:12:11 +08:00
|
|
|
if (elt.first == name) {
|
|
|
|
elt.second = value;
|
2018-07-06 12:20:59 +08:00
|
|
|
attrs = AttributeListStorage::get(newAttrs, context);
|
2018-07-06 00:12:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, add it.
|
2018-07-06 12:20:59 +08:00
|
|
|
newAttrs.push_back({name, value});
|
|
|
|
attrs = AttributeListStorage::get(newAttrs, context);
|
2018-07-06 00:12:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove the attribute with the specified name if it exists. The return
|
|
|
|
/// value indicates whether the attribute was present or not.
|
2018-07-06 12:20:59 +08:00
|
|
|
auto Operation::removeAttr(Identifier name, MLIRContext *context)
|
|
|
|
-> RemoveResult {
|
|
|
|
auto origAttrs = getAttrs();
|
|
|
|
for (unsigned i = 0, e = origAttrs.size(); i != e; ++i) {
|
|
|
|
if (origAttrs[i].first == name) {
|
|
|
|
SmallVector<NamedAttribute, 8> newAttrs;
|
|
|
|
newAttrs.reserve(origAttrs.size() - 1);
|
|
|
|
newAttrs.append(origAttrs.begin(), origAttrs.begin() + i);
|
|
|
|
newAttrs.append(origAttrs.begin() + i + 1, origAttrs.end());
|
|
|
|
attrs = AttributeListStorage::get(newAttrs, context);
|
2018-07-05 11:45:39 +08:00
|
|
|
return RemoveResult::Removed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return RemoveResult::NotFound;
|
|
|
|
}
|