10#include "slang/text/SFormat.h"
14using namespace ImportVerilog;
16using moore::IntFormat;
17using moore::IntPadding;
18using slang::SFormat::FormatOptions;
21struct FormatStringParser {
25 ArrayRef<const slang::ast::Expression *> arguments;
30 IntFormat defaultFormat;
33 SmallVector<Value> fragments;
35 FormatStringParser(
Context &context,
36 ArrayRef<const slang::ast::Expression *> arguments,
37 Location loc, IntFormat defaultFormat)
38 : context(context), builder(context.builder), arguments(arguments),
39 loc(loc), defaultFormat(defaultFormat) {}
42 FailureOr<Value> parse(
bool appendNewline) {
43 while (!arguments.empty()) {
44 const auto &arg = *arguments[0];
45 arguments = arguments.drop_front();
46 if (arg.kind == slang::ast::ExpressionKind::EmptyArgument)
49 if (
auto *lit = arg.as_if<slang::ast::StringLiteral>()) {
50 if (failed(parseFormat(lit->getValue())))
53 if (failed(emitDefault(arg)))
64 if (fragments.empty())
66 if (fragments.size() == 1)
68 return builder.create<moore::FormatConcatOp>(loc, fragments).getResult();
73 LogicalResult parseFormat(StringRef format) {
74 bool anyFailure =
false;
75 auto onText = [&](
auto text) {
80 auto onArg = [&](
auto specifier,
auto offset,
auto len,
81 const auto &options) {
84 if (failed(emitArgument(specifier, format.substr(offset, len), options)))
87 auto onError = [&](
auto,
auto,
auto,
auto) {
88 assert(
false &&
"Slang should have already reported all errors");
90 slang::SFormat::parse(format, onText, onArg, onError);
91 return failure(anyFailure);
95 void emitLiteral(StringRef literal) {
96 fragments.push_back(builder.create<moore::FormatLiteralOp>(loc, literal));
101 LogicalResult emitArgument(
char specifier, StringRef fullSpecifier,
102 const FormatOptions &options) {
103 auto specifierLower = std::tolower(specifier);
106 if (specifierLower ==
'm' || specifierLower ==
'l')
107 return mlir::emitError(loc)
108 <<
"unsupported format specifier `" << fullSpecifier <<
"`";
112 assert(!arguments.empty() &&
"Slang guarantees correct arg count");
113 const auto &arg = *arguments[0];
114 arguments = arguments.drop_front();
119 switch (specifierLower) {
121 return emitInteger(arg, options, IntFormat::Binary);
123 return emitInteger(arg, options, IntFormat::Octal);
125 return emitInteger(arg, options, IntFormat::Decimal);
128 return emitInteger(arg, options,
129 std::isupper(specifier) ? IntFormat::HexUpper
130 : IntFormat::HexLower);
134 if (
auto *lit = arg.as_if<slang::ast::StringLiteral>()) {
136 return mlir::emitError(loc)
137 <<
"string format specifier with width not supported";
138 emitLiteral(lit->getValue());
141 return mlir::emitError(argLoc)
142 <<
"expression cannot be formatted as string";
145 return mlir::emitError(loc)
146 <<
"unsupported format specifier `" << fullSpecifier <<
"`";
151 LogicalResult emitInteger(
const slang::ast::Expression &arg,
152 const FormatOptions &options, IntFormat format) {
161 width = *options.width;
163 width = cast<moore::IntType>(value.getType()).getWidth();
164 if (format == IntFormat::Octal)
166 width = (width + 2) / 3;
167 else if (format == IntFormat::HexLower || format == IntFormat::HexUpper)
169 width = (width + 3) / 4;
170 else if (format == IntFormat::Decimal)
172 width = std::ceil(width * std::log(2) / std::log(10));
176 auto alignment = options.leftJustify ? IntAlign::Left : IntAlign::Right;
178 format == IntFormat::Decimal ? IntPadding::Space : IntPadding::Zero;
180 fragments.push_back(builder.create<moore::FormatIntOp>(
181 loc, value, format, width, alignment, padding));
186 LogicalResult emitDefault(
const slang::ast::Expression &expr) {
187 FormatOptions options;
188 return emitInteger(expr, options, defaultFormat);
194 slang::span<const slang::ast::Expression *const> arguments, Location loc,
195 IntFormat defaultFormat,
bool appendNewline) {
196 FormatStringParser parser(*
this, ArrayRef(arguments.data(), arguments.size()),
198 return parser.parse(appendNewline);
assert(baseType &&"element must be base type")
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
FailureOr< Value > convertFormatString(slang::span< const slang::ast::Expression *const > arguments, Location loc, moore::IntFormat defaultFormat=moore::IntFormat::Decimal, bool appendNewline=false)
Convert a list of string literal arguments with formatting specifiers and arguments to be interpolate...
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
Value convertToSimpleBitVector(Value value)
Helper function to convert a value to its simple bit vector representation, if it has one.
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.