@@ -319,139 +319,8 @@ getRecSelfConstructor(llvm::DINode *node) {
319
319
.Default (CtorType ());
320
320
}
321
321
322
- // / An iterative attribute replacer that also handles pruning recursive types.
323
- // / - Recurses down the attribute tree while replacing attributes based on the
324
- // / provided replacement map.
325
- // / - Keeps track of the currently open recursive declarations, and upon
326
- // / encountering a duplicate declaration, replace with a self-reference.
327
- static Attribute replaceAndPruneRecursiveTypes (
328
- Attribute baseNode,
329
- const DenseMap<DIRecursiveTypeAttrInterface, DINodeAttr> &mapping) {
330
-
331
- struct ReplacementState {
332
- // The attribute being replaced.
333
- Attribute node;
334
- // The nested elements of `node`.
335
- SmallVector<Attribute> attrs;
336
- SmallVector<Type> types;
337
- // The current attr being walked on (index into `attrs`).
338
- size_t attrIndex;
339
- // Whether or not any attr was replaced.
340
- bool changed;
341
-
342
- void replaceCurrAttr (Attribute attr) {
343
- Attribute &target = attrs[attrIndex];
344
- if (attr != target) {
345
- changed = true ;
346
- target = attr;
347
- }
348
- }
349
- };
350
-
351
- // Every iteration, perform replacement on the attribute at `attrIndex` at the
352
- // top of `workStack`.
353
- // If `attrIndex` reaches past the size of `attrs`, replace `node` with
354
- // `attrs` & `types`, and pop off a stack frame and assign the replacement to
355
- // the attr being replaced on the previous stack frame.
356
- SmallVector<ReplacementState> workStack;
357
- workStack.push_back ({nullptr , {baseNode}, {}, 0 , false });
358
-
359
- // Replacement cache that remembers the context in which the cache is valid.
360
- // All unboundRecIds must be in openDecls at time of lookup.
361
- struct CacheWithContext {
362
- DenseSet<DistinctAttr> unboundRecIds;
363
- Attribute entry;
364
- };
365
- DenseMap<Attribute, CacheWithContext> replacementCache;
366
-
367
- DenseSet<DistinctAttr> openDecls;
368
- while (workStack.size () > 1 || workStack.back ().attrIndex == 0 ) {
369
- ReplacementState &state = workStack.back ();
370
-
371
- // Check for popping condition.
372
- if (state.attrIndex == state.attrs .size ()) {
373
- Attribute result = state.node ;
374
- if (state.changed )
375
- result = result.replaceImmediateSubElements (state.attrs , state.types );
376
-
377
- // Reset context.
378
- if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(state.node ))
379
- if (DistinctAttr recId = recType.getRecId ())
380
- openDecls.erase (recId);
381
-
382
- replacementCache[state.node ] = CacheWithContext{openDecls, result};
383
-
384
- workStack.pop_back ();
385
- ReplacementState &prevState = workStack.back ();
386
- prevState.replaceCurrAttr (result);
387
- ++prevState.attrIndex ;
388
- continue ;
389
- }
390
-
391
- Attribute node = state.attrs [state.attrIndex ];
392
-
393
- // Lookup in cache first.
394
- if (auto it = replacementCache.find (node); it != replacementCache.end ()) {
395
- // If all the requried recIds are open decls, use cache.
396
- if (llvm::set_is_subset (it->second .unboundRecIds , openDecls)) {
397
- state.replaceCurrAttr (it->second .entry );
398
- ++state.attrIndex ;
399
- continue ;
400
- }
401
-
402
- // Otherwise, the cache entry is stale and can be removed now.
403
- replacementCache.erase (it);
404
- }
405
-
406
- if (auto recType = dyn_cast<DIRecursiveTypeAttrInterface>(node)) {
407
- if (DistinctAttr recId = recType.getRecId ()) {
408
- if (recType.isRecSelf ()) {
409
- // Replace selfRef based on the provided mapping and re-walk from the
410
- // replacement node (do not increment attrIndex).
411
- if (DINodeAttr replacement = mapping.lookup (recType)) {
412
- state.replaceCurrAttr (replacement);
413
- continue ;
414
- }
415
-
416
- // Otherwise, nothing to do. Advance to next attr.
417
- ++state.attrIndex ;
418
- continue ;
419
- }
420
-
421
- // Configure context.
422
- auto [_, inserted] = openDecls.insert (recId);
423
- if (!inserted) {
424
- // This is a nested decl. Replace with recSelf. Nothing more to do.
425
- state.replaceCurrAttr (recType.getRecSelf (recId));
426
- ++state.attrIndex ;
427
- continue ;
428
- }
429
- }
430
- }
431
-
432
- // Recurse into this node.
433
- workStack.push_back ({node, {}, {}, 0 , false });
434
- ReplacementState &newState = workStack.back ();
435
- node.walkImmediateSubElements (
436
- [&newState](Attribute attr) { newState.attrs .push_back (attr); },
437
- [&newState](Type type) { newState.types .push_back (type); });
438
- };
439
-
440
- return workStack.back ().attrs .front ();
441
- }
442
-
443
322
DINodeAttr DebugImporter::RecursionPruner::pruneOrPushTranslationStack (
444
323
llvm::DINode *node) {
445
- // Lookup the cache first.
446
- auto [result, unboundSelfRefs] = lookup (node);
447
- if (result) {
448
- // Need to inject unbound self-refs into the previous layer.
449
- if (!unboundSelfRefs.empty ())
450
- translationStack.back ().second .unboundSelfRefs .insert (
451
- unboundSelfRefs.begin (), unboundSelfRefs.end ());
452
- return result;
453
- }
454
-
455
324
// If the node type is capable of being recursive, check if it's seen
456
325
// before.
457
326
auto recSelfCtor = getRecSelfConstructor (node);
@@ -465,7 +334,11 @@ DINodeAttr DebugImporter::RecursionPruner::pruneOrPushTranslationStack(
465
334
// a different self-reference. Use that if possible.
466
335
DIRecursiveTypeAttrInterface recSelf = iter->second .recSelf ;
467
336
if (!recSelf) {
468
- DistinctAttr recId = DistinctAttr::create (UnitAttr::get (context));
337
+ DistinctAttr recId = nodeToRecId.lookup (node);
338
+ if (!recId) {
339
+ recId = DistinctAttr::create (UnitAttr::get (context));
340
+ nodeToRecId[node] = recId;
341
+ }
469
342
recSelf = recSelfCtor (recId);
470
343
iter->second .recSelf = recSelf;
471
344
}
@@ -474,7 +347,8 @@ DINodeAttr DebugImporter::RecursionPruner::pruneOrPushTranslationStack(
474
347
return cast<DINodeAttr>(recSelf);
475
348
}
476
349
}
477
- return nullptr ;
350
+
351
+ return lookup (node);
478
352
}
479
353
480
354
std::pair<DINodeAttr, bool >
@@ -493,39 +367,18 @@ DebugImporter::RecursionPruner::finalizeTranslation(llvm::DINode *node,
493
367
if (DIRecursiveTypeAttrInterface recSelf = state.recSelf ) {
494
368
auto recType = cast<DIRecursiveTypeAttrInterface>(result);
495
369
result = cast<DINodeAttr>(recType.withRecId (recSelf.getRecId ()));
496
-
497
370
// Remove this recSelf from the set of unbound selfRefs.
498
371
state.unboundSelfRefs .erase (recSelf);
499
-
500
- // Insert the newly resolved recursive type into the cache entries that
501
- // rely on it.
502
- // Only need to look at the caches at this level.
503
- uint64_t numRemaining = state.cacheSize ;
504
- for (CachedTranslation &cacheEntry :
505
- llvm::make_second_range (llvm::reverse (cache))) {
506
- if (numRemaining == 0 )
507
- break ;
508
- --numRemaining;
509
-
510
- if (auto refIter = cacheEntry.pendingReplacements .find (recSelf);
511
- refIter != cacheEntry.pendingReplacements .end ())
512
- refIter->second = result;
513
- }
514
372
}
515
373
516
- // Insert the current result into the cache.
517
- state.cacheSize ++;
518
- auto [iter, inserted] = cache.try_emplace (node);
519
- assert (inserted && " invalid state: caching the same DINode twice" );
520
- iter->second .attr = result;
521
-
522
- // If this node had any unbound self-refs free when it is registered into
523
- // the cache, set up replacement placeholders: This result will need these
524
- // unbound self-refs to be replaced before being used.
525
- for (DIRecursiveTypeAttrInterface selfRef : state.unboundSelfRefs )
526
- iter->second .pendingReplacements .try_emplace (selfRef, nullptr );
527
-
528
- return {result, state.unboundSelfRefs .empty ()};
374
+ // Insert the result into our internal cache if it's not self-contained.
375
+ if (!state.unboundSelfRefs .empty ()) {
376
+ auto [_, inserted] = dependentCache.try_emplace (
377
+ node, DependentTranslation{result, state.unboundSelfRefs });
378
+ assert (inserted && " invalid state: caching the same DINode twice" );
379
+ return {result, false };
380
+ }
381
+ return {result, true };
529
382
}
530
383
531
384
void DebugImporter::RecursionPruner::popTranslationStack (llvm::DINode *node) {
@@ -540,56 +393,30 @@ void DebugImporter::RecursionPruner::popTranslationStack(llvm::DINode *node) {
540
393
if (translationStack.size () == 1 ) {
541
394
assert (currLayerState.unboundSelfRefs .empty () &&
542
395
" internal error: unbound recursive self reference at top level." );
543
- assert (currLayerState.cacheSize == cache.size () &&
544
- " internal error: inconsistent cache size" );
545
396
translationStack.pop_back ();
546
- cache.clear ();
547
397
return ;
548
398
}
549
399
550
400
// Copy unboundSelfRefs down to the previous level.
551
401
TranslationState &nextLayerState = (++translationStack.rbegin ())->second ;
552
402
nextLayerState.unboundSelfRefs .insert (currLayerState.unboundSelfRefs .begin (),
553
403
currLayerState.unboundSelfRefs .end ());
554
-
555
- // The current layer cache is now considered part of the lower layer cache.
556
- nextLayerState.cacheSize += currLayerState.cacheSize ;
557
-
558
- // Finally pop off this layer when all bookkeeping is done.
559
404
translationStack.pop_back ();
560
405
}
561
406
562
- std::pair<DINodeAttr, DenseSet<DIRecursiveTypeAttrInterface>>
563
- DebugImporter::RecursionPruner::lookup (llvm::DINode *node) {
564
- auto cacheIter = cache.find (node);
565
- if (cacheIter == cache.end ())
407
+ DINodeAttr DebugImporter::RecursionPruner::lookup (llvm::DINode *node) {
408
+ auto cacheIter = dependentCache.find (node);
409
+ if (cacheIter == dependentCache.end ())
566
410
return {};
567
411
568
- CachedTranslation &entry = cacheIter->second ;
569
-
570
- if (entry.pendingReplacements .empty ())
571
- return std::make_pair (entry.attr , DenseSet<DIRecursiveTypeAttrInterface>{});
572
-
573
- Attribute replacedAttr =
574
- replaceAndPruneRecursiveTypes (entry.attr , entry.pendingReplacements );
575
- DINodeAttr result = cast<DINodeAttr>(replacedAttr);
576
-
577
- // Update cache entry to save replaced version and remove already-applied
578
- // replacements.
579
- entry.attr = result;
580
- DenseSet<DIRecursiveTypeAttrInterface> unboundRefs;
581
- DenseSet<DIRecursiveTypeAttrInterface> boundRefs;
582
- for (auto [refSelf, replacement] : entry.pendingReplacements ) {
583
- if (replacement)
584
- boundRefs.insert (refSelf);
585
- else
586
- unboundRefs.insert (refSelf);
587
- }
588
-
589
- for (DIRecursiveTypeAttrInterface ref : boundRefs)
590
- entry.pendingReplacements .erase (ref);
412
+ DependentTranslation &entry = cacheIter->second ;
413
+ if (llvm::set_is_subset (entry.unboundSelfRefs ,
414
+ translationStack.back ().second .unboundSelfRefs ))
415
+ return entry.attr ;
591
416
592
- return std::make_pair (result, unboundRefs);
417
+ // Stale cache entry.
418
+ dependentCache.erase (cacheIter);
419
+ return {};
593
420
}
594
421
595
422
// ===----------------------------------------------------------------------===//
0 commit comments