Modules are now Ops and, as such, can be nested. They do not produce an SSA value so there is no possibility to refer to them in the IR. Introduce support for symbol names attached to the module Op so that it can be referred to using SymbolRefAttrs. The name is optional, for example the implicit top-level module does not have a name. PiperOrigin-RevId: 272671600
121 lines
4.2 KiB
C++
121 lines
4.2 KiB
C++
//===- Module.cpp - MLIR Module Operation ---------------------------------===//
|
|
//
|
|
// 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/Module.h"
|
|
#include "mlir/IR/Builders.h"
|
|
#include "mlir/IR/OpImplementation.h"
|
|
|
|
using namespace mlir;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Module Operation.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void ModuleOp::build(Builder *builder, OperationState &result, StringRef name) {
|
|
ensureTerminator(*result.addRegion(), *builder, result.location);
|
|
if (!name.empty())
|
|
result.attributes.push_back(
|
|
builder->getNamedAttr(mlir::SymbolTable::getSymbolAttrName(),
|
|
builder->getSymbolRefAttr(name)));
|
|
}
|
|
|
|
/// Construct a module from the given context.
|
|
ModuleOp ModuleOp::create(Location loc, StringRef name) {
|
|
OperationState state(loc, "module");
|
|
Builder builder(loc->getContext());
|
|
ModuleOp::build(&builder, state, name);
|
|
return llvm::cast<ModuleOp>(Operation::create(state));
|
|
}
|
|
|
|
ParseResult ModuleOp::parse(OpAsmParser &parser, OperationState &result) {
|
|
// If the name is present, parse it.
|
|
StringAttr nameAttr;
|
|
(void)parser.parseSymbolName(nameAttr, mlir::SymbolTable::getSymbolAttrName(),
|
|
result.attributes);
|
|
|
|
// If module attributes are present, parse them.
|
|
if (succeeded(parser.parseOptionalKeyword("attributes")))
|
|
if (parser.parseOptionalAttributeDict(result.attributes))
|
|
return failure();
|
|
|
|
// Parse the module body.
|
|
auto *body = result.addRegion();
|
|
if (parser.parseRegion(*body, llvm::None, llvm::None))
|
|
return failure();
|
|
|
|
// Ensure that this module has a valid terminator.
|
|
ensureTerminator(*body, parser.getBuilder(), result.location);
|
|
return success();
|
|
}
|
|
|
|
void ModuleOp::print(OpAsmPrinter &p) {
|
|
p << "module";
|
|
|
|
StringRef name = getName();
|
|
if (!name.empty())
|
|
p << " @" << name;
|
|
|
|
// Print the module attributes.
|
|
auto attrs = getAttrs();
|
|
if (!attrs.empty() &&
|
|
!(attrs.size() == 1 && attrs.front().first.strref() ==
|
|
mlir::SymbolTable::getSymbolAttrName())) {
|
|
p << " attributes";
|
|
p.printOptionalAttrDict(attrs, {mlir::SymbolTable::getSymbolAttrName()});
|
|
}
|
|
|
|
// Print the region.
|
|
p.printRegion(getOperation()->getRegion(0), /*printEntryBlockArgs=*/false,
|
|
/*printBlockTerminators=*/false);
|
|
}
|
|
|
|
LogicalResult ModuleOp::verify() {
|
|
auto &bodyRegion = getOperation()->getRegion(0);
|
|
|
|
// The body must contain a single basic block.
|
|
if (bodyRegion.empty() || std::next(bodyRegion.begin()) != bodyRegion.end())
|
|
return emitOpError("expected body region to have a single block");
|
|
|
|
// Check that the body has no block arguments.
|
|
auto *body = &bodyRegion.front();
|
|
if (body->getNumArguments() != 0)
|
|
return emitOpError("expected body to have no arguments");
|
|
|
|
// Check that none of the attributes are non-dialect attributes, except for
|
|
// the symbol name attribute.
|
|
for (auto attr : getOperation()->getAttrList().getAttrs()) {
|
|
if (!attr.first.strref().contains('.') &&
|
|
attr.first.strref() != mlir::SymbolTable::getSymbolAttrName())
|
|
return emitOpError(
|
|
"can only contain dialect-specific attributes, found: '")
|
|
<< attr.first << "'";
|
|
}
|
|
|
|
return success();
|
|
}
|
|
|
|
/// Return body of this module.
|
|
Region &ModuleOp::getBodyRegion() { return getOperation()->getRegion(0); }
|
|
Block *ModuleOp::getBody() { return &getBodyRegion().front(); }
|
|
|
|
StringRef ModuleOp::getName() {
|
|
if (auto nameAttr =
|
|
getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName()))
|
|
return nameAttr.getValue();
|
|
return {};
|
|
}
|