llvm.org GIT mirror llvm / 5bd98bf
Add -strip-nonlinetable-debuginfo capability This adds a new function to DebugInfo.cpp that takes an llvm::Module as input and removes all debug info metadata that is not directly needed for line tables, thus effectively stripping all type and variable information from the module. The primary motivation for this feature was the bitcode work flow (cf. http://lists.llvm.org/pipermail/llvm-dev/2016-June/100643.html for more background). This is not wired up yet, but will be in subsequent patches. For testing, the new functionality is exposed to opt with a -strip-nonlinetable-debuginfo option. The secondary use-case (and one that works right now!) is as a reduction pass in bugpoint. I added two new bugpoint options (-disable-strip-debuginfo and -disable-strip-debug-types) to control the new features. By default it will first attempt to remove all debug information, then only the type info, and then proceed to hack at any remaining MDNodes. Thanks to Adrian Prantl for stewarding this patch! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285094 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Ilseman 2 years ago
16 changed file(s) with 576 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
4242 /// Return true if module is modified.
4343 bool StripDebugInfo(Module &M);
4444 bool stripDebugInfo(Function &F);
45
46 /// Downgrade the debug info in a module to contain only line table information.
47 ///
48 /// In order to convert debug info to what -gline-tables-only would have
49 /// created, this does the following:
50 /// 1) Delete all debug intrinsics.
51 /// 2) Delete all non-CU named metadata debug info nodes.
52 /// 3) Create new DebugLocs for each instruction.
53 /// 4) Create a new CU debug info, and similarly for every metadata node
54 /// that's reachable from the CU debug info.
55 /// All debug type metadata nodes are unreachable and garbage collected.
56 bool stripNonLineTableDebugInfo(Module &M);
4557
4658 /// \brief Return Debug Info Metadata Version by checking module flags.
4759 unsigned getDebugMetadataVersionFromModule(const Module &M);
12981298 /// \brief Drop all references and remove the node from parent module.
12991299 void eraseFromParent();
13001300
1301 /// \brief Remove all uses and clear node vector.
1302 void dropAllReferences();
1301 /// Remove all uses and clear node vector.
1302 void dropAllReferences() { clearOperands(); }
1303 /// Drop all references to this node's operands.
1304 void clearOperands();
13031305
13041306 ~NamedMDNode();
13051307
329329 void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&);
330330 void initializeStripDebugDeclarePass(PassRegistry&);
331331 void initializeStripNonDebugSymbolsPass(PassRegistry&);
332 void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
332333 void initializeStripSymbolsPass(PassRegistry&);
333334 void initializeStructurizeCFGPass(PassRegistry&);
334335 void initializeTailCallElimPass(PassRegistry&);
4242 //
4343 ModulePass *createStripNonDebugSymbolsPass();
4444
45 /// This function returns a new pass that downgrades the debug info in the
46 /// module to line tables only.
47 ModulePass *createStripNonLineTableDebugInfoPass();
48
4549 //===----------------------------------------------------------------------===//
4650 //
4751 // These pass removes llvm.dbg.declare intrinsics.
299299 return Changed;
300300 }
301301
302 namespace {
303
304 /// Helper class to downgrade -g metadata to -gline-tables-only metadata.
305 class DebugTypeInfoRemoval {
306 DenseMap Replacements;
307
308 public:
309 /// The (void)() type.
310 MDNode *EmptySubroutineType;
311
312 private:
313 /// Remember what linkage name we originally had before stripping. If we end
314 /// up making two subprograms identical who originally had different linkage
315 /// names, then we need to make one of them distinct, to avoid them getting
316 /// uniqued. Maps the new node to the old linkage name.
317 DenseMap NewToLinkageName;
318
319 // TODO: Remember the distinct subprogram we created for a given linkage name,
320 // so that we can continue to unique whenever possible. Map
321 // node, old linkage name> to the first (possibly distinct) mdsubprogram
322 // created for that combination. This is not strictly needed for correctness,
323 // but can cut down on the number of MDNodes and let us diff cleanly with the
324 // output of -gline-tables-only.
325
326 public:
327 DebugTypeInfoRemoval(LLVMContext &C)
328 : EmptySubroutineType(DISubroutineType::get(C, DINode::FlagZero, 0,
329 MDNode::get(C, {}))) {}
330
331 Metadata *map(Metadata *M) {
332 if (!M)
333 return nullptr;
334 auto Replacement = Replacements.find(M);
335 if (Replacement != Replacements.end())
336 return Replacement->second;
337
338 return M;
339 }
340 MDNode *mapNode(Metadata *N) { return dyn_cast_or_null(map(N)); }
341
342 /// Recursively remap N and all its referenced children. Does a DF post-order
343 /// traversal, so as to remap bottoms up.
344 void traverseAndRemap(MDNode *N) { traverse(N); }
345
346 private:
347 // Create a new DISubprogram, to replace the one given.
348 DISubprogram *getReplacementSubprogram(DISubprogram *MDS) {
349 auto *FileAndScope = cast_or_null(map(MDS->getFile()));
350 StringRef LinkageName = MDS->getName().empty() ? MDS->getLinkageName() : "";
351 DISubprogram *Declaration = nullptr;
352 auto *Type = cast_or_null(map(MDS->getType()));
353 DITypeRef ContainingType(map(MDS->getContainingType()));
354 auto *Unit = cast_or_null(map(MDS->getUnit()));
355 auto Variables = nullptr;
356 auto TemplateParams = nullptr;
357
358 // Make a distinct DISubprogram, for situations that warrent it.
359 auto distinctMDSubprogram = [&]() {
360 return DISubprogram::getDistinct(
361 MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
362 FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
363 MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
364 MDS->getVirtuality(), MDS->getVirtualIndex(),
365 MDS->getThisAdjustment(), MDS->getFlags(), MDS->isOptimized(), Unit,
366 TemplateParams, Declaration, Variables);
367 };
368
369 if (MDS->isDistinct())
370 return distinctMDSubprogram();
371
372 auto *NewMDS = DISubprogram::get(
373 MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
374 FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
375 MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
376 MDS->getVirtuality(), MDS->getVirtualIndex(), MDS->getThisAdjustment(),
377 MDS->getFlags(), MDS->isOptimized(), Unit, TemplateParams, Declaration,
378 Variables);
379
380 StringRef OldLinkageName = MDS->getLinkageName();
381
382 // See if we need to make a distinct one.
383 auto OrigLinkage = NewToLinkageName.find(NewMDS);
384 if (OrigLinkage != NewToLinkageName.end()) {
385 if (OrigLinkage->second == OldLinkageName)
386 // We're good.
387 return NewMDS;
388
389 // Otherwise, need to make a distinct one.
390 // TODO: Query the map to see if we already have one.
391 return distinctMDSubprogram();
392 }
393
394 NewToLinkageName.insert({NewMDS, MDS->getLinkageName()});
395 return NewMDS;
396 }
397
398 /// Create a new compile unit, to replace the one given
399 DICompileUnit *getReplacementCU(DICompileUnit *CU) {
400 // Drop skeleton CUs.
401 if (CU->getDWOId())
402 return nullptr;
403
404 auto *File = cast_or_null(map(CU->getFile()));
405 MDTuple *EnumTypes = nullptr;
406 MDTuple *RetainedTypes = nullptr;
407 MDTuple *GlobalVariables = nullptr;
408 MDTuple *ImportedEntities = nullptr;
409 return DICompileUnit::getDistinct(
410 CU->getContext(), CU->getSourceLanguage(), File, CU->getProducer(),
411 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
412 CU->getSplitDebugFilename(), DICompileUnit::LineTablesOnly, EnumTypes,
413 RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros(),
414 CU->getDWOId(), CU->getSplitDebugInlining());
415 }
416
417 DILocation *getReplacementMDLocation(DILocation *MLD) {
418 auto *Scope = map(MLD->getScope());
419 auto *InlinedAt = map(MLD->getInlinedAt());
420 if (MLD->isDistinct())
421 return DILocation::getDistinct(MLD->getContext(), MLD->getLine(),
422 MLD->getColumn(), Scope, InlinedAt);
423 return DILocation::get(MLD->getContext(), MLD->getLine(), MLD->getColumn(),
424 Scope, InlinedAt);
425 }
426
427 /// Create a new generic MDNode, to replace the one given
428 MDNode *getReplacementMDNode(MDNode *N) {
429 SmallVector Ops;
430 Ops.reserve(N->getNumOperands());
431 for (auto &I : N->operands())
432 if (I)
433 Ops.push_back(map(I));
434 auto *Ret = MDNode::get(N->getContext(), Ops);
435 return Ret;
436 }
437
438 /// Attempt to re-map N to a newly created node.
439 void remap(MDNode *N) {
440 if (Replacements.count(N))
441 return;
442
443 auto doRemap = [&](MDNode *N) -> MDNode * {
444 if (!N)
445 return nullptr;
446 if (auto *MDSub = dyn_cast(N)) {
447 remap(MDSub->getUnit());
448 return getReplacementSubprogram(MDSub);
449 }
450 if (isa(N))
451 return EmptySubroutineType;
452 if (auto *CU = dyn_cast(N))
453 return getReplacementCU(CU);
454 if (isa(N))
455 return N;
456 if (auto *MDLB = dyn_cast(N))
457 // Remap to our referenced scope (recursively).
458 return mapNode(MDLB->getScope());
459 if (auto *MLD = dyn_cast(N))
460 return getReplacementMDLocation(MLD);
461
462 // Otherwise, if we see these, just drop them now. Not strictly necessary,
463 // but this speeds things up a little.
464 if (isa(N))
465 return nullptr;
466
467 return getReplacementMDNode(N);
468 };
469 Replacements[N] = doRemap(N);
470 }
471
472 /// Do the remapping traversal.
473 void traverse(MDNode *);
474 };
475
476 } // Anonymous namespace.
477
478 void DebugTypeInfoRemoval::traverse(MDNode *N) {
479 if (!N || Replacements.count(N))
480 return;
481
482 // To avoid cycles, as well as for efficiency sake, we will sometimes prune
483 // parts of the graph.
484 auto prune = [](MDNode *Parent, MDNode *Child) {
485 if (auto *MDS = dyn_cast(Parent))
486 return Child == MDS->getVariables().get();
487 return false;
488 };
489
490 SmallVector ToVisit;
491 DenseSet Opened;
492
493 // Visit each node starting at N in post order, and map them.
494 ToVisit.push_back(N);
495 while (!ToVisit.empty()) {
496 auto *N = ToVisit.back();
497 if (!Opened.insert(N).second) {
498 // Close it.
499 remap(N);
500 ToVisit.pop_back();
501 continue;
502 }
503 for (auto &I : N->operands())
504 if (auto *MDN = dyn_cast_or_null(I))
505 if (!Opened.count(MDN) && !Replacements.count(MDN) && !prune(N, MDN) &&
506 !isa(MDN))
507 ToVisit.push_back(MDN);
508 }
509 }
510
511 bool llvm::stripNonLineTableDebugInfo(Module &M) {
512 bool Changed = false;
513
514 // First off, delete the debug intrinsics.
515 auto RemoveUses = [&](StringRef Name) {
516 if (auto *DbgVal = M.getFunction(Name)) {
517 while (!DbgVal->use_empty())
518 cast(DbgVal->user_back())->eraseFromParent();
519 DbgVal->eraseFromParent();
520 Changed = true;
521 }
522 };
523 RemoveUses("llvm.dbg.declare");
524 RemoveUses("llvm.dbg.value");
525
526 // Delete non-CU debug info named metadata nodes.
527 for (auto NMI = M.named_metadata_begin(), NME = M.named_metadata_end();
528 NMI != NME;) {
529 NamedMDNode *NMD = &*NMI;
530 ++NMI;
531 // Specifically keep dbg.cu around.
532 if (NMD->getName() == "llvm.dbg.cu")
533 continue;
534 }
535
536 // Drop all dbg attachments from global variables.
537 for (auto &GV : M.globals())
538 GV.eraseMetadata(LLVMContext::MD_dbg);
539
540 DebugTypeInfoRemoval Mapper(M.getContext());
541 auto remap = [&](llvm::MDNode *Node) -> llvm::MDNode * {
542 if (!Node)
543 return nullptr;
544 Mapper.traverseAndRemap(Node);
545 auto *NewNode = Mapper.mapNode(Node);
546 Changed |= Node != NewNode;
547 Node = NewNode;
548 return NewNode;
549 };
550
551 // Rewrite the DebugLocs to be equivalent to what
552 // -gline-tables-only would have created.
553 for (auto &F : M) {
554 if (auto *SP = F.getSubprogram()) {
555 Mapper.traverseAndRemap(SP);
556 auto *NewSP = cast(Mapper.mapNode(SP));
557 Changed |= SP != NewSP;
558 F.setSubprogram(NewSP);
559 }
560 for (auto &BB : F) {
561 for (auto &I : BB) {
562 if (I.getDebugLoc() == DebugLoc())
563 continue;
564
565 // Make a replacement.
566 auto &DL = I.getDebugLoc();
567 auto *Scope = DL.getScope();
568 MDNode *InlinedAt = DL.getInlinedAt();
569 Scope = remap(Scope);
570 InlinedAt = remap(InlinedAt);
571 I.setDebugLoc(
572 DebugLoc::get(DL.getLine(), DL.getCol(), Scope, InlinedAt));
573 }
574 }
575 }
576
577 // Create a new llvm.dbg.cu, which is equivalent to the one
578 // -gline-tables-only would have created.
579 for (auto &NMD : M.getNamedMDList()) {
580 SmallVector Ops;
581 for (MDNode *Op : NMD.operands())
582 Ops.push_back(remap(Op));
583
584 if (!Changed)
585 continue;
586
587 NMD.clearOperands();
588 for (auto *Op : Ops)
589 if (Op)
590 NMD.addOperand(Op);
591 }
592 return Changed;
593 }
594
302595 unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
303596 if (auto *Val = mdconst::dyn_extract_or_null(
304597 M.getModuleFlag("Debug Info Version")))
10531053
10541054 void NamedMDNode::eraseFromParent() { getParent()->eraseNamedMetadata(this); }
10551055
1056 void NamedMDNode::dropAllReferences() { getNMDOps(Operands).clear(); }
1056 void NamedMDNode::clearOperands() { getNMDOps(Operands).clear(); }
10571057
10581058 StringRef NamedMDNode::getName() const { return StringRef(Name); }
10591059
4242 SimplifyInstructions.cpp
4343 SimplifyLibCalls.cpp
4444 SplitModule.cpp
45 StripNonLineTableDebugInfo.cpp
4546 SymbolRewriter.cpp
4647 UnifyFunctionExitNodes.cpp
4748 Utils.cpp
0 //===- StripNonLineTableDebugInfo.cpp -- Strip parts of Debug Info --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Transforms/IPO.h"
10 #include "llvm/IR/DebugInfo.h"
11 #include "llvm/Pass.h"
12 using namespace llvm;
13
14 namespace {
15
16 /// This pass strips all debug info that is not related line tables.
17 /// The result will be the same as if the program where compiled with
18 /// -gline-tables-only.
19 struct StripNonLineTableDebugInfo : public ModulePass {
20 static char ID; // Pass identification, replacement for typeid
21 StripNonLineTableDebugInfo() : ModulePass(ID) {
22 initializeStripNonLineTableDebugInfoPass(*PassRegistry::getPassRegistry());
23 }
24
25 void getAnalysisUsage(AnalysisUsage &AU) const override {
26 AU.setPreservesAll();
27 }
28
29 bool runOnModule(Module &M) override {
30 return llvm::stripNonLineTableDebugInfo(M);
31 }
32 };
33 }
34
35 char StripNonLineTableDebugInfo::ID = 0;
36 INITIALIZE_PASS(StripNonLineTableDebugInfo, "strip-nonlinetable-debuginfo",
37 "Strip all debug info except linetables", false, false)
38
39 ModulePass *llvm::createStripNonLineTableDebugInfoPass() {
40 return new StripNonLineTableDebugInfo();
41 }
3030 initializeLowerSwitchPass(Registry);
3131 initializeNameAnonGlobalLegacyPassPass(Registry);
3232 initializePromoteLegacyPassPass(Registry);
33 initializeStripNonLineTableDebugInfoPass(Registry);
3334 initializeUnifyFunctionExitNodesPass(Registry);
3435 initializeInstSimplifierPass(Registry);
3536 initializeMetaRenamerPass(Registry);
None ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove > /dev/null
0 ; REQUIRES: loadable_module
1 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo -disable-strip-debug-types > /dev/null
12 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
2 ; REQUIRES: loadable_module
3
3 ;
4 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-nodebug -bugpoint-crashcalls -silence-passes -disable-namedmd-remove > /dev/null
5 ; RUN: llvm-dis %t-nodebug-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NODEBUG
6 ;
7 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t-notype -bugpoint-crashcalls -silence-passes -disable-namedmd-remove -disable-strip-debuginfo > /dev/null
8 ; RUN: llvm-dis %t-notype-reduced-simplified.bc -o - | FileCheck %s --check-prefix=NOTYPE
9 ;
410 ; Bugpoint should keep the call's metadata attached to the call.
511
612 ; CHECK: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
13 ; NODEBUG: call void @foo(), !attach ![[CALL:[0-9]+]]
14 ; NOTYPE: call void @foo(), !dbg ![[LOC:[0-9]+]], !attach ![[CALL:[0-9]+]]
15 ; NODEBUG-NOT: call void @foo(), !attach ![[CALL:[0-9]+]]
16 ; NOTYPE-NOT: !DIBasicType
17 ; NOTYPE: !DICompileUnit
18 ; NOTYPE-NOT: !DIBasicType
719 ; CHECK-DAG: ![[LOC]] = !DILocation(line: 104, column: 105, scope: ![[SCOPE:[0-9]+]])
820 ; CHECK-DAG: ![[SCOPE]] = distinct !DISubprogram(name: "test",{{.*}}file: ![[FILE:[0-9]+]]
921 ; CHECK-DAG: ![[FILE]] = !DIFile(filename: "source.c", directory: "/dir")
3143 !4 = !{!"filler"}
3244
3345 !8 = distinct !DICompileUnit(language: DW_LANG_C99, file: !15)
34 !9 = distinct !DISubprogram(name: "test", file: !15, unit: !8)
46 !9 = distinct !DISubprogram(name: "test", file: !15, type: !18, unit: !8)
3547 !10 = !DILocation(line: 100, column: 101, scope: !9)
3648 !11 = !DILocation(line: 102, column: 103, scope: !9)
3749 !12 = !DILocation(line: 104, column: 105, scope: !9)
4052 !15 = !DIFile(filename: "source.c", directory: "/dir")
4153 !16 = !{}
4254 !17 = !{i32 1, !"Debug Info Version", i32 3}
55 !18 = !DISubroutineType(types: !19)
56 !19 = !{!20, !20}
57 !20 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
None ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
0 ; RUN: bugpoint -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes -disable-strip-debuginfo > /dev/null
11 ; RUN: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
22 ; RUN-DISABLE: bugpoint -disable-namedmd-remove -load %llvmshlibdir/BugpointPasses%shlibext %s -output-prefix %t -bugpoint-crash-too-many-cus -silence-passes > /dev/null
33 ; RUN-DISABLE: llvm-dis %t-reduced-simplified.bc -o - | FileCheck %s
0 ; RUN: opt -S -strip-nonlinetable-debuginfo %s -o %t.ll
1 ; RUN: cat %t.ll | FileCheck %s
2 ; RUN: cat %t.ll | FileCheck %s --check-prefix=CHECK-NEG
3 ;
4 ; This test provides coverage for setting the containing type of a DISubprogram.
5 ;
6 ; Generated an reduced from:
7 ; struct A {
8 ; virtual ~A();
9 ; };
10 ; struct B : A {};
11 ; B b;
12
13 source_filename = "t.cpp"
14 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
15 target triple = "x86_64-apple-macosx10.12.0"
16
17 %struct.B = type { %struct.A }
18 %struct.A = type { i32 (...)** }
19
20 ; CHECK: @b = global
21 ; CHECK-NOT: !dbg
22 @b = global %struct.B zeroinitializer, align 8, !dbg !0
23
24 declare void @_ZN1BC2Ev(%struct.B*) unnamed_addr
25
26 ; Function Attrs: nounwind readnone
27 declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
28
29 ; Function Attrs: inlinehint nounwind ssp uwtable
30 ; CHECK: define
31 define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr #1 align 2 !dbg !24 {
32 entry:
33 %this.addr = alloca %struct.B*, align 8
34 store %struct.B* %this, %struct.B** %this.addr, align 8
35 ; CHECK-NOT: @llvm.dbg.declare
36 call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !29, metadata !31), !dbg !32
37 %this1 = load %struct.B*, %struct.B** %this.addr, align 8
38 ; CHECK: call void @_ZN1BC2Ev(%struct.B* %this1){{.*}} !dbg !
39 call void @_ZN1BC2Ev(%struct.B* %this1) #2, !dbg !33
40 ret void, !dbg !33
41 }
42
43 attributes #0 = { nounwind readnone }
44 attributes #1 = { inlinehint nounwind ssp uwtable }
45 attributes #2 = { nounwind }
46
47 !llvm.dbg.cu = !{!1}
48 !llvm.module.flags = !{!20, !21, !22}
49 !llvm.ident = !{!23}
50
51 ; CHECK-NEG-NOT: !DI{{Basic|Composite|Derived}}Type
52
53 !0 = distinct !DIGlobalVariable(name: "b", scope: !1, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true)
54 !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
55 !2 = !DIFile(filename: "t.cpp", directory: "/")
56 !3 = !{}
57 !4 = !{!0}
58 !5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !2, line: 4, size: 64, align: 64, elements: !6, vtableHolder: !8, identifier: "_ZTS1B")
59 !6 = !{!7}
60 !7 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !5, baseType: !8)
61 !8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !2, line: 1, size: 64, align: 64, elements: !9, vtableHolder: !8, identifier: "_ZTS1A")
62 !9 = !{!10, !16}
63 !10 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !2, file: !2, baseType: !11, size: 64, flags: DIFlagArtificial)
64 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
65 !12 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !13, size: 64)
66 !13 = !DISubroutineType(types: !14)
67 !14 = !{!15}
68 !15 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
69 ; Only referenced by the type system.
70 ; CHECK-NEG-NOT: !DISubprogram(name: "~A"
71 !16 = !DISubprogram(name: "~A", scope: !8, file: !2, line: 2, type: !17, isLocal: false, isDefinition: false, scopeLine: 2, containingType: !8, virtuality: DW_VIRTUALITY_virtual, virtualIndex: 0, flags: DIFlagPrototyped, isOptimized: false)
72 !17 = !DISubroutineType(types: !18)
73 !18 = !{null, !19}
74 !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
75 !20 = !{i32 2, !"Dwarf Version", i32 4}
76 !21 = !{i32 2, !"Debug Info Version", i32 3}
77 !22 = !{i32 1, !"PIC Level", i32 2}
78 !23 = !{!"clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)"}
79 ; CHECK: !DISubprogram(name: "B", scope: ![[FILE:.*]], file: ![[FILE]],
80 ; CHECK-NOT: containingType:
81 !24 = distinct !DISubprogram(name: "B", linkageName: "_ZN1BC1Ev", scope: !5, file: !2, line: 4, type: !25, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false, unit: !1, declaration: !28, variables: !3)
82 !25 = !DISubroutineType(types: !26)
83 !26 = !{null, !27}
84 !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
85 ; CHECK-NEG-NOT: !DISubprogram(name: "B", {{.*}}, isDefinition: false
86 !28 = !DISubprogram(name: "B", scope: !5, type: !25, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
87 !29 = !DILocalVariable(name: "this", arg: 1, scope: !24, type: !30, flags: DIFlagArtificial | DIFlagObjectPointer)
88 !30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64)
89 !31 = !DIExpression()
90 !32 = !DILocation(line: 0, scope: !24)
91 !33 = !DILocation(line: 4, column: 8, scope: !24)
0 ; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
1 !llvm.dbg.cu = !{!2, !6}
2 !llvm.gcov = !{!3}
3 !llvm.module.flags = !{!7}
4
5 !1 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
6 ; The first CU is used for the line table, the second one is a module skeleton
7 ; and should be stripped.
8 ; CHECK: !llvm.dbg.cu = !{![[CU:[0-9]+]]}
9 ; CHECK: ![[CU]] = distinct !DICompileUnit({{.*}}"abc.debug"{{.*}}LineTablesOnly
10 ; CHECK-NOT: retainedTypes:
11 ; CHECK-SAME: )
12 ; CHECK-NOT: DICompositeType
13 !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
14 isOptimized: true, flags: "-O2", runtimeVersion: 2,
15 splitDebugFilename: "abc.debug", emissionKind: FullDebug,
16 retainedTypes: !4)
17 !3 = !{!"path/to/file.o", !2}
18 !4 = !{!5}
19 !5 = !DICompositeType(tag: DW_TAG_structure_type, file: !1, identifier: "ThisWillBeStripped")
20 !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
21 splitDebugFilename: "abc.dwo", emissionKind: FullDebug,
22 dwoId: 1234)
23 !7 = !{i32 1, !"Debug Info Version", i32 3}
0 ; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
1 ; CHECK: define void @f() !dbg ![[F:[0-9]+]]
2 define void @f() !dbg !4 {
3 entry:
4 %i = alloca i32, align 4
5 ; CHECK-NOT: llvm.dbg.declare
6 call void @llvm.dbg.declare(metadata i32* %i, metadata !11, metadata !13), !dbg !14
7 store i32 42, i32* %i, align 4, !dbg !14
8 ret void, !dbg !15
9 }
10
11 ; Function Attrs: nounwind readnone
12 declare void @llvm.dbg.declare(metadata, metadata, metadata)
13
14 !llvm.dbg.cu = !{!0}
15 !llvm.module.flags = !{!7, !8, !9}
16 !llvm.ident = !{!10}
17
18 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2)
19 !1 = !DIFile(filename: "f.c", directory: "/")
20 !2 = !{}
21 ; CHECK: ![[F]] = distinct !DISubprogram(name: "f"
22 ; CHECK-NOT: variables:
23 ; CHECK-NOT: distinct !DISubprogram(name: "f"
24 !4 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, variables: !2)
25 !5 = !DISubroutineType(types: !6)
26 !6 = !{null}
27 !7 = !{i32 2, !"Dwarf Version", i32 2}
28 !8 = !{i32 2, !"Debug Info Version", i32 3}
29 !9 = !{i32 1, !"PIC Level", i32 2}
30 !10 = !{!"LLVM"}
31 !11 = !DILocalVariable(name: "i", scope: !4, file: !1, line: 1, type: !12)
32 !12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
33 !13 = !DIExpression()
34 !14 = !DILocation(line: 1, column: 16, scope: !4)
35 !15 = !DILocation(line: 1, column: 24, scope: !4)
0 ; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
1 ; Test that subroutine types are downgraded to (void)().
2 define internal i32 @"__hidden#2878_"() #0 !dbg !12 {
3 ret i32 0, !dbg !634
4 }
5 !llvm.dbg.cu = !{!18}
6 !llvm.module.flags = !{!482}
7 !5 = !{}
8 !2 = !{!12}
9 ; CHECK-NOT: DICompositeType
10 ; CHECK: distinct !DISubprogram(name: "f", {{.*}}, type: ![[FNTY:[0-9]+]]
11 ; CHECK: ![[FNTY]] = !DISubroutineType(types: ![[VOID:[0-9]+]])
12 ; CHECK: ![[VOID]] = !{}
13 ; CHECK-NOT: DICompositeType
14 !12 = distinct !DISubprogram(name: "f", scope: !16, file: !16, line: 133, type: !13, isLocal: true, isDefinition: true, scopeLine: 133, flags: DIFlagPrototyped, isOptimized: true, unit: !18, variables: !5)
15 !13 = !DISubroutineType(types: !14)
16 !14 = !{!17}
17 !16 = !DIFile(filename: "f.m", directory: "/")
18 !17 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e", scope: !18, file: !16, line: 13, size: 32, align: 32, flags: DIFlagFwdDecl)
19 !18 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !16, producer: "clang", isOptimized: true, runtimeVersion: 2, emissionKind: 1, enums: !14, retainedTypes: !14, globals: !5, imports: !5)
20 !482 = !{i32 2, !"Debug Info Version", i32 3}
21 !634 = !DILocation(line: 143, column: 5, scope: !12)
1818 #include "llvm/Analysis/TargetTransformInfo.h"
1919 #include "llvm/IR/CFG.h"
2020 #include "llvm/IR/Constants.h"
21 #include "llvm/IR/DebugInfo.h"
2122 #include "llvm/IR/DerivedTypes.h"
2223 #include "llvm/IR/Instructions.h"
2324 #include "llvm/IR/LegacyPassManager.h"
5354 cl::opt NoNamedMDRM("disable-namedmd-remove",
5455 cl::desc("Do not remove global named metadata"),
5556 cl::init(false));
57 cl::opt NoStripDebugInfo("disable-strip-debuginfo",
58 cl::desc("Do not strip debug info metadata"),
59 cl::init(false));
60 cl::opt NoStripDebugTypeInfo("disable-strip-debug-types",
61 cl::desc("Do not strip debug type info metadata"),
62 cl::init(false));
5663 cl::opt VerboseErrors("verbose-errors",
5764 cl::desc("Print the output of crashing program"),
5865 cl::init(false));
11221129 if (Error E = ReduceInsts(BD, TestFn))
11231130 return E;
11241131
1132 // Attempt to strip debug info metadata.
1133 auto stripMetadata = [&](std::function strip) {
1134 std::unique_ptr M = CloneModule(BD.getProgram());
1135 strip(*M);
1136 if (TestFn(BD, M.get()))
1137 BD.setNewProgram(M.release());
1138 };
1139 if (!NoStripDebugInfo && !BugpointIsInterrupted) {
1140 outs() << "\n*** Attempting to strip the debug info: ";
1141 stripMetadata(StripDebugInfo);
1142 }
1143 if (!NoStripDebugTypeInfo && !BugpointIsInterrupted) {
1144 outs() << "\n*** Attempting to strip the debug type info: ";
1145 stripMetadata(stripNonLineTableDebugInfo);
1146 }
1147
11251148 if (!NoNamedMDRM) {
11261149 if (!BugpointIsInterrupted) {
11271150 // Try to reduce the amount of global metadata (particularly debug info),