@@ -113,8 +113,11 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
113
113
<< " object " << objectName << " {\n " ;
114
114
}
115
115
116
+ std::vector<std::shared_ptr<const Type>> visitedTypes;
117
+
116
118
for (const auto &typeDef : ir.typeDefs ) {
117
- if (ir.shouldOutput (typeDef)) {
119
+ visitedTypes.clear ();
120
+ if (ir.shouldOutput (typeDef, visitedTypes)) {
118
121
s << *typeDef;
119
122
} else if (isAliasForOpaqueType (typeDef.get ()) &&
120
123
ir.inMainFile (*typeDef)) {
@@ -177,7 +180,8 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
177
180
178
181
std::string sep = " " ;
179
182
for (const auto &e : ir.enums ) {
180
- if (ir.shouldOutput (e)) {
183
+ visitedTypes.clear ();
184
+ if (ir.shouldOutput (e, visitedTypes)) {
181
185
s << sep << *e;
182
186
sep = " \n " ;
183
187
}
@@ -190,13 +194,15 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &s, const IR &ir) {
190
194
s << " object " << ir.libName << " Helpers {\n " ;
191
195
192
196
for (const auto &st : ir.structs ) {
193
- if (ir.shouldOutput (st) && st->hasHelperMethods ()) {
197
+ visitedTypes.clear ();
198
+ if (ir.shouldOutput (st, visitedTypes) && st->hasHelperMethods ()) {
194
199
s << " \n " << st->generateHelperClass ();
195
200
}
196
201
}
197
202
198
203
for (const auto &u : ir.unions ) {
199
- if (ir.shouldOutput (u) && u->hasHelperMethods ()) {
204
+ visitedTypes.clear ();
205
+ if (ir.shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
200
206
s << " \n " << u->generateHelperClass ();
201
207
}
202
208
}
@@ -216,14 +222,17 @@ void IR::generate(const std::string &excludePrefix) {
216
222
}
217
223
218
224
bool IR::hasHelperMethods () const {
225
+ std::vector<std::shared_ptr<const Type>> visitedTypes;
219
226
for (const auto &u : unions) {
220
- if (shouldOutput (u) && u->hasHelperMethods ()) {
227
+ visitedTypes.clear ();
228
+ if (shouldOutput (u, visitedTypes) && u->hasHelperMethods ()) {
221
229
return true ;
222
230
}
223
231
}
224
232
225
233
for (const auto &s : structs) {
226
- if (shouldOutput (s) && s->hasHelperMethods ()) {
234
+ visitedTypes.clear ();
235
+ if (shouldOutput (s, visitedTypes) && s->hasHelperMethods ()) {
227
236
return true ;
228
237
}
229
238
}
@@ -272,8 +281,10 @@ void IR::replaceTypeInTypeDefs(std::shared_ptr<Type> oldType,
272
281
template <typename T>
273
282
bool IR::isTypeUsed (const std::vector<T> &declarations,
274
283
std::shared_ptr<Type> type, bool stopOnTypeDefs) const {
284
+ std::vector<std::shared_ptr<const Type>> visitedTypes;
275
285
for (const auto &decl : declarations) {
276
- if (decl->usesType (type, stopOnTypeDefs)) {
286
+ visitedTypes.clear ();
287
+ if (decl->usesType (type, stopOnTypeDefs, visitedTypes)) {
277
288
return true ;
278
289
}
279
290
}
@@ -289,46 +300,55 @@ bool IR::typeIsUsedOnlyInTypeDefs(const std::shared_ptr<Type> &type) const {
289
300
isTypeUsed (literalDefines, type, true ));
290
301
}
291
302
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 ;
307
323
}
308
324
}
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 ;
316
333
}
317
334
}
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 ;
325
343
}
326
344
}
327
- return false ;
328
- } else {
329
- return !(typeIsUsedOnlyInTypeDefs (type) &&
330
- !isTypeUsed (typeDefs, type, false ));
331
345
}
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 ));
332
352
}
333
353
334
354
void IR::setScalaNames () {
@@ -460,17 +480,21 @@ template <typename T> bool IR::inMainFile(const T &type) const {
460
480
template <typename T>
461
481
bool IR::hasOutputtedDeclaration (
462
482
const std::vector<std::shared_ptr<T>> &declarations) const {
483
+ std::vector<std::shared_ptr<const Type>> visitedTypes;
463
484
for (const auto &declaration : declarations) {
464
- if (shouldOutput (declaration)) {
485
+ visitedTypes.clear ();
486
+ if (shouldOutput (declaration, visitedTypes)) {
465
487
return true ;
466
488
}
467
489
}
468
490
return false ;
469
491
}
470
492
471
493
template <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)) {
474
498
return true ;
475
499
}
476
500
if (!inMainFile (*type)) {
0 commit comments