@@ -318,73 +318,101 @@ getRecSelfConstructor(llvm::DINode *node) {
318
318
.Default (CtorType ());
319
319
}
320
320
321
- // / An attribute replacer that replaces nested recursive decls with recursive
322
- // / self-references instead.
323
- // /
321
+ // / An iterative attribute replacer that also handles pruning recursive types.
324
322
// / - Recurses down the attribute tree while replacing attributes based on the
325
323
// / provided replacement map.
326
324
// / - Keeps track of the currently open recursive declarations, and upon
327
- // / encountering a duplicate declaration, replace with a self-ref instead.
328
- static Attribute replaceAndPruneRecursiveTypesImpl (
329
- Attribute node,
330
- const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping,
331
- DenseSet<DistinctAttr> &openDecls) {
332
- DistinctAttr recId;
333
- if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(node)) {
334
- recId = recType.getRecId ();
335
-
336
- // Configure context.
337
- if (recId) {
338
- if (recType.isRecSelf ()) {
339
- // Replace selfRef based on the provided mapping.
340
- if (DINodeAttr replacement = mapping.lookup (recType))
341
- return replaceAndPruneRecursiveTypesImpl (replacement, mapping,
342
- openDecls);
343
- return node;
344
- }
325
+ // / encountering a duplicate declaration, replace with a self-reference.
326
+ static Attribute replaceAndPruneRecursiveTypes (
327
+ Attribute baseNode,
328
+ const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping) {
345
329
346
- auto [_, inserted] = openDecls.insert (recId);
347
- if (!inserted) {
348
- // This is a nested decl. Replace with recSelf.
349
- return recType.getRecSelf (recId);
330
+ struct ReplacementState {
331
+ // The attribute being replaced.
332
+ Attribute node;
333
+ // The nested elements of `node`.
334
+ SmallVector<Attribute> attrs;
335
+ SmallVector<Type> types;
336
+ // The current attr being walked on (index into `attrs`).
337
+ size_t attrIndex;
338
+ // Whether or not any attr was replaced.
339
+ bool changed;
340
+
341
+ void replaceCurrAttr (Attribute attr) {
342
+ Attribute &target = attrs[attrIndex];
343
+ if (attr != target) {
344
+ changed = true ;
345
+ target = attr;
350
346
}
351
347
}
352
- }
348
+ };
353
349
354
- // Collect sub attrs.
355
- SmallVector<Attribute> attrs;
356
- SmallVector<Type> types;
357
- node.walkImmediateSubElements (
358
- [&attrs](Attribute attr) { attrs.push_back (attr); },
359
- [&types](Type type) { types.push_back (type); });
360
-
361
- // Recurse into attributes.
362
- bool changed = false ;
363
- for (auto it = attrs.begin (); it != attrs.end (); it++) {
364
- Attribute replaced =
365
- replaceAndPruneRecursiveTypesImpl (*it, mapping, openDecls);
366
- if (replaced != *it) {
367
- *it = replaced;
368
- changed = true ;
369
- }
370
- }
350
+ // Every iteration, perform replacement on the attribute at `attrIndex` at the
351
+ // top of `workStack`.
352
+ // If `attrIndex` reaches past the size of `attrs`, replace `node` with
353
+ // `attrs` & `types`, and pop off a stack frame and assign the replacement to
354
+ // the attr being replaced on the previous stack frame.
355
+ SmallVector<ReplacementState> workStack;
356
+ workStack.push_back ({nullptr , {baseNode}, {}, 0 , false });
371
357
372
- Attribute result = node;
373
- if (changed)
374
- result = result.replaceImmediateSubElements (attrs, types);
358
+ DenseSet<DistinctAttr> openDecls;
359
+ while (workStack.size () > 1 || workStack.back ().attrIndex == 0 ) {
360
+ ReplacementState &state = workStack.back ();
361
+
362
+ // Check for popping condition.
363
+ if (state.attrIndex == state.attrs .size ()) {
364
+ Attribute result = state.node ;
365
+ if (state.changed )
366
+ result = result.replaceImmediateSubElements (state.attrs , state.types );
367
+
368
+ // Reset context.
369
+ if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(state.node ))
370
+ if (DistinctAttr recId = recType.getRecId ())
371
+ openDecls.erase (recId);
372
+
373
+ workStack.pop_back ();
374
+ ReplacementState &prevState = workStack.back ();
375
+ prevState.replaceCurrAttr (result);
376
+ ++prevState.attrIndex ;
377
+ continue ;
378
+ }
375
379
376
- // Reset context.
377
- if (recId)
378
- openDecls.erase (recId);
380
+ Attribute node = state.attrs [state.attrIndex ];
381
+ if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(node)) {
382
+ if (DistinctAttr recId = recType.getRecId ()) {
383
+ if (recType.isRecSelf ()) {
384
+ // Replace selfRef based on the provided mapping and re-walk from the
385
+ // replacement node (do not increment attrIndex).
386
+ if (DINodeAttr replacement = mapping.lookup (recType)) {
387
+ state.replaceCurrAttr (replacement);
388
+ continue ;
389
+ }
390
+
391
+ // Otherwise, nothing to do. Advance to next attr.
392
+ ++state.attrIndex ;
393
+ continue ;
394
+ }
395
+
396
+ // Configure context.
397
+ auto [_, inserted] = openDecls.insert (recId);
398
+ if (!inserted) {
399
+ // This is a nested decl. Replace with recSelf. Nothing more to do.
400
+ state.replaceCurrAttr (recType.getRecSelf (recId));
401
+ ++state.attrIndex ;
402
+ continue ;
403
+ }
404
+ }
405
+ }
379
406
380
- return result;
381
- }
407
+ // Recurse into this node.
408
+ workStack.push_back ({node, {}, {}, 0 , false });
409
+ ReplacementState &newState = workStack.back ();
410
+ node.walkImmediateSubElements (
411
+ [&newState](Attribute attr) { newState.attrs .push_back (attr); },
412
+ [&newState](Type type) { newState.types .push_back (type); });
413
+ };
382
414
383
- static Attribute replaceAndPruneRecursiveTypes (
384
- DINodeAttr node,
385
- const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping) {
386
- DenseSet<DistinctAttr> openDecls;
387
- return replaceAndPruneRecursiveTypesImpl (node, mapping, openDecls);
415
+ return workStack.back ().attrs .front ();
388
416
}
389
417
390
418
DINodeAttr DebugImporter::RecursionPruner::pruneOrPushTranslationStack (
0 commit comments