From bb9fbacdf6d8bc38f1fd7c65c49c7b94b9a1d971 Mon Sep 17 00:00:00 2001 From: Mike Urbach Date: Wed, 7 Aug 2024 10:22:41 -0700 Subject: [PATCH] [FIRRTL] Add list concatenation parser support. This parses `list_concat(exp+)` into the ListConcatOp. The type of the list is inferred during parsing, and all expressions must be the same. It is a parser error to not concatenate at least one list. --- lib/Dialect/FIRRTL/Import/FIRParser.cpp | 49 +++++++++++++++++++++ lib/Dialect/FIRRTL/Import/FIRTokenKinds.def | 1 + test/Dialect/FIRRTL/parse-basic.fir | 14 ++++++ test/Dialect/FIRRTL/parse-errors.fir | 36 +++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/lib/Dialect/FIRRTL/Import/FIRParser.cpp b/lib/Dialect/FIRRTL/Import/FIRParser.cpp index 1a38326136a1..40f6ddf2246d 100644 --- a/lib/Dialect/FIRRTL/Import/FIRParser.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRParser.cpp @@ -1720,6 +1720,7 @@ struct FIRStmtParser : public FIRParser { ParseResult parsePrimExp(Value &result); ParseResult parseIntegerLiteralExp(Value &result); ParseResult parseListExp(Value &result); + ParseResult parseListConcatExp(Value &result); std::optional parseExpWithLeadingKeyword(FIRToken keyword); @@ -1978,6 +1979,16 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, return failure(); break; } + + case FIRToken::lp_list_concat: { + if (isLeadingStmt) + return emitError("unexpected list_create() as start of statement"); + if (requireFeature(nextFIRVersion, "List concat") || + parseListConcatExp(result)) + return failure(); + break; + } + case FIRToken::lp_path: if (isLeadingStmt) return emitError("unexpected path() as start of statement"); @@ -2455,6 +2466,44 @@ ParseResult FIRStmtParser::parseListExp(Value &result) { return success(); } +/// list-concat-exp ::= 'list_concat' '(' exp* ')' +ParseResult FIRStmtParser::parseListConcatExp(Value &result) { + consumeToken(FIRToken::lp_list_concat); + + auto loc = getToken().getLoc(); + ListType type; + SmallVector operands; + if (parseListUntil(FIRToken::r_paren, [&]() -> ParseResult { + Value operand; + locationProcessor.setLoc(loc); + if (parseExp(operand, "expected expression in List concat expression")) + return failure(); + + if (!type_isa(operand.getType())) + return emitError(loc, "unexpected expression of type ") + << operand.getType() << " in List concat expression"; + + if (!type) + type = type_cast(operand.getType()); + + if (operand.getType() != type) + return emitError(loc, "unexpected expression of type ") + << operand.getType() << " in List concat expression of type " + << type; + + operands.push_back(operand); + return success(); + })) + return failure(); + + if (operands.empty()) + return emitError(loc, "need at least one List to concatenate"); + + locationProcessor.setLoc(loc); + result = builder.create(type, operands); + return success(); +} + /// The .fir grammar has the annoying property where: /// 1) some statements start with keywords /// 2) some start with an expression diff --git a/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def b/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def index 895779127065..b3983a86068c 100644 --- a/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def +++ b/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def @@ -169,6 +169,7 @@ TOK_LPKEYWORD(assume) TOK_LPKEYWORD(cover) TOK_LPKEYWORD(path) +TOK_LPKEYWORD(list_concat) TOK_LPKEYWORD(force) TOK_LPKEYWORD(force_initial) diff --git a/test/Dialect/FIRRTL/parse-basic.fir b/test/Dialect/FIRRTL/parse-basic.fir index 961cfba9e712..6bfd861f650f 100644 --- a/test/Dialect/FIRRTL/parse-basic.fir +++ b/test/Dialect/FIRRTL/parse-basic.fir @@ -1670,6 +1670,20 @@ circuit IntegerArithmetic : ; CHECK: firrtl.propassign %e, [[E]] propassign e, integer_shr(a, b) +;// ----- +FIRRTL version 4.0.0 + +; CHECK-LABEL: firrtl.circuit "PropertyListOps" +circuit PropertyListOps : + public module PropertyListOps : + input a : List + input b : List + output c : List + + ; CHECK: [[C:%.+]] = firrtl.list.concat %a, %b + ; CHECK: firrtl.propassign %c, [[C]] + propassign c, list_concat(a, b) + ;// ----- FIRRTL version 3.1.0 diff --git a/test/Dialect/FIRRTL/parse-errors.fir b/test/Dialect/FIRRTL/parse-errors.fir index 0ce93e169073..87cc7c60153b 100644 --- a/test/Dialect/FIRRTL/parse-errors.fir +++ b/test/Dialect/FIRRTL/parse-errors.fir @@ -1026,6 +1026,42 @@ circuit Top: ; expected-error @below {{Integer arithmetic expressions are a FIRRTL 4.0.0+ feature, but the specified FIRRTL version was 3.1.0}} propassign c, integer_shr(a, b) +;// ----- +FIRRTL version 4.0.0 + +; CHECK-LABEL: firrtl.circuit "Top" +circuit Top : + public module Top : + input a : Integer + output b : List + + ; expected-error @below {{unexpected expression of type '!firrtl.integer' in List concat expression}} + propassign b, list_concat(a) + +;// ----- +FIRRTL version 4.0.0 + +; CHECK-LABEL: firrtl.circuit "Top" +circuit Top : + public module Top : + input a : List + input b : List + output c : List + + ; expected-error @below {{unexpected expression of type '!firrtl.list' in List concat expression of type '!firrtl.list'}} + propassign c, list_concat(a, b) + +;// ----- +FIRRTL version 4.0.0 + +; CHECK-LABEL: firrtl.circuit "Top" +circuit Top : + public module Top : + output c : List + + ; expected-error @below {{need at least one List to concatenate}} + propassign c, list_concat() + ;// ----- FIRRTL version 3.3.0