Skip to content

Commit 007e8f6

Browse files
committed
Fix duplicated cloned type entities bug
1 parent 13c24f5 commit 007e8f6

File tree

2 files changed

+386
-9
lines changed

2 files changed

+386
-9
lines changed

xls/dslx/frontend/ast_cloner.cc

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ class AstCloner : public AstNodeVisitor {
274274
}
275275

276276
absl::Status HandleEnumDef(const EnumDef* n) override {
277+
if (old_to_new_.contains(n)) {
278+
return absl::OkStatus();
279+
}
277280
XLS_RETURN_IF_ERROR(VisitChildren(n));
278281

279282
NameDef* new_name_def = down_cast<NameDef*>(old_to_new_.at(n->name_def()));
@@ -845,6 +848,9 @@ class AstCloner : public AstNodeVisitor {
845848
}
846849

847850
absl::Status HandleStructDef(const StructDef* n) override {
851+
if (old_to_new_.contains(n)) {
852+
return absl::OkStatus();
853+
}
848854
absl::Status status = HandleStructDefBaseInternal(n);
849855
if (status.ok()) {
850856
AstNode* new_node = old_to_new_.at(n);
@@ -859,6 +865,9 @@ class AstCloner : public AstNodeVisitor {
859865
}
860866

861867
absl::Status HandleProcDef(const ProcDef* n) override {
868+
if (old_to_new_.contains(n)) {
869+
return absl::OkStatus();
870+
}
862871
return HandleStructDefBaseInternal(n);
863872
}
864873

@@ -985,6 +994,13 @@ class AstCloner : public AstNodeVisitor {
985994
}
986995

987996
absl::Status HandleTypeAlias(const TypeAlias* n) override {
997+
if (old_to_new_.contains(n)) {
998+
// Ensure the NameDef definer points at the already-cloned alias.
999+
NameDef* existing_name_def =
1000+
down_cast<NameDef*>(old_to_new_.at(&n->name_def()));
1001+
existing_name_def->set_definer(old_to_new_.at(n));
1002+
return absl::OkStatus();
1003+
}
9881004
XLS_RETURN_IF_ERROR(VisitChildren(n));
9891005

9901006
NameDef* new_name_def = down_cast<NameDef*>(old_to_new_.at(&n->name_def()));
@@ -1003,14 +1019,71 @@ class AstCloner : public AstNodeVisitor {
10031019
absl::Status HandleTypeRef(const TypeRef* n) override {
10041020
TypeDefinition new_type_definition = n->type_definition();
10051021

1006-
// A TypeRef doesn't own its referenced type definition, so we have to
1007-
// explicitly visit it.
1022+
// A TypeRef doesn't own its referenced type definition. Reuse an existing
1023+
// type definition in the target module (by identifier) to avoid
1024+
// duplicating type defs when cloning subtrees into an already-cloned
1025+
// module. If none exists yet, clone the referenced definition now.
10081026
XLS_RETURN_IF_ERROR(absl::visit(
1009-
Visitor{[&](auto* ref) -> absl::Status {
1010-
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1011-
new_type_definition = down_cast<decltype(ref)>(old_to_new_.at(ref));
1012-
return absl::OkStatus();
1013-
}},
1027+
Visitor{
1028+
// Reuse an existing same-named type definition already present
1029+
// in the target module for module-scoped type defs.
1030+
[&](TypeAlias* ref) -> absl::Status {
1031+
absl::StatusOr<TypeDefinition> existing =
1032+
module(n)->GetTypeDefinition(ref->identifier());
1033+
if (existing.ok()) {
1034+
new_type_definition = *existing;
1035+
return absl::OkStatus();
1036+
}
1037+
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1038+
new_type_definition =
1039+
down_cast<decltype(ref)>(old_to_new_.at(ref));
1040+
return absl::OkStatus();
1041+
},
1042+
[&](StructDef* ref) -> absl::Status {
1043+
absl::StatusOr<TypeDefinition> existing =
1044+
module(n)->GetTypeDefinition(ref->identifier());
1045+
if (existing.ok()) {
1046+
new_type_definition = *existing;
1047+
return absl::OkStatus();
1048+
}
1049+
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1050+
new_type_definition =
1051+
down_cast<decltype(ref)>(old_to_new_.at(ref));
1052+
return absl::OkStatus();
1053+
},
1054+
[&](ProcDef* ref) -> absl::Status {
1055+
absl::StatusOr<TypeDefinition> existing =
1056+
module(n)->GetTypeDefinition(ref->identifier());
1057+
if (existing.ok()) {
1058+
new_type_definition = *existing;
1059+
return absl::OkStatus();
1060+
}
1061+
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1062+
new_type_definition =
1063+
down_cast<decltype(ref)>(old_to_new_.at(ref));
1064+
return absl::OkStatus();
1065+
},
1066+
[&](EnumDef* ref) -> absl::Status {
1067+
absl::StatusOr<TypeDefinition> existing =
1068+
module(n)->GetTypeDefinition(ref->identifier());
1069+
if (existing.ok()) {
1070+
new_type_definition = *existing;
1071+
return absl::OkStatus();
1072+
}
1073+
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1074+
new_type_definition =
1075+
down_cast<decltype(ref)>(old_to_new_.at(ref));
1076+
return absl::OkStatus();
1077+
},
1078+
// For ColonRef* and UseTreeEntry* we cannot look up by identifier
1079+
// in the target module; just clone/visit as before.
1080+
[&](auto* ref) -> absl::Status {
1081+
XLS_RETURN_IF_ERROR(ReplaceOrVisit(ref));
1082+
new_type_definition =
1083+
down_cast<decltype(ref)>(old_to_new_.at(ref));
1084+
return absl::OkStatus();
1085+
},
1086+
},
10141087
n->type_definition()));
10151088

10161089
old_to_new_[n] = module(n)->Make<TypeRef>(n->span(), new_type_definition);

0 commit comments

Comments
 (0)