@@ -113,8 +113,11 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
113113 << " object " << objectName << " {\n " ;
114114 }
115115
116+ std::vector<std::shared_ptr<const Type>> visitedTypes;
117+
116118 for (const auto &typeDef : ir.typeDefs ) {
117- if (ir.shouldOutput (typeDef)) {
119+ visitedTypes.clear ();
120+ if (ir.shouldOutput (typeDef, visitedTypes)) {
118121 s << *typeDef;
119122 } else if (isAliasForOpaqueType (typeDef.get ()) &&
120123 ir.inMainFile (*typeDef)) {
@@ -177,7 +180,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
177180
178181 std::string sep = " " ;
179182 for (const auto &e : ir.enums ) {
180- if (ir.shouldOutput (e)) {
183+ visitedTypes.clear ();
184+ if (ir.shouldOutput (e, visitedTypes)) {
181185 s << sep << *e;
182186 sep = " \n " ;
183187 }
@@ -190,13 +194,15 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
190194 s << " object " << ir.libName << " Helpers {\n " ;
191195
192196 for (const auto &st : ir.structs ) {
193- if (ir.shouldOutput (st) && st->hasHelperMethods ()) {
197+ visitedTypes.clear ();
198+ if (ir.shouldOutput (st, visitedTypes) && st->hasHelperMethods ()) {
194199 s << " \n " << st->generateHelperClass ();
195200 }
196201 }
197202
198203 for (const auto &u : ir.unions ) {
199- if (ir.shouldOutput (u) && u->hasHelperMethods ()) {
204+ visitedTypes.clear ();
205+ if (ir.shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
200206 s << " \n " << u->generateHelperClass ();
201207 }
202208 }
@@ -216,14 +222,17 @@ void IR::generate(const std::string &excludePrefix) {
216222}
217223
218224bool IR::hasHelperMethods () const {
225+ std::vector<std::shared_ptr<const Type>> visitedTypes;
219226 for (const auto &u : unions) {
220- if (shouldOutput (u) && u->hasHelperMethods ()) {
227+ visitedTypes.clear ();
228+ if (shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
221229 return true ;
222230 }
223231 }
224232
225233 for (const auto &s : structs) {
226- if (shouldOutput (s) && s->hasHelperMethods ()) {
234+ visitedTypes.clear ();
235+ if (shouldOutput (s, visitedTypes) && s->hasHelperMethods ()) {
227236 return true ;
228237 }
229238 }
@@ -272,8 +281,10 @@ void IR::replaceTypeInTypeDefs(std::shared_ptr<Type> oldType,
272281template <typename T>
273282bool IR::isTypeUsed (const std::vector<T> &declarations,
274283 std::shared_ptr<Type> type, bool stopOnTypeDefs) const {
284+ std::vector<std::shared_ptr<const Type>> visitedTypes;
275285 for (const auto &decl : declarations) {
276- if (decl->usesType (type, stopOnTypeDefs)) {
286+ visitedTypes.clear ();
287+ if (decl->usesType (type, stopOnTypeDefs, visitedTypes)) {
277288 return true ;
278289 }
279290 }
@@ -289,46 +300,55 @@ bool IR::typeIsUsedOnlyInTypeDefs(const std::shared_ptr<Type> &type) const {
289300 isTypeUsed (literalDefines, type, true ));
290301}
291302
292- bool IR::isTypeUsed (const std::shared_ptr<Type> &type,
293- bool checkRecursively) const {
294- if (checkRecursively) {
295- if (isTypeUsed (functions, type, true ) ||
296- isTypeUsed (variables, type, true ) ||
297- isTypeUsed (literalDefines, type, true )) {
298- return true ;
299- }
300- /* type is used if there exists another type that is used and that
301- * references this type */
302- for (const auto &typeDef : typeDefs) {
303- if (typeDef->usesType (type, false )) {
304- if (shouldOutput (typeDef)) {
305- return true ;
306- }
303+ bool IR::isTypeUsed (
304+ const std::shared_ptr<Type> &type,
305+ std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
306+ if (contains (type.get (), visitedTypes)) {
307+ return false ;
308+ }
309+ visitedTypes.push_back (type);
310+ if (isTypeUsed (functions, type, true ) ||
311+ isTypeUsed (variables, type, true ) ||
312+ isTypeUsed (literalDefines, type, true )) {
313+ return true ;
314+ }
315+ /* type is used if there exists another type that is used and that
316+ * references this type */
317+ std::vector<std::shared_ptr<const Type>> visitedTypesInner;
318+ for (const auto &typeDef : typeDefs) {
319+ visitedTypesInner.clear ();
320+ if (typeDef->usesType (type, false , visitedTypesInner)) {
321+ if (shouldOutput (typeDef, visitedTypes)) {
322+ return true ;
307323 }
308324 }
309- for (const auto &s : structs) {
310- /* stopOnTypeDefs parameter is true because because typedefs were
311- * checked */
312- if (s->usesType (type, true )) {
313- if (shouldOutput (s)) {
314- return true ;
315- }
325+ }
326+ for (const auto &s : structs) {
327+ /* stopOnTypeDefs parameter is true because because typedefs were
328+ * checked */
329+ visitedTypesInner.clear ();
330+ if (s->usesType (type, true , visitedTypesInner)) {
331+ if (shouldOutput (s, visitedTypes)) {
332+ return true ;
316333 }
317334 }
318- for (const auto &u : unions) {
319- /* stopOnTypeDefs parameter is true because because typedefs were
320- * checked */
321- if (u->usesType (type, true )) {
322- if (shouldOutput (u)) {
323- return true ;
324- }
335+ }
336+ for (const auto &u : unions) {
337+ /* stopOnTypeDefs parameter is true because because typedefs were
338+ * checked */
339+ visitedTypesInner.clear ();
340+ if (u->usesType (type, true , visitedTypesInner)) {
341+ if (shouldOutput (u, visitedTypes)) {
342+ return true ;
325343 }
326344 }
327- return false ;
328- } else {
329- return !(typeIsUsedOnlyInTypeDefs (type) &&
330- !isTypeUsed (typeDefs, type, false ));
331345 }
346+ return false ;
347+ }
348+
349+ bool IR::isTypeUsed (const std::shared_ptr<Type> &type) const {
350+ return !(typeIsUsedOnlyInTypeDefs (type) &&
351+ !isTypeUsed (typeDefs, type, false ));
332352}
333353
334354void IR::setScalaNames () {
@@ -460,17 +480,21 @@ template <typename T> bool IR::inMainFile(const T &type) const {
460480template <typename T>
461481bool IR::hasOutputtedDeclaration (
462482 const std::vector<std::shared_ptr<T>> &declarations) const {
483+ std::vector<std::shared_ptr<const Type>> visitedTypes;
463484 for (const auto &declaration : declarations) {
464- if (shouldOutput (declaration)) {
485+ visitedTypes.clear ();
486+ if (shouldOutput (declaration, visitedTypes)) {
465487 return true ;
466488 }
467489 }
468490 return false ;
469491}
470492
471493template <typename T>
472- bool IR::shouldOutput (const std::shared_ptr<T> &type) const {
473- if (isTypeUsed (type, true )) {
494+ bool IR::shouldOutput (
495+ const std::shared_ptr<T> &type,
496+ std::vector<std::shared_ptr<const Type>> &visitedTypes) const {
497+ if (isTypeUsed (type, visitedTypes)) {
474498 return true ;
475499 }
476500 if (!inMainFile (*type)) {
0 commit comments