@@ -287,6 +287,315 @@ bool llvm::StripDebugInfo(Module &M) {
287
287
return Changed;
288
288
}
289
289
290
+ namespace {
291
+
292
+ // / Helper class to downgrade -g metadata to -gline-tables-only metadata.
293
+ class DebugTypeInfoRemoval {
294
+ DenseMap<Metadata *, Metadata *> Replacements;
295
+
296
+ public:
297
+ // / The (void)() type.
298
+ MDNode *EmptySubroutineType;
299
+
300
+ private:
301
+ // / Remember what linkage name we originally had before stripping. If we end
302
+ // / up making two subprograms identical who originally had different linkage
303
+ // / names, then we need to make one of them distinct, to avoid them getting
304
+ // / uniqued. Maps the new node to the old linkage name.
305
+ DenseMap<DISubprogram *, StringRef> NewToLinkageName;
306
+
307
+ // TODO: Remember the distinct subprogram we created for a given linkage name,
308
+ // so that we can continue to unique whenever possible. Map <newly created
309
+ // node, old linkage name> to the first (possibly distinct) mdsubprogram
310
+ // created for that combination. This is not strictly needed for correctness,
311
+ // but can cut down on the number of MDNodes and let us diff cleanly with the
312
+ // output of -gline-tables-only.
313
+
314
+ public:
315
+ DebugTypeInfoRemoval (LLVMContext &C)
316
+ : EmptySubroutineType(DISubroutineType::get(C, DINode::FlagZero, 0 ,
317
+ MDNode::get (C, {}))) {}
318
+
319
+ Metadata *map (Metadata *M) {
320
+ if (!M)
321
+ return nullptr ;
322
+ if (Replacements.count (M))
323
+ return Replacements.lookup (M);
324
+
325
+ return M;
326
+ }
327
+ MDNode *mapNode (Metadata *N) { return dyn_cast_or_null<MDNode>(map (N)); }
328
+
329
+ // / Recursively remap N and all its referenced children. Does a DF post-order
330
+ // / traversal, so as to remap bottoms up.
331
+ void traverseAndRemap (MDNode *N) { traverse (N); }
332
+
333
+ private:
334
+ // Create a new DISubprogram, to replace the one given.
335
+ DISubprogram *getReplacementSubprogram (DISubprogram *MDS) {
336
+ auto *FileAndScope = cast_or_null<DIFile>(map (MDS->getFile ()));
337
+ StringRef LinkageName = MDS->getName ().empty () ? MDS->getLinkageName () : " " ;
338
+ DISubprogram *Declaration = nullptr ;
339
+ auto *Type = cast_or_null<DISubroutineType>(map (MDS->getType ()));
340
+ DITypeRef ContainingType (map (MDS->getContainingType ()));
341
+ auto *Unit = cast_or_null<DICompileUnit>(map (MDS->getUnit ()));
342
+ auto Variables = nullptr ;
343
+ auto TemplateParams = nullptr ;
344
+
345
+ // Make a distinct DISubprogram, for situations that warrent it.
346
+ auto distinctMDSubprogram = [&]() {
347
+ return DISubprogram::getDistinct (
348
+ MDS->getContext (), FileAndScope, MDS->getName (), LinkageName,
349
+ FileAndScope, MDS->getLine (), Type, MDS->isLocalToUnit (),
350
+ MDS->isDefinition (), MDS->getScopeLine (), ContainingType,
351
+ MDS->getVirtuality (), MDS->getVirtualIndex (),
352
+ MDS->getThisAdjustment (), MDS->getFlags (), MDS->isOptimized (), Unit,
353
+ TemplateParams, Declaration, Variables);
354
+ };
355
+
356
+ if (MDS->isDistinct ())
357
+ return distinctMDSubprogram ();
358
+
359
+ auto *NewMDS = DISubprogram::get (
360
+ MDS->getContext (), FileAndScope, MDS->getName (), LinkageName,
361
+ FileAndScope, MDS->getLine (), Type, MDS->isLocalToUnit (),
362
+ MDS->isDefinition (), MDS->getScopeLine (), ContainingType,
363
+ MDS->getVirtuality (), MDS->getVirtualIndex (), MDS->getThisAdjustment (),
364
+ MDS->getFlags (), MDS->isOptimized (), Unit, TemplateParams, Declaration,
365
+ Variables);
366
+
367
+ StringRef OldLinkageName = MDS->getLinkageName ();
368
+
369
+ // See if we need to make a distinct one.
370
+ auto OrigLinkage = NewToLinkageName.find (NewMDS);
371
+ if (OrigLinkage != NewToLinkageName.end ()) {
372
+ if (OrigLinkage->second == OldLinkageName)
373
+ // We're good.
374
+ return NewMDS;
375
+
376
+ // Otherwise, need to make a distinct one.
377
+ // TODO: Query the map to see if we already have one.
378
+ return distinctMDSubprogram ();
379
+ }
380
+
381
+ NewToLinkageName.insert ({NewMDS, MDS->getLinkageName ()});
382
+ return NewMDS;
383
+ }
384
+
385
+ // / Create a new compile unit, to replace the one given
386
+ DICompileUnit *getReplacementCU (DICompileUnit *CU) {
387
+ // Drop skeleton CUs.
388
+ if (CU->getDWOId ())
389
+ return nullptr ;
390
+
391
+ auto *File = cast_or_null<DIFile>(map (CU->getFile ()));
392
+ MDTuple *EnumTypes = nullptr ;
393
+ MDTuple *RetainedTypes = nullptr ;
394
+ MDTuple *GlobalVariables = nullptr ;
395
+ MDTuple *ImportedEntities = nullptr ;
396
+ return DICompileUnit::getDistinct (
397
+ CU->getContext (), CU->getSourceLanguage (), File, CU->getProducer (),
398
+ CU->isOptimized (), CU->getFlags (), CU->getRuntimeVersion (),
399
+ CU->getSplitDebugFilename (), DICompileUnit::LineTablesOnly, EnumTypes,
400
+ RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros (),
401
+ CU->getDWOId (), CU->getSplitDebugInlining ());
402
+ }
403
+
404
+ DILocation *getReplacementMDLocation (DILocation *MLD) {
405
+ auto *Scope = map (MLD->getScope ());
406
+ auto *InlinedAt = map (MLD->getInlinedAt ());
407
+ if (MLD->isDistinct ())
408
+ return DILocation::getDistinct (MLD->getContext (), MLD->getLine (),
409
+ MLD->getColumn (), Scope, InlinedAt);
410
+ return DILocation::get (MLD->getContext (), MLD->getLine (), MLD->getColumn (),
411
+ Scope, InlinedAt);
412
+ }
413
+
414
+ // / Create a new generic MDNode, to replace the one given
415
+ MDNode *getReplacementMDNode (MDNode *N) {
416
+ SmallVector<Metadata *, 8 > Ops;
417
+ Ops.reserve (N->getNumOperands ());
418
+ for (auto &I : N->operands ())
419
+ if (I)
420
+ Ops.push_back (map (I));
421
+ auto *Ret = MDNode::get (N->getContext (), Ops);
422
+ return Ret;
423
+ }
424
+
425
+ // / Attempt to re-map N to a newly created node.
426
+ void remap (MDNode *N) {
427
+ if (Replacements.count (N))
428
+ return ;
429
+
430
+ auto doRemap = [&](MDNode *N) -> MDNode * {
431
+ if (!N)
432
+ return nullptr ;
433
+ if (auto *MDSub = dyn_cast<DISubprogram>(N)) {
434
+ remap (MDSub->getUnit ());
435
+ return getReplacementSubprogram (MDSub);
436
+ }
437
+ if (isa<DISubroutineType>(N))
438
+ return EmptySubroutineType;
439
+ if (auto *CU = dyn_cast<DICompileUnit>(N))
440
+ return getReplacementCU (CU);
441
+ if (isa<DIFile>(N))
442
+ return N;
443
+ if (auto *MDLB = dyn_cast<DILexicalBlockBase>(N))
444
+ // Remap to our referenced scope (recursively).
445
+ return mapNode (MDLB->getScope ());
446
+ if (auto *MLD = dyn_cast<DILocation>(N))
447
+ return getReplacementMDLocation (MLD);
448
+
449
+ // Otherwise, if we see these, just drop them now. Not strictly necessary,
450
+ // but this speeds things up a little.
451
+ if (isa<DINode>(N))
452
+ return nullptr ;
453
+
454
+ return getReplacementMDNode (N);
455
+ };
456
+ Replacements[N] = doRemap (N);
457
+ }
458
+
459
+ // / Do the remapping traversal.
460
+ void traverse (MDNode *);
461
+ };
462
+
463
+ } // Anonymous namespace.
464
+
465
+ void DebugTypeInfoRemoval::traverse (MDNode *N) {
466
+ if (!N || Replacements.count (N))
467
+ return ;
468
+
469
+ // To avoid cycles, as well as for efficiency sake, we will sometimes prune
470
+ // parts of the graph.
471
+ auto prune = [](MDNode *Parent, MDNode *Child) {
472
+ if (auto *MDS = dyn_cast<DISubprogram>(Parent))
473
+ return Child == MDS->getVariables ().get ();
474
+ return false ;
475
+ };
476
+
477
+ SmallVector<MDNode *, 16 > ToVisit;
478
+ DenseSet<MDNode *> Opened;
479
+
480
+ // Visit each node starting at N in post order, and map them.
481
+ ToVisit.push_back (N);
482
+ while (!ToVisit.empty ()) {
483
+ auto *N = ToVisit.back ();
484
+ auto Result = Opened.insert (N);
485
+ if (!Result.second ) {
486
+ // Close it.
487
+ remap (N);
488
+ ToVisit.pop_back ();
489
+ continue ;
490
+ }
491
+ for (auto &I : N->operands ())
492
+ if (auto *MDN = dyn_cast_or_null<MDNode>(I))
493
+ if (!Opened.count (MDN) && !Replacements.count (MDN) && !prune (N, MDN) &&
494
+ !isa<DICompileUnit>(MDN))
495
+ ToVisit.push_back (MDN);
496
+ }
497
+ }
498
+
499
+ bool llvm::stripNonLineTableDebugInfo (Module &M) {
500
+ bool Changed = false ;
501
+
502
+ // First off, delete the debug intrinsics.
503
+ if (Function *Declare = M.getFunction (" llvm.dbg.declare" )) {
504
+ while (!Declare->use_empty ()) {
505
+ auto *DDI = cast<DbgDeclareInst>(Declare->user_back ());
506
+ DDI->eraseFromParent ();
507
+ }
508
+ Declare->eraseFromParent ();
509
+ Changed = true ;
510
+ }
511
+ if (Function *DbgVal = M.getFunction (" llvm.dbg.value" )) {
512
+ while (!DbgVal->use_empty ()) {
513
+ auto *DVI = cast<DbgValueInst>(DbgVal->user_back ());
514
+ DVI->eraseFromParent ();
515
+ }
516
+ DbgVal->eraseFromParent ();
517
+ Changed = true ;
518
+ }
519
+
520
+ // Delete non-CU debug info named metadata nodes.
521
+ for (auto NMI = M.named_metadata_begin (), NME = M.named_metadata_end ();
522
+ NMI != NME;) {
523
+ NamedMDNode *NMD = &*NMI;
524
+ ++NMI;
525
+ // Specifically keep dbg.cu around.
526
+ if (NMD->getName () == " llvm.dbg.cu" )
527
+ continue ;
528
+ }
529
+
530
+ // Drop all dbg attachments from global variables.
531
+ for (auto &GV : M.globals ())
532
+ GV.getContext ().pImpl ->GlobalObjectMetadata [&GV].erase (LLVMContext::MD_dbg);
533
+
534
+ DebugTypeInfoRemoval Mapper (M.getContext ());
535
+
536
+ // Rewrite the DebugLocs to be equivalent to what
537
+ // -gline-tables-only would have created.
538
+ for (auto &F : M) {
539
+ auto *SP = F.getSubprogram ();
540
+ if (SP) {
541
+ Mapper.traverseAndRemap (SP);
542
+ auto *NewSP = cast<DISubprogram>(Mapper.mapNode (SP));
543
+ Changed |= SP != NewSP;
544
+ F.setSubprogram (NewSP);
545
+ }
546
+ for (auto &BB : F) {
547
+ for (auto &I : BB) {
548
+ if (I.getDebugLoc () == DebugLoc ())
549
+ continue ;
550
+
551
+ // Make a replacement.
552
+ auto &DL = I.getDebugLoc ();
553
+ auto *Scope = DL.getScope ();
554
+ auto *InlinedAt = DL.getInlinedAt ();
555
+
556
+ // Remap scope.
557
+ if (Scope) {
558
+ Mapper.traverseAndRemap (Scope);
559
+ auto *NewScope = Mapper.mapNode (Scope);
560
+ Changed |= Scope != NewScope;
561
+ Scope = NewScope;
562
+ }
563
+
564
+ // Remap inlinedAt.
565
+ if (InlinedAt) {
566
+ Mapper.traverseAndRemap (InlinedAt);
567
+ auto *NewIA = Mapper.mapNode (InlinedAt);
568
+ Changed |= InlinedAt != NewIA;
569
+ InlinedAt = cast_or_null<DILocation>(NewIA);
570
+ }
571
+
572
+ I.setDebugLoc (
573
+ DebugLoc::get (DL.getLine (), DL.getCol (), Scope, InlinedAt));
574
+ }
575
+ }
576
+ }
577
+
578
+ // Create a new llvm.dbg.cu, which is equivalent to the one
579
+ // -gline-tables-only would have created.
580
+ for (auto &NMD : M.getNamedMDList ()) {
581
+ SmallVector<MDNode *, 8 > Ops;
582
+ for (MDNode *Op : NMD.operands ()) {
583
+ Mapper.traverseAndRemap (Op);
584
+ auto *NewOp = Mapper.mapNode (Op);
585
+ Changed |= NewOp != Op;
586
+ Ops.push_back (NewOp);
587
+ }
588
+
589
+ if (Changed) {
590
+ NMD.dropAllReferences ();
591
+ for (auto *Op : Ops)
592
+ if (Op)
593
+ NMD.addOperand (Op);
594
+ }
595
+ }
596
+ return Changed;
597
+ }
598
+
290
599
unsigned llvm::getDebugMetadataVersionFromModule (const Module &M) {
291
600
if (auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
292
601
M.getModuleFlag (" Debug Info Version" )))
0 commit comments