@@ -274,6 +274,9 @@ class AstCloner : public AstNodeVisitor {
274
274
}
275
275
276
276
absl::Status HandleEnumDef (const EnumDef* n) override {
277
+ if (old_to_new_.contains (n)) {
278
+ return absl::OkStatus ();
279
+ }
277
280
XLS_RETURN_IF_ERROR (VisitChildren (n));
278
281
279
282
NameDef* new_name_def = down_cast<NameDef*>(old_to_new_.at (n->name_def ()));
@@ -845,6 +848,9 @@ class AstCloner : public AstNodeVisitor {
845
848
}
846
849
847
850
absl::Status HandleStructDef (const StructDef* n) override {
851
+ if (old_to_new_.contains (n)) {
852
+ return absl::OkStatus ();
853
+ }
848
854
absl::Status status = HandleStructDefBaseInternal (n);
849
855
if (status.ok ()) {
850
856
AstNode* new_node = old_to_new_.at (n);
@@ -859,6 +865,9 @@ class AstCloner : public AstNodeVisitor {
859
865
}
860
866
861
867
absl::Status HandleProcDef (const ProcDef* n) override {
868
+ if (old_to_new_.contains (n)) {
869
+ return absl::OkStatus ();
870
+ }
862
871
return HandleStructDefBaseInternal (n);
863
872
}
864
873
@@ -985,6 +994,13 @@ class AstCloner : public AstNodeVisitor {
985
994
}
986
995
987
996
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
+ }
988
1004
XLS_RETURN_IF_ERROR (VisitChildren (n));
989
1005
990
1006
NameDef* new_name_def = down_cast<NameDef*>(old_to_new_.at (&n->name_def ()));
@@ -1003,14 +1019,71 @@ class AstCloner : public AstNodeVisitor {
1003
1019
absl::Status HandleTypeRef (const TypeRef* n) override {
1004
1020
TypeDefinition new_type_definition = n->type_definition ();
1005
1021
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.
1008
1026
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
+ },
1014
1087
n->type_definition ()));
1015
1088
1016
1089
old_to_new_[n] = module (n)->Make <TypeRef>(n->span (), new_type_definition);
0 commit comments