mirror of https://github.com/llvm/circt.git
[HW] [NFC] Extract out printing/parsing functions for modules (#1773)
This commit is contained in:
parent
4730fe8361
commit
af8b1f500e
|
@ -0,0 +1,59 @@
|
|||
//===- ModuleImplementation.h - Module-like Op utilities --------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides utility functions for implementing module-like
|
||||
// operations, in particular, parsing, and printing common to module-like
|
||||
// operations.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CIRCT_DIALECT_HW_MODULEIMPLEMENTATION_H
|
||||
#define CIRCT_DIALECT_HW_MODULEIMPLEMENTATION_H
|
||||
|
||||
#include "circt/Support/LLVM.h"
|
||||
|
||||
#include "mlir/IR/DialectImplementation.h"
|
||||
|
||||
namespace circt {
|
||||
namespace hw {
|
||||
|
||||
namespace module_like_impl {
|
||||
|
||||
/// Parse a portname as a keyword or a quote surrounded string, followed by a
|
||||
/// colon.
|
||||
StringAttr parsePortName(OpAsmParser &parser);
|
||||
|
||||
/// Get the portname from an SSA value string, if said value name is not a
|
||||
/// number.
|
||||
StringAttr getPortNameAttr(MLIRContext *context, StringRef name);
|
||||
|
||||
/// This is a variant of mlor::parseFunctionSignature that allows names on
|
||||
/// result arguments.
|
||||
ParseResult parseModuleFunctionSignature(
|
||||
OpAsmParser &parser, SmallVectorImpl<OpAsmParser::OperandType> &argNames,
|
||||
SmallVectorImpl<Type> &argTypes, SmallVectorImpl<NamedAttrList> &argAttrs,
|
||||
bool &isVariadic, SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames);
|
||||
|
||||
/// Parse a function result list with named results.
|
||||
ParseResult parseFunctionResultList(OpAsmParser &parser,
|
||||
SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames);
|
||||
|
||||
/// Print a module signature with named results.
|
||||
void printModuleSignature(OpAsmPrinter &p, Operation *op,
|
||||
ArrayRef<Type> argTypes, bool isVariadic,
|
||||
ArrayRef<Type> resultTypes, bool &needArgNamesAttr);
|
||||
|
||||
} // namespace module_like_impl
|
||||
} // namespace hw
|
||||
} // namespace circt
|
||||
|
||||
#endif // CIRCT_DIALECT_HW_MODULEIMPLEMENTATION_H
|
|
@ -1,6 +1,8 @@
|
|||
file(GLOB globbed *.cpp)
|
||||
add_circt_dialect_library(CIRCTHW
|
||||
${globbed}
|
||||
HWDialect.cpp
|
||||
HWOps.cpp
|
||||
HWTypes.cpp
|
||||
ModuleImplementation.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${CIRCT_MAIN_INCLUDE_DIR}/circt/Dialect/HW
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "circt/Dialect/HW/HWOps.h"
|
||||
#include "circt/Dialect/Comb/CombOps.h"
|
||||
#include "circt/Dialect/HW/HWVisitors.h"
|
||||
#include "circt/Dialect/HW/ModuleImplementation.h"
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/FunctionImplementation.h"
|
||||
|
||||
|
@ -31,19 +32,6 @@ static bool isValidKeyword(StringRef name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Parse a portname as a keyword or a quote surrounded string, followed by a
|
||||
// colon.
|
||||
static StringAttr parsePortName(OpAsmParser &parser) {
|
||||
StringAttr result;
|
||||
StringRef keyword;
|
||||
if (succeeded(parser.parseOptionalKeyword(&keyword))) {
|
||||
result = parser.getBuilder().getStringAttr(keyword);
|
||||
} else if (parser.parseAttribute(result,
|
||||
parser.getBuilder().getType<NoneType>()))
|
||||
return {};
|
||||
return succeeded(parser.parseColon()) ? result : StringAttr();
|
||||
}
|
||||
|
||||
/// Return true if the specified operation is a combinatorial logic op.
|
||||
bool hw::isCombinatorial(Operation *op) {
|
||||
struct IsCombClassifier : public TypeOpVisitor<IsCombClassifier, bool> {
|
||||
|
@ -385,74 +373,6 @@ SmallVector<PortInfo> hw::getAllModulePortInfos(Operation *op) {
|
|||
return results;
|
||||
}
|
||||
|
||||
static StringAttr getPortNameAttr(MLIRContext *context, StringRef name) {
|
||||
if (!name.empty()) {
|
||||
// Ignore numeric names like %42
|
||||
assert(name.size() > 1 && name[0] == '%' && "Unknown MLIR name");
|
||||
if (isdigit(name[1]))
|
||||
name = StringRef();
|
||||
else
|
||||
name = name.drop_front();
|
||||
}
|
||||
return StringAttr::get(context, name);
|
||||
}
|
||||
|
||||
/// Parse a function result list.
|
||||
///
|
||||
/// function-result-list ::= function-result-list-parens
|
||||
/// function-result-list-parens ::= `(` `)`
|
||||
/// | `(` function-result-list-no-parens `)`
|
||||
/// function-result-list-no-parens ::= function-result (`,` function-result)*
|
||||
/// function-result ::= (percent-identifier `:`) type attribute-dict?
|
||||
///
|
||||
static ParseResult
|
||||
parseFunctionResultList(OpAsmParser &parser, SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames) {
|
||||
if (parser.parseLParen())
|
||||
return failure();
|
||||
|
||||
// Special case for an empty set of parens.
|
||||
if (succeeded(parser.parseOptionalRParen()))
|
||||
return success();
|
||||
|
||||
// Parse individual function results.
|
||||
do {
|
||||
resultNames.push_back(parsePortName(parser));
|
||||
if (!resultNames.back())
|
||||
return failure();
|
||||
|
||||
resultTypes.emplace_back();
|
||||
resultAttrs.emplace_back();
|
||||
if (parser.parseType(resultTypes.back()) ||
|
||||
parser.parseOptionalAttrDict(resultAttrs.back()))
|
||||
return failure();
|
||||
} while (succeeded(parser.parseOptionalComma()));
|
||||
return parser.parseRParen();
|
||||
}
|
||||
|
||||
/// This is a variant of mlor::parseFunctionSignature that allows names on
|
||||
/// result arguments.
|
||||
static ParseResult parseModuleFunctionSignature(
|
||||
OpAsmParser &parser, SmallVectorImpl<OpAsmParser::OperandType> &argNames,
|
||||
SmallVectorImpl<Type> &argTypes, SmallVectorImpl<NamedAttrList> &argAttrs,
|
||||
bool &isVariadic, SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames) {
|
||||
|
||||
using namespace mlir::function_like_impl;
|
||||
bool allowArgAttrs = true;
|
||||
bool allowVariadic = false;
|
||||
if (parseFunctionArgumentList(parser, allowArgAttrs, allowVariadic, argNames,
|
||||
argTypes, argAttrs, isVariadic))
|
||||
return failure();
|
||||
|
||||
if (succeeded(parser.parseOptionalArrow()))
|
||||
return parseFunctionResultList(parser, resultTypes, resultAttrs,
|
||||
resultNames);
|
||||
return success();
|
||||
}
|
||||
|
||||
static bool hasAttribute(StringRef name, ArrayRef<NamedAttribute> attrs) {
|
||||
for (auto &argAttr : attrs)
|
||||
if (argAttr.first == name)
|
||||
|
@ -490,9 +410,9 @@ static ParseResult parseHWModuleOp(OpAsmParser &parser, OperationState &result,
|
|||
// Parse the function signature.
|
||||
bool isVariadic = false;
|
||||
SmallVector<Attribute> resultNames;
|
||||
if (parseModuleFunctionSignature(parser, entryArgs, argTypes, argAttrs,
|
||||
isVariadic, resultTypes, resultAttrs,
|
||||
resultNames))
|
||||
if (module_like_impl::parseModuleFunctionSignature(
|
||||
parser, entryArgs, argTypes, argAttrs, isVariadic, resultTypes,
|
||||
resultAttrs, resultNames))
|
||||
return failure();
|
||||
|
||||
// Record the argument and result types as an attribute. This is necessary
|
||||
|
@ -517,7 +437,7 @@ static ParseResult parseHWModuleOp(OpAsmParser &parser, OperationState &result,
|
|||
SmallVector<Attribute> argNames;
|
||||
if (!entryArgs.empty()) {
|
||||
for (auto &arg : entryArgs)
|
||||
argNames.push_back(getPortNameAttr(context, arg.name));
|
||||
argNames.push_back(module_like_impl::getPortNameAttr(context, arg.name));
|
||||
} else if (!argTypes.empty()) {
|
||||
// The parser returns empty names in a special way.
|
||||
argNames.assign(argTypes.size(), StringAttr::get(context, ""));
|
||||
|
@ -907,7 +827,7 @@ static ParseResult parseInstanceOp(OpAsmParser &parser,
|
|||
result.attributes) ||
|
||||
parser.getCurrentLocation(&inputsOperandsLoc) ||
|
||||
parseCommaSeparatedList([&]() -> ParseResult {
|
||||
argNames.push_back(parsePortName(parser));
|
||||
argNames.push_back(module_like_impl::parsePortName(parser));
|
||||
if (!argNames.back())
|
||||
return failure();
|
||||
inputsOperands.push_back({});
|
||||
|
@ -919,7 +839,7 @@ static ParseResult parseInstanceOp(OpAsmParser &parser,
|
|||
parser.resolveOperands(inputsOperands, inputsTypes, inputsOperandsLoc,
|
||||
result.operands) ||
|
||||
parser.parseArrow() || parseCommaSeparatedList([&]() -> ParseResult {
|
||||
resultNames.push_back(parsePortName(parser));
|
||||
resultNames.push_back(module_like_impl::parsePortName(parser));
|
||||
if (!resultNames.back())
|
||||
return failure();
|
||||
allResultTypes.push_back({});
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
//===- ModuleImplementation.cpp - Utilities for module-like ops -----------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "circt/Dialect/HW/ModuleImplementation.h"
|
||||
#include "circt/Dialect/HW/HWOps.h"
|
||||
#include "circt/Support/LLVM.h"
|
||||
|
||||
#include "mlir/IR/Builders.h"
|
||||
#include "mlir/IR/DialectImplementation.h"
|
||||
#include "mlir/IR/FunctionImplementation.h"
|
||||
|
||||
using namespace mlir;
|
||||
using namespace circt::hw;
|
||||
|
||||
/// Get the portname from an SSA value string, if said value name is not a
|
||||
/// number
|
||||
StringAttr module_like_impl::getPortNameAttr(MLIRContext *context,
|
||||
StringRef name) {
|
||||
if (!name.empty()) {
|
||||
// Ignore numeric names like %42
|
||||
assert(name.size() > 1 && name[0] == '%' && "Unknown MLIR name");
|
||||
if (isdigit(name[1]))
|
||||
name = StringRef();
|
||||
else
|
||||
name = name.drop_front();
|
||||
}
|
||||
return StringAttr::get(context, name);
|
||||
}
|
||||
|
||||
/// Parse a portname as a keyword or a quote surrounded string, followed by a
|
||||
/// colon.
|
||||
StringAttr module_like_impl::parsePortName(OpAsmParser &parser) {
|
||||
StringAttr result;
|
||||
StringRef keyword;
|
||||
if (succeeded(parser.parseOptionalKeyword(&keyword))) {
|
||||
result = parser.getBuilder().getStringAttr(keyword);
|
||||
} else if (parser.parseAttribute(result,
|
||||
parser.getBuilder().getType<NoneType>()))
|
||||
return {};
|
||||
return succeeded(parser.parseColon()) ? result : StringAttr();
|
||||
}
|
||||
|
||||
/// Parse a function result list.
|
||||
///
|
||||
/// function-result-list ::= function-result-list-parens
|
||||
/// function-result-list-parens ::= `(` `)`
|
||||
/// | `(` function-result-list-no-parens `)`
|
||||
/// function-result-list-no-parens ::= function-result (`,` function-result)*
|
||||
/// function-result ::= (percent-identifier `:`) type attribute-dict?
|
||||
///
|
||||
ParseResult module_like_impl::parseFunctionResultList(
|
||||
OpAsmParser &parser, SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames) {
|
||||
if (parser.parseLParen())
|
||||
return failure();
|
||||
|
||||
// Special case for an empty set of parens.
|
||||
if (succeeded(parser.parseOptionalRParen()))
|
||||
return success();
|
||||
|
||||
// Parse individual function results.
|
||||
do {
|
||||
resultNames.push_back(parsePortName(parser));
|
||||
if (!resultNames.back())
|
||||
return failure();
|
||||
|
||||
resultTypes.emplace_back();
|
||||
resultAttrs.emplace_back();
|
||||
if (parser.parseType(resultTypes.back()) ||
|
||||
parser.parseOptionalAttrDict(resultAttrs.back()))
|
||||
return failure();
|
||||
} while (succeeded(parser.parseOptionalComma()));
|
||||
return parser.parseRParen();
|
||||
}
|
||||
|
||||
/// This is a variant of mlor::parseFunctionSignature that allows names on
|
||||
/// result arguments.
|
||||
ParseResult module_like_impl::parseModuleFunctionSignature(
|
||||
OpAsmParser &parser, SmallVectorImpl<OpAsmParser::OperandType> &argNames,
|
||||
SmallVectorImpl<Type> &argTypes, SmallVectorImpl<NamedAttrList> &argAttrs,
|
||||
bool &isVariadic, SmallVectorImpl<Type> &resultTypes,
|
||||
SmallVectorImpl<NamedAttrList> &resultAttrs,
|
||||
SmallVectorImpl<Attribute> &resultNames) {
|
||||
|
||||
using namespace mlir::function_like_impl;
|
||||
bool allowArgAttrs = true;
|
||||
bool allowVariadic = false;
|
||||
if (parseFunctionArgumentList(parser, allowArgAttrs, allowVariadic, argNames,
|
||||
argTypes, argAttrs, isVariadic))
|
||||
return failure();
|
||||
|
||||
if (succeeded(parser.parseOptionalArrow()))
|
||||
return parseFunctionResultList(parser, resultTypes, resultAttrs,
|
||||
resultNames);
|
||||
return success();
|
||||
}
|
||||
|
||||
void circt::hw::module_like_impl::printModuleSignature(
|
||||
OpAsmPrinter &p, Operation *op, ArrayRef<Type> argTypes, bool isVariadic,
|
||||
ArrayRef<Type> resultTypes, bool &needArgNamesAttr) {
|
||||
Region &body = op->getRegion(0);
|
||||
bool isExternal = body.empty();
|
||||
SmallString<32> resultNameStr;
|
||||
|
||||
p << '(';
|
||||
for (unsigned i = 0, e = argTypes.size(); i < e; ++i) {
|
||||
if (i > 0)
|
||||
p << ", ";
|
||||
|
||||
auto argName = getModuleArgumentName(op, i);
|
||||
|
||||
if (!isExternal) {
|
||||
// Get the printed format for the argument name.
|
||||
resultNameStr.clear();
|
||||
llvm::raw_svector_ostream tmpStream(resultNameStr);
|
||||
p.printOperand(body.front().getArgument(i), tmpStream);
|
||||
|
||||
// If the name wasn't printable in a way that agreed with argName, make
|
||||
// sure to print out an explicit argNames attribute.
|
||||
if (tmpStream.str().drop_front() != argName)
|
||||
needArgNamesAttr = true;
|
||||
|
||||
p << tmpStream.str() << ": ";
|
||||
} else if (!argName.empty()) {
|
||||
p << '%' << argName << ": ";
|
||||
}
|
||||
|
||||
p.printType(argTypes[i]);
|
||||
p.printOptionalAttrDict(::mlir::function_like_impl::getArgAttrs(op, i));
|
||||
}
|
||||
|
||||
if (isVariadic) {
|
||||
if (!argTypes.empty())
|
||||
p << ", ";
|
||||
p << "...";
|
||||
}
|
||||
|
||||
p << ')';
|
||||
|
||||
// We print result types specially since we support named arguments.
|
||||
if (!resultTypes.empty()) {
|
||||
auto &os = p.getStream();
|
||||
os << " -> (";
|
||||
for (size_t i = 0, e = resultTypes.size(); i < e; ++i) {
|
||||
if (i != 0)
|
||||
os << ", ";
|
||||
StringRef name = getModuleResultName(op, i);
|
||||
if (!name.empty())
|
||||
os << '%' << name << ": ";
|
||||
|
||||
p.printType(resultTypes[i]);
|
||||
p.printOptionalAttrDict(
|
||||
::mlir::function_like_impl::getResultAttrs(op, i));
|
||||
}
|
||||
os << ')';
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue