llvm.org GIT mirror llvm / bda4e02
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283473 91177308-0d34-0410-b5e6-96231b3b80d8 Michael Ilseman 2 years ago
14 changed file(s) with 584 addition(s) and 5 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);
327327 void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&);
328328 void initializeStripDebugDeclarePass(PassRegistry&);
329329 void initializeStripNonDebugSymbolsPass(PassRegistry&);
330 void initializeStripNonLineTableDebugInfoPass(PassRegistry&);
330331 void initializeStripSymbolsPass(PassRegistry&);
331332 void initializeStructurizeCFGPass(PassRegistry&);
332333 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.
286286 return Changed;
287287 }
288288
289 namespace {
290
291 /// Helper class to downgrade -g metadata to -gline-tables-only metadata.
292 class DebugTypeInfoRemoval {
293 DenseMap Replacements;
294
295 public:
296 /// The (void)() type.
297 MDNode *EmptySubroutineType;
298
299 private:
300 /// Remember what linkage name we originally had before stripping. If we end
301 /// up making two subprograms identical who originally had different linkage
302 /// names, then we need to make one of them distinct, to avoid them getting
303 /// uniqued. Maps the new node to the old linkage name.
304 DenseMap NewToLinkageName;
305
306 // TODO: Remember the distinct subprogram we created for a given linkage name,
307 // so that we can continue to unique whenever possible. Map
308 // node, old linkage name> to the first (possibly distinct) mdsubprogram
309 // created for that combination. This is not strictly needed for correctness,
310 // but can cut down on the number of MDNodes and let us diff cleanly with the
311 // output of -gline-tables-only.
312
313 public:
314 DebugTypeInfoRemoval(LLVMContext &C)
315 : EmptySubroutineType(DISubroutineType::get(C, DINode::FlagZero, 0,
316 MDNode::get(C, {}))) {}
317
318 Metadata *map(Metadata *M) {
319 if (!M)
320 return nullptr;
321 if (Replacements.count(M))
322 return Replacements.lookup(M);
323
324 return M;
325 }
326 MDNode *mapNode(Metadata *N) { return dyn_cast_or_null(map(N)); }
327
328 /// Recursively remap N and all its referenced children. Does a DF post-order
329 /// traversal, so as to remap bottoms up.
330 void traverseAndRemap(MDNode *N) { traverse(N); }
331
332 private:
333 // Create a new DISubprogram, to replace the one given.
334 DISubprogram *getReplacementSubprogram(DISubprogram *MDS) {
335 auto *FileAndScope = cast_or_null(map(MDS->getFile()));
336 StringRef LinkageName = MDS->getName().empty() ? MDS->getLinkageName() : "";
337 DISubprogram *Declaration = nullptr;
338 auto *Type = cast_or_null(map(MDS->getType()));
339 DITypeRef ContainingType(map(MDS->getContainingType()));
340 auto *Unit = cast_or_null(map(MDS->getUnit()));
341 auto Variables = nullptr;
342 auto TemplateParams = nullptr;
343
344 // Make a distinct DISubprogram, for situations that warrent it.
345 auto distinctMDSubprogram = [&]() {
346 return DISubprogram::getDistinct(
347 MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
348 FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
349 MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
350 MDS->getVirtuality(), MDS->getVirtualIndex(),
351 MDS->getThisAdjustment(), MDS->getFlags(), MDS->isOptimized(), Unit,
352 TemplateParams, Declaration, Variables);
353 };
354
355 if (MDS->isDistinct())
356 return distinctMDSubprogram();
357
358 auto *NewMDS = DISubprogram::get(
359 MDS->getContext(), FileAndScope, MDS->getName(), LinkageName,
360 FileAndScope, MDS->getLine(), Type, MDS->isLocalToUnit(),
361 MDS->isDefinition(), MDS->getScopeLine(), ContainingType,
362 MDS->getVirtuality(), MDS->getVirtualIndex(), MDS->getThisAdjustment(),
363 MDS->getFlags(), MDS->isOptimized(), Unit, TemplateParams, Declaration,
364 Variables);
365
366 StringRef OldLinkageName = MDS->getLinkageName();
367
368 // See if we need to make a distinct one.
369 auto OrigLinkage = NewToLinkageName.find(NewMDS);
370 if (OrigLinkage != NewToLinkageName.end()) {
371 if (OrigLinkage->second == OldLinkageName)
372 // We're good.
373 return NewMDS;
374
375 // Otherwise, need to make a distinct one.
376 // TODO: Query the map to see if we already have one.
377 return distinctMDSubprogram();
378 }
379
380 NewToLinkageName.insert({NewMDS, MDS->getLinkageName()});
381 return NewMDS;
382 }
383
384 /// Create a new compile unit, to replace the one given
385 DICompileUnit *getReplacementCU(DICompileUnit *CU) {
386 // Drop skeleton CUs.
387 if (CU->getDWOId())
388 return nullptr;
389
390 auto *File = cast_or_null(map(CU->getFile()));
391 MDTuple *EnumTypes = nullptr;
392 MDTuple *RetainedTypes = nullptr;
393 MDTuple *GlobalVariables = nullptr;
394 MDTuple *ImportedEntities = nullptr;
395 return DICompileUnit::getDistinct(
396 CU->getContext(), CU->getSourceLanguage(), File, CU->getProducer(),
397 CU->isOptimized(), CU->getFlags(), CU->getRuntimeVersion(),
398 CU->getSplitDebugFilename(), DICompileUnit::LineTablesOnly, EnumTypes,
399 RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros(),
400 CU->getDWOId(), CU->getSplitDebugInlining());
401 }
402
403 DILocation *getReplacementMDLocation(DILocation *MLD) {
404 auto *Scope = map(MLD->getScope());
405 auto *InlinedAt = map(MLD->getInlinedAt());
406 if (MLD->isDistinct())
407 return DILocation::getDistinct(MLD->getContext(), MLD->getLine(),
408 MLD->getColumn(), Scope, InlinedAt);
409 return DILocation::get(MLD->getContext(), MLD->getLine(), MLD->getColumn(),
410 Scope, InlinedAt);
411 }
412
413 /// Create a new generic MDNode, to replace the one given
414 MDNode *getReplacementMDNode(MDNode *N) {
415 SmallVector Ops;
416 Ops.reserve(N->getNumOperands());
417 for (auto &I : N->operands())
418 if (I)
419 Ops.push_back(map(I));
420 auto *Ret = MDNode::get(N->getContext(), Ops);
421 return Ret;
422 }
423
424 /// Attempt to re-map N to a newly created node.
425 void remap(MDNode *N) {
426 if (Replacements.count(N))
427 return;
428
429 auto doRemap = [&](MDNode *N) -> MDNode * {
430 if (!N)
431 return nullptr;
432 if (auto *MDSub = dyn_cast(N)) {
433 remap(MDSub->getUnit());
434 return getReplacementSubprogram(MDSub);
435 }
436 if (isa(N))
437 return EmptySubroutineType;
438 if (auto *CU = dyn_cast(N))
439 return getReplacementCU(CU);
440 if (isa(N))
441 return N;
442 if (auto *MDLB = dyn_cast(N))
443 // Remap to our referenced scope (recursively).
444 return mapNode(MDLB->getScope());
445 if (auto *MLD = dyn_cast(N))
446 return getReplacementMDLocation(MLD);
447
448 // Otherwise, if we see these, just drop them now. Not strictly necessary,
449 // but this speeds things up a little.
450 if (isa(N))
451 return nullptr;
452
453 return getReplacementMDNode(N);
454 };
455 Replacements[N] = doRemap(N);
456 }
457
458 /// Do the remapping traversal.
459 void traverse(MDNode *);
460 };
461
462 } // Anonymous namespace.
463
464 void DebugTypeInfoRemoval::traverse(MDNode *N) {
465 if (!N || Replacements.count(N))
466 return;
467
468 // To avoid cycles, as well as for efficiency sake, we will sometimes prune
469 // parts of the graph.
470 auto prune = [](MDNode *Parent, MDNode *Child) {
471 if (auto *MDS = dyn_cast(Parent))
472 return Child == MDS->getVariables().get();
473 return false;
474 };
475
476 SmallVector ToVisit;
477 DenseSet Opened;
478
479 // Visit each node starting at N in post order, and map them.
480 ToVisit.push_back(N);
481 while (!ToVisit.empty()) {
482 auto *N = ToVisit.back();
483 auto Result = Opened.insert(N);
484 if (!Result.second) {
485 // Close it.
486 remap(N);
487 ToVisit.pop_back();
488 continue;
489 }
490 for (auto &I : N->operands())
491 if (auto *MDN = dyn_cast_or_null(I))
492 if (!Opened.count(MDN) && !Replacements.count(MDN) && !prune(N, MDN) &&
493 !isa(MDN))
494 ToVisit.push_back(MDN);
495 }
496 }
497
498 bool llvm::stripNonLineTableDebugInfo(Module &M) {
499 bool Changed = false;
500
501 // First off, delete the debug intrinsics.
502 if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
503 while (!Declare->use_empty()) {
504 auto *DDI = cast(Declare->user_back());
505 DDI->eraseFromParent();
506 }
507 Declare->eraseFromParent();
508 Changed = true;
509 }
510 if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
511 while (!DbgVal->use_empty()) {
512 auto *DVI = cast(DbgVal->user_back());
513 DVI->eraseFromParent();
514 }
515 DbgVal->eraseFromParent();
516 Changed = true;
517 }
518
519 // Delete non-CU debug info named metadata nodes.
520 for (auto NMI = M.named_metadata_begin(), NME = M.named_metadata_end();
521 NMI != NME;) {
522 NamedMDNode *NMD = &*NMI;
523 ++NMI;
524 // Specifically keep dbg.cu around.
525 if (NMD->getName() == "llvm.dbg.cu")
526 continue;
527 }
528
529 // Drop all dbg attachments from global variables.
530 for (auto &GV : M.globals())
531 GV.getContext().pImpl->GlobalObjectMetadata[&GV].erase(LLVMContext::MD_dbg);
532
533 DebugTypeInfoRemoval Mapper(M.getContext());
534
535 // Rewrite the DebugLocs to be equivalent to what
536 // -gline-tables-only would have created.
537 for (auto &F : M) {
538 auto *SP = F.getSubprogram();
539 if (SP) {
540 Mapper.traverseAndRemap(SP);
541 auto *NewSP = cast(Mapper.mapNode(SP));
542 Changed |= SP != NewSP;
543 F.setSubprogram(NewSP);
544 }
545 for (auto &BB : F) {
546 for (auto &I : BB) {
547 if (I.getDebugLoc() == DebugLoc())
548 continue;
549
550 // Make a replacement.
551 auto &DL = I.getDebugLoc();
552 auto *Scope = DL.getScope();
553 auto *InlinedAt = DL.getInlinedAt();
554
555 // Remap scope.
556 if (Scope) {
557 Mapper.traverseAndRemap(Scope);
558 auto *NewScope = Mapper.mapNode(Scope);
559 Changed |= Scope != NewScope;
560 Scope = NewScope;
561 }
562
563 // Remap inlinedAt.
564 if (InlinedAt) {
565 Mapper.traverseAndRemap(InlinedAt);
566 auto *NewIA = Mapper.mapNode(InlinedAt);
567 Changed |= InlinedAt != NewIA;
568 InlinedAt = cast_or_null(NewIA);
569 }
570
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 Mapper.traverseAndRemap(Op);
583 auto *NewOp = Mapper.mapNode(Op);
584 Changed |= NewOp != Op;
585 Ops.push_back(NewOp);
586 }
587
588 if (Changed) {
589 NMD.dropAllReferences();
590 for (auto *Op : Ops)
591 if (Op)
592 NMD.addOperand(Op);
593 }
594 }
595 return Changed;
596 }
597
289598 unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
290599 if (auto *Val = mdconst::dyn_extract_or_null(
291600 M.getModuleFlag("Debug Info Version")))
4040 SimplifyInstructions.cpp
4141 SimplifyLibCalls.cpp
4242 SplitModule.cpp
43 StripNonLineTableDebugInfo.cpp
4344 SymbolRewriter.cpp
4445 UnifyFunctionExitNodes.cpp
4546 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 }
2929 initializeLowerSwitchPass(Registry);
3030 initializeNameAnonGlobalLegacyPassPass(Registry);
3131 initializePromoteLegacyPassPass(Registry);
32 initializeStripNonLineTableDebugInfoPass(Registry);
3233 initializeUnifyFunctionExitNodesPass(Registry);
3334 initializeInstSimplifierPass(Registry);
3435 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 - | 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 define internal i32 @"__hidden#2878_"() #0 !dbg !12 {
2 ret i32 0, !dbg !634
3 }
4 !llvm.dbg.cu = !{!18}
5 !llvm.module.flags = !{!482}
6 !5 = !{}
7 !2 = !{!12}
8 ; CHECK-NOT: DICompositeType
9 ; CHECK: distinct !DISubprogram(name: "f", {{.*}}, type: ![[FNTY:[0-9]+]]
10 ; CHECK: ![[FNTY]] = !DISubroutineType(types: ![[VOID:[0-9]+]])
11 ; CHECK: ![[VOID]] = !{}
12 ; CHECK-NOT: DICompositeType
13 !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)
14 !13 = !DISubroutineType(types: !14)
15 !14 = !{!17}
16 !16 = !DIFile(filename: "f.m", directory: "/")
17 !17 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "e", scope: !18, file: !16, line: 13, size: 32, align: 32, flags: DIFlagFwdDecl)
18 !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)
19 !482 = !{i32 2, !"Debug Info Version", i32 3}
20 !634 = !DILocation(line: 143, column: 5, scope: !12)
0 ; RUN: opt -S -strip-nonlinetable-debuginfo %s -o - | FileCheck %s
1 ; Generated an reduced from:
2 ; struct A {
3 ; virtual ~A();
4 ; };
5 ; struct B : A {};
6 ; B b;
7
8 source_filename = "t.cpp"
9 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
10 target triple = "x86_64-apple-macosx10.12.0"
11
12 %struct.B = type { %struct.A }
13 %struct.A = type { i32 (...)** }
14
15 ; CHECK: @b = global
16 ; CHECK-NOT: !dbg
17 @b = global %struct.B zeroinitializer, align 8, !dbg !0
18
19 declare void @_ZN1BC2Ev(%struct.B*) unnamed_addr
20
21 ; Function Attrs: nounwind readnone
22 declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
23
24 ; Function Attrs: inlinehint nounwind ssp uwtable
25 ; CHECK: define
26 define linkonce_odr void @_ZN1BC1Ev(%struct.B* %this) unnamed_addr #1 align 2 !dbg !24 {
27 entry:
28 %this.addr = alloca %struct.B*, align 8
29 store %struct.B* %this, %struct.B** %this.addr, align 8
30 ; CHECK-NOT: @llvm.dbg.declare
31 call void @llvm.dbg.declare(metadata %struct.B** %this.addr, metadata !29, metadata !31), !dbg !32
32 %this1 = load %struct.B*, %struct.B** %this.addr, align 8
33 ; CHECK: call void @_ZN1BC2Ev(%struct.B* %this1){{.*}} !dbg !
34 call void @_ZN1BC2Ev(%struct.B* %this1) #2, !dbg !33
35 ret void, !dbg !33
36 }
37
38 attributes #0 = { nounwind readnone }
39 attributes #1 = { inlinehint nounwind ssp uwtable }
40 attributes #2 = { nounwind }
41
42 !llvm.dbg.cu = !{!1}
43 !llvm.module.flags = !{!20, !21, !22}
44 !llvm.ident = !{!23}
45
46 ; CHECK-NOT: !DI{{Basic|Composite|Derived}}Type
47
48 !0 = distinct !DIGlobalVariable(name: "b", scope: !1, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true)
49 !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)
50 !2 = !DIFile(filename: "t.cpp", directory: "/")
51 !3 = !{}
52 !4 = !{!0}
53 !5 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !2, line: 4, size: 64, align: 64, elements: !6, vtableHolder: !8, identifier: "_ZTS1B")
54 !6 = !{!7}
55 !7 = !DIDerivedType(tag: DW_TAG_inheritance, scope: !5, baseType: !8)
56 !8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !2, line: 1, size: 64, align: 64, elements: !9, vtableHolder: !8, identifier: "_ZTS1A")
57 !9 = !{!10, !16}
58 !10 = !DIDerivedType(tag: DW_TAG_member, name: "_vptr$A", scope: !2, file: !2, baseType: !11, size: 64, flags: DIFlagArtificial)
59 !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
60 !12 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__vtbl_ptr_type", baseType: !13, size: 64)
61 !13 = !DISubroutineType(types: !14)
62 !14 = !{!15}
63 !15 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
64 !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)
65 !17 = !DISubroutineType(types: !18)
66 !18 = !{null, !19}
67 !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
68 !20 = !{i32 2, !"Dwarf Version", i32 4}
69 !21 = !{i32 2, !"Debug Info Version", i32 3}
70 !22 = !{i32 1, !"PIC Level", i32 2}
71 !23 = !{!"clang version 4.0.0 (trunk 282583) (llvm/trunk 282611)"}
72 !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)
73 !25 = !DISubroutineType(types: !26)
74 !26 = !{null, !27}
75 !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
76 !28 = !DISubprogram(name: "B", scope: !5, type: !25, isLocal: false, isDefinition: false, flags: DIFlagArtificial | DIFlagPrototyped, isOptimized: false)
77 !29 = !DILocalVariable(name: "this", arg: 1, scope: !24, type: !30, flags: DIFlagArtificial | DIFlagObjectPointer)
78 !30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !5, size: 64, align: 64)
79 !31 = !DIExpression()
80 !32 = !DILocation(line: 0, scope: !24)
81 !33 = !DILocation(line: 4, column: 8, scope: !24)
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 if (!NoStripDebugInfo) {
1133 if (!BugpointIsInterrupted) {
1134 outs() << "\n*** Attempting to strip the debug info: ";
1135 Module *M = CloneModule(BD.getProgram()).release();
1136 StripDebugInfo(*M);
1137 if (TestFn(BD, M))
1138 BD.setNewProgram(M);
1139 else
1140 delete M;
1141 }
1142 }
1143
1144 if (!NoStripDebugTypeInfo) {
1145 if (!BugpointIsInterrupted) {
1146 outs() << "\n*** Attempting to strip the debug type info: ";
1147 Module *M = CloneModule(BD.getProgram()).release();
1148 stripNonLineTableDebugInfo(*M);
1149 if (TestFn(BD, M))
1150 BD.setNewProgram(M);
1151 else
1152 delete M;
1153 }
1154 }
1155
11251156 if (!NoNamedMDRM) {
11261157 if (!BugpointIsInterrupted) {
11271158 // Try to reduce the amount of global metadata (particularly debug info),