Skip to content

Commit 475b936

Browse files
authored
[FIRRTL] Fix: Enforce flat namespace for modules (#8345)
Added a check for duplicates in the symbolTable. Added and removed tests for the same. - fixes #7773 - fixes #1537
1 parent ca4feb6 commit 475b936

File tree

3 files changed

+74
-23
lines changed

3 files changed

+74
-23
lines changed

lib/Dialect/FIRRTL/Import/FIRParser.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,9 @@ struct FIRModuleContext : public FIRParser {
14301430
insertNameIntoGlobalScope);
14311431
}
14321432

1433+
// Removes a symbol from symbolTable (Workaround since symbolTable is private)
1434+
void removeSymbolEntry(StringRef name);
1435+
14331436
/// Resolved a symbol table entry to a value. Emission of error is optional.
14341437
ParseResult resolveSymbolEntry(Value &result, SymbolValueEntry &entry,
14351438
SMLoc loc, bool fatal = true);
@@ -1511,6 +1514,11 @@ struct FIRModuleContext : public FIRParser {
15111514

15121515
} // end anonymous namespace
15131516

1517+
// Removes a symbol from symbolTable (Workaround since symbolTable is private)
1518+
void FIRModuleContext::removeSymbolEntry(StringRef name) {
1519+
symbolTable.erase(name);
1520+
}
1521+
15141522
/// Add a symbol entry with the specified name, returning failure if the name
15151523
/// is already defined.
15161524
///
@@ -1522,12 +1530,22 @@ ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
15221530
bool insertNameIntoGlobalScope) {
15231531
// Do a lookup by trying to do an insertion. Do so in a way that we can tell
15241532
// if we hit a missing element (SMLoc is null).
1525-
auto entryIt =
1526-
symbolTable.try_emplace(name, SMLoc(), SymbolValueEntry()).first;
1527-
if (entryIt->second.first.isValid()) {
1528-
emitError(loc, "redefinition of name '" + name + "'")
1529-
.attachNote(translateLocation(entryIt->second.first))
1530-
<< "previous definition here";
1533+
auto [entryIt, inserted] =
1534+
symbolTable.try_emplace(name, SMLoc(), SymbolValueEntry());
1535+
1536+
// If insertion failed, the name already exists
1537+
if (!inserted) {
1538+
if (entryIt->second.first.isValid()) {
1539+
// Valid activeSMLoc: active symbol in current scope redeclared
1540+
emitError(loc, "redefinition of name '" + name + "' ")
1541+
.attachNote(translateLocation(entryIt->second.first))
1542+
<< "previous definition here.";
1543+
} else {
1544+
// Invalid activeSMLoc: symbol from a completed scope redeclared
1545+
emitError(loc, "redefinition of name '" + name + "' ")
1546+
<< "- FIRRTL has flat namespace and requires all "
1547+
<< "declarations in a module to have unique names.";
1548+
}
15311549
return failure();
15321550
}
15331551

@@ -1536,7 +1554,6 @@ ParseResult FIRModuleContext::addSymbolEntry(StringRef name,
15361554
entryIt->second = {loc, entry};
15371555
if (currentScope && !insertNameIntoGlobalScope)
15381556
currentScope->scopedDecls.push_back(&*entryIt);
1539-
15401557
return success();
15411558
}
15421559

@@ -4878,10 +4895,12 @@ ParseResult FIRStmtParser::parseContract(unsigned blockIndent) {
48784895

48794896
// Declare the results.
48804897
for (auto [id, loc, value, result] :
4881-
llvm::zip(ids, locs, values, contract.getResults()))
4898+
llvm::zip(ids, locs, values, contract.getResults())) {
4899+
// Remove previous symbol to avoid duplicates
4900+
moduleContext.removeSymbolEntry(id);
48824901
if (failed(moduleContext.addSymbolEntry(id, result, loc)))
48834902
return failure();
4884-
4903+
}
48854904
return success();
48864905
}
48874906

test/Dialect/FIRRTL/parse-basic.fir

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,20 +211,6 @@ circuit MyModule : ; CHECK: firrtl.circuit "MyModule" {
211211
; CHECK: }
212212
when reset : connect _t, _t_2 else : connect _t, _t_2
213213

214-
; CHECK: firrtl.when %reset : !firrtl.uint<1> {
215-
; CHECK: [[N4A:%.+]] = firrtl.node interesting_name %_t_2
216-
; CHECK: firrtl.matchingconnect %_t, [[N4A]]
217-
; CHECK: } else {
218-
; CHECK: [[N4B:%.+]] = firrtl.node interesting_name %_t_2
219-
; CHECK: firrtl.matchingconnect %_t, [[N4B]]
220-
; CHECK: }
221-
when reset :
222-
node n4 = _t_2
223-
connect _t, n4
224-
else :
225-
node n4 = _t_2 ; 'n4' name is in unique scopes.
226-
connect _t, n4
227-
228214
; CHECK: [[TMP:%.+]] = firrtl.constant 4
229215
; CHECK: [[COND:%.+]] = firrtl.lt %reset, [[TMP]]
230216
; CHECK: firrtl.when [[COND]] : !firrtl.uint<1> {

test/Dialect/FIRRTL/parse-errors.fir

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,3 +1667,49 @@ circuit Top:
16671667
public module Top:
16681668
; expected-error @below {{contracts are a FIRRTL 5.1.0+ feature}}
16691669
contract:
1670+
1671+
// -----
1672+
FIRRTL version 4.0.0
1673+
circuit DuplicateWhenElse:
1674+
public module DuplicateWhenElse:
1675+
input reset: UInt<1>
1676+
output _t: UInt<1>
1677+
wire _t_2: UInt<1>
1678+
1679+
when reset :
1680+
node n4 = _t_2
1681+
connect _t, n4
1682+
else :
1683+
; expected-error @+1 {{redefinition of name 'n4' - FIRRTL has flat namespace and requires all declarations in a module to have unique names}}
1684+
node n4 = _t_2 ; 'n4' is duplicated across scopes
1685+
connect _t, n4
1686+
1687+
// -----
1688+
FIRRTL version 4.0.0
1689+
circuit SameScopeRedef:
1690+
public module SameScopeRedef:
1691+
input reset: UInt<1>
1692+
output _t: UInt<1>
1693+
wire _t_2: UInt<1>
1694+
1695+
; expected-note @+1 {{previous definition here}}
1696+
node x = _t_2
1697+
; expected-error @+1 {{redefinition of name 'x'}}
1698+
node x = _t_2 ; 'x' is duplicated in same scope
1699+
connect _t, x
1700+
1701+
// -----
1702+
FIRRTL version 4.0.0
1703+
circuit NestedWhenRedef:
1704+
public module NestedWhenRedef:
1705+
input reset: UInt<1>
1706+
output _t: UInt<1>
1707+
wire _t_2: UInt<1>
1708+
1709+
when reset :
1710+
; expected-note @+1 {{previous definition here}}
1711+
node val = _t_2
1712+
when reset :
1713+
; expected-error @+1 {{redefinition of name 'val'}}
1714+
node val = _t_2 ; 'val' is duplicated in nested when
1715+
connect _t, val

0 commit comments

Comments
 (0)