[HW] [NFC] Extract out printing/parsing functions for modules (#1773)

This commit is contained in:
John Demme 2021-09-14 19:50:41 -07:00 committed by GitHub
parent 4730fe8361
commit af8b1f500e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 233 additions and 89 deletions

View File

@ -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

View File

@ -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

View File

@ -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({});

View File

@ -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 << ')';
}
}