Skip to content

Commit

Permalink
[FIRRTL] Add list concatenation parser support. (#7512)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mikeurbach authored Aug 12, 2024
1 parent bb6471f commit 23371f8
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 0 deletions.
49 changes: 49 additions & 0 deletions lib/Dialect/FIRRTL/Import/FIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ParseResult> parseExpWithLeadingKeyword(FIRToken keyword);

Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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<Value, 3> 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<ListType>(operand.getType()))
return emitError(loc, "unexpected expression of type ")
<< operand.getType() << " in List concat expression";

if (!type)
type = type_cast<ListType>(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<ListConcatOp>(type, operands);
return success();
}

/// The .fir grammar has the annoying property where:
/// 1) some statements start with keywords
/// 2) some start with an expression
Expand Down
1 change: 1 addition & 0 deletions lib/Dialect/FIRRTL/Import/FIRTokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ TOK_LPKEYWORD(assume)
TOK_LPKEYWORD(cover)

TOK_LPKEYWORD(path)
TOK_LPKEYWORD(list_concat)

TOK_LPKEYWORD(force)
TOK_LPKEYWORD(force_initial)
Expand Down
14 changes: 14 additions & 0 deletions test/Dialect/FIRRTL/parse-basic.fir
Original file line number Diff line number Diff line change
Expand Up @@ -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<Integer>
input b : List<Integer>
output c : List<Integer>

; CHECK: [[C:%.+]] = firrtl.list.concat %a, %b
; CHECK: firrtl.propassign %c, [[C]]
propassign c, list_concat(a, b)

;// -----
FIRRTL version 3.1.0

Expand Down
36 changes: 36 additions & 0 deletions test/Dialect/FIRRTL/parse-errors.fir
Original file line number Diff line number Diff line change
Expand Up @@ -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<Integer>

; 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<Integer>
input b : List<String>
output c : List<Integer>

; expected-error @below {{unexpected expression of type '!firrtl.list<string>' in List concat expression of type '!firrtl.list<integer>'}}
propassign c, list_concat(a, b)

;// -----
FIRRTL version 4.0.0

; CHECK-LABEL: firrtl.circuit "Top"
circuit Top :
public module Top :
output c : List<Integer>

; expected-error @below {{need at least one List to concatenate}}
propassign c, list_concat()

;// -----
FIRRTL version 3.3.0

Expand Down

0 comments on commit 23371f8

Please sign in to comment.