forked from OSchip/llvm-project
Debug Info: remove duplication of DIEs when a DIE can be shared across CUs.
We add a map in DwarfDebug to map MDNodes that are shareable across CUs to the corresponding DIEs: MDTypeNodeToDieMap. These DIEs can be shared across CUs, that is why we keep the maps in DwarfDebug instead of CompileUnit. We make the assumption that if a DIE is not added to an owner yet, we assume it belongs to the current CU. Since DIEs for the type system are added to their owners immediately after creation, and other DIEs belong to the current CU, the assumption should be true. A testing case is added to show that we only create a single DIE for a type MDNode and we use ref_addr to refer to the type DIE. We also add a testing case to show ref_addr relocations for non-darwin platforms. llvm-svn: 193779
This commit is contained in:
parent
8d72f4a06f
commit
4dbdc9021d
|
@ -115,13 +115,21 @@ DIE::~DIE() {
|
||||||
/// Climb up the parent chain to get the compile unit DIE to which this DIE
|
/// Climb up the parent chain to get the compile unit DIE to which this DIE
|
||||||
/// belongs.
|
/// belongs.
|
||||||
const DIE *DIE::getCompileUnit() const {
|
const DIE *DIE::getCompileUnit() const {
|
||||||
|
const DIE *Cu = getCompileUnitOrNull();
|
||||||
|
assert(Cu && "We should not have orphaned DIEs.");
|
||||||
|
return Cu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Climb up the parent chain to get the compile unit DIE this DIE belongs
|
||||||
|
/// to. Return NULL if DIE is not added to an owner yet.
|
||||||
|
const DIE *DIE::getCompileUnitOrNull() const {
|
||||||
const DIE *p = this;
|
const DIE *p = this;
|
||||||
while (p) {
|
while (p) {
|
||||||
if (p->getTag() == dwarf::DW_TAG_compile_unit)
|
if (p->getTag() == dwarf::DW_TAG_compile_unit)
|
||||||
return p;
|
return p;
|
||||||
p = p->getParent();
|
p = p->getParent();
|
||||||
}
|
}
|
||||||
llvm_unreachable("We should not have orphaned DIEs.");
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIEValue *DIE::findAttribute(uint16_t Attribute) {
|
DIEValue *DIE::findAttribute(uint16_t Attribute) {
|
||||||
|
|
|
@ -149,6 +149,9 @@ namespace llvm {
|
||||||
/// Climb up the parent chain to get the compile unit DIE this DIE belongs
|
/// Climb up the parent chain to get the compile unit DIE this DIE belongs
|
||||||
/// to.
|
/// to.
|
||||||
const DIE *getCompileUnit() const;
|
const DIE *getCompileUnit() const;
|
||||||
|
/// Similar to getCompileUnit, returns null when DIE is not added to an
|
||||||
|
/// owner yet.
|
||||||
|
const DIE *getCompileUnitOrNull() const;
|
||||||
void setOffset(unsigned O) { Offset = O; }
|
void setOffset(unsigned O) { Offset = O; }
|
||||||
void setSize(unsigned S) { Size = S; }
|
void setSize(unsigned S) { Size = S; }
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,35 @@ int64_t CompileUnit::getDefaultLowerBound() const {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether the DIE for this MDNode can be shared across CUs.
|
||||||
|
static bool isShareableAcrossCUs(const MDNode *N) {
|
||||||
|
// When the MDNode can be part of the type system, the DIE can be
|
||||||
|
// shared across CUs.
|
||||||
|
return DIDescriptor(N).isType() ||
|
||||||
|
(DIDescriptor(N).isSubprogram() && !DISubprogram(N).isDefinition());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getDIE - Returns the debug information entry map slot for the
|
||||||
|
/// specified debug variable. We delegate the request to DwarfDebug
|
||||||
|
/// when the DIE for this MDNode can be shared across CUs. The mappings
|
||||||
|
/// will be kept in DwarfDebug for shareable DIEs.
|
||||||
|
DIE *CompileUnit::getDIE(const MDNode *N) const {
|
||||||
|
if (isShareableAcrossCUs(N))
|
||||||
|
return DD->getDIE(N);
|
||||||
|
return MDNodeToDieMap.lookup(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug
|
||||||
|
/// when the DIE for this MDNode can be shared across CUs. The mappings
|
||||||
|
/// will be kept in DwarfDebug for shareable DIEs.
|
||||||
|
void CompileUnit::insertDIE(const MDNode *N, DIE *D) {
|
||||||
|
if (isShareableAcrossCUs(N)) {
|
||||||
|
DD->insertDIE(N, D);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MDNodeToDieMap.insert(std::make_pair(N, D));
|
||||||
|
}
|
||||||
|
|
||||||
/// addFlag - Add a flag that is true.
|
/// addFlag - Add a flag that is true.
|
||||||
void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
|
void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
|
||||||
if (DD->getDwarfVersion() >= 4)
|
if (DD->getDwarfVersion() >= 4)
|
||||||
|
@ -245,8 +274,21 @@ void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form For
|
||||||
/// addDIEEntry - Add a DIE attribute data and value.
|
/// addDIEEntry - Add a DIE attribute data and value.
|
||||||
///
|
///
|
||||||
void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) {
|
void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) {
|
||||||
// We currently only use ref4.
|
addDIEEntry(Die, Attribute, createDIEEntry(Entry));
|
||||||
Die->addValue(Attribute, dwarf::DW_FORM_ref4, createDIEEntry(Entry));
|
}
|
||||||
|
|
||||||
|
void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
|
||||||
|
DIEEntry *Entry) {
|
||||||
|
const DIE *DieCU = Die->getCompileUnitOrNull();
|
||||||
|
const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull();
|
||||||
|
if (!DieCU)
|
||||||
|
// We assume that Die belongs to this CU, if it is not linked to any CU yet.
|
||||||
|
DieCU = getCUDie();
|
||||||
|
if (!EntryCU)
|
||||||
|
EntryCU = getCUDie();
|
||||||
|
Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4
|
||||||
|
: dwarf::DW_FORM_ref_addr,
|
||||||
|
Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a DIE with the given Tag, add the DIE to its parent, and
|
/// Create a DIE with the given Tag, add the DIE to its parent, and
|
||||||
|
@ -882,7 +924,7 @@ void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) {
|
||||||
DIEEntry *Entry = getDIEEntry(Ty);
|
DIEEntry *Entry = getDIEEntry(Ty);
|
||||||
// If it exists then use the existing value.
|
// If it exists then use the existing value.
|
||||||
if (Entry) {
|
if (Entry) {
|
||||||
Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
|
addDIEEntry(Entity, Attribute, Entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,7 +934,7 @@ void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) {
|
||||||
// Set up proxy.
|
// Set up proxy.
|
||||||
Entry = createDIEEntry(Buffer);
|
Entry = createDIEEntry(Buffer);
|
||||||
insertDIEEntry(Ty, Entry);
|
insertDIEEntry(Ty, Entry);
|
||||||
Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
|
addDIEEntry(Entity, Attribute, Entry);
|
||||||
|
|
||||||
// If this is a complete composite type then include it in the
|
// If this is a complete composite type then include it in the
|
||||||
// list of global types.
|
// list of global types.
|
||||||
|
|
|
@ -155,15 +155,19 @@ public:
|
||||||
void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die);
|
void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die);
|
||||||
|
|
||||||
/// getDIE - Returns the debug information entry map slot for the
|
/// getDIE - Returns the debug information entry map slot for the
|
||||||
/// specified debug variable.
|
/// specified debug variable. We delegate the request to DwarfDebug
|
||||||
DIE *getDIE(const MDNode *N) const { return MDNodeToDieMap.lookup(N); }
|
/// when the MDNode can be part of the type system, since DIEs for
|
||||||
|
/// the type system can be shared across CUs and the mappings are
|
||||||
|
/// kept in DwarfDebug.
|
||||||
|
DIE *getDIE(const MDNode *N) const;
|
||||||
|
|
||||||
DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); }
|
DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); }
|
||||||
|
|
||||||
/// insertDIE - Insert DIE into the map.
|
/// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug
|
||||||
void insertDIE(const MDNode *N, DIE *D) {
|
/// when the MDNode can be part of the type system, since DIEs for
|
||||||
MDNodeToDieMap.insert(std::make_pair(N, D));
|
/// the type system can be shared across CUs and the mappings are
|
||||||
}
|
/// kept in DwarfDebug.
|
||||||
|
void insertDIE(const MDNode *N, DIE *D);
|
||||||
|
|
||||||
/// addDie - Adds or interns the DIE to the compile unit.
|
/// addDie - Adds or interns the DIE to the compile unit.
|
||||||
///
|
///
|
||||||
|
@ -224,6 +228,10 @@ public:
|
||||||
///
|
///
|
||||||
void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry);
|
void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry);
|
||||||
|
|
||||||
|
/// addDIEEntry - Add a DIE attribute data and value.
|
||||||
|
///
|
||||||
|
void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIEEntry *Entry);
|
||||||
|
|
||||||
/// addBlock - Add block data.
|
/// addBlock - Add block data.
|
||||||
///
|
///
|
||||||
void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block);
|
void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block);
|
||||||
|
|
|
@ -2083,6 +2083,9 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
|
||||||
DwarfInfoSectionSym,
|
DwarfInfoSectionSym,
|
||||||
DIEEntry::getRefAddrSize(Asm));
|
DIEEntry::getRefAddrSize(Asm));
|
||||||
} else {
|
} else {
|
||||||
|
// Make sure Origin belong to the same CU.
|
||||||
|
assert(Die->getCompileUnit() == Origin->getCompileUnit() &&
|
||||||
|
"The referenced DIE should belong to the same CU in ref4");
|
||||||
Asm->EmitInt32(Addr);
|
Asm->EmitInt32(Addr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -332,6 +332,11 @@ class DwarfDebug {
|
||||||
// Maps a CU DIE with its corresponding CompileUnit.
|
// Maps a CU DIE with its corresponding CompileUnit.
|
||||||
DenseMap <const DIE *, CompileUnit *> CUDieMap;
|
DenseMap <const DIE *, CompileUnit *> CUDieMap;
|
||||||
|
|
||||||
|
/// Maps MDNodes for type sysstem with the corresponding DIEs. These DIEs can
|
||||||
|
/// be shared across CUs, that is why we keep the map here instead
|
||||||
|
/// of in CompileUnit.
|
||||||
|
DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
|
||||||
|
|
||||||
// Used to uniquely define abbreviations.
|
// Used to uniquely define abbreviations.
|
||||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||||
|
|
||||||
|
@ -662,6 +667,13 @@ public:
|
||||||
//
|
//
|
||||||
DwarfDebug(AsmPrinter *A, Module *M);
|
DwarfDebug(AsmPrinter *A, Module *M);
|
||||||
|
|
||||||
|
void insertDIE(const MDNode *TypeMD, DIE *Die) {
|
||||||
|
MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
|
||||||
|
}
|
||||||
|
DIE *getDIE(const MDNode *TypeMD) {
|
||||||
|
return MDTypeNodeToDieMap.lookup(TypeMD);
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Emit all Dwarf sections that should come prior to the
|
/// \brief Emit all Dwarf sections that should come prior to the
|
||||||
/// content.
|
/// content.
|
||||||
void beginModule();
|
void beginModule();
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-linux-gnu < %s | FileCheck %s
|
||||||
|
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-linux-gnu -o %t
|
||||||
|
; RUN: llvm-dwarfdump %t | FileCheck %s -check-prefix=CHECK-DWARF
|
||||||
|
|
||||||
|
; RUN: llc -filetype=obj %s -mtriple=x86_64-apple-darwin -o %t2
|
||||||
|
; RUN: llvm-dwarfdump %t2 | FileCheck %s -check-prefix=DARWIN-DWARF
|
||||||
|
|
||||||
|
; Testing case generated from:
|
||||||
|
; clang++ tu1.cpp tu2.cpp -g -emit-llvm -c
|
||||||
|
; llvm-link tu1.bc tu2.bc -o tu12.ll -S
|
||||||
|
; cat hdr.h
|
||||||
|
; struct foo {
|
||||||
|
; };
|
||||||
|
; cat tu1.cpp
|
||||||
|
; #include "hdr.h"
|
||||||
|
; foo f;
|
||||||
|
; cat tu2.cpp
|
||||||
|
; #include "hdr.h"
|
||||||
|
; foo g;
|
||||||
|
|
||||||
|
; Make sure we use relocation for ref_addr on non-darwin platforms.
|
||||||
|
; CHECK: DW_TAG_compile_unit
|
||||||
|
; CHECK: DW_TAG_variable
|
||||||
|
; CHECK: .long [[TYPE:.*]] # DW_AT_type
|
||||||
|
; CHECK: DW_TAG_structure_type
|
||||||
|
; CHECK: debug_info_end0
|
||||||
|
; CHECK: DW_TAG_compile_unit
|
||||||
|
; CHECK-NOT: DW_TAG_structure_type
|
||||||
|
; This variable's type is in the 1st CU.
|
||||||
|
; CHECK: DW_TAG_variable
|
||||||
|
; Make sure this is relocatable.
|
||||||
|
; CHECK: .quad .Lsection_info+[[TYPE]] # DW_AT_type
|
||||||
|
; CHECK-NOT: DW_TAG_structure_type
|
||||||
|
; CHECK: debug_info_end1
|
||||||
|
|
||||||
|
; CHECK-DWARF: DW_TAG_compile_unit
|
||||||
|
; CHECK-DWARF: 0x[[ADDR:.*]]: DW_TAG_structure_type
|
||||||
|
; CHECK-DWARF: DW_TAG_compile_unit
|
||||||
|
; CHECK-DWARF: DW_TAG_variable
|
||||||
|
; CHECK-DWARF: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[ADDR]])
|
||||||
|
|
||||||
|
; DARWIN-DWARF: DW_TAG_compile_unit
|
||||||
|
; DARWIN-DWARF: 0x[[ADDR:.*]]: DW_TAG_structure_type
|
||||||
|
; DARWIN-DWARF: DW_TAG_compile_unit
|
||||||
|
; DARWIN-DWARF: DW_TAG_variable
|
||||||
|
; DARWIN-DWARF: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[ADDR]])
|
||||||
|
|
||||||
|
%struct.foo = type { i8 }
|
||||||
|
|
||||||
|
@f = global %struct.foo zeroinitializer, align 1
|
||||||
|
@g = global %struct.foo zeroinitializer, align 1
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0, !9}
|
||||||
|
!llvm.module.flags = !{!14}
|
||||||
|
|
||||||
|
!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4 (trunk 191799)", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !2, metadata !6, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/Users/manmanren/test-Nov/type_unique_air/ref_addr/tu1.cpp] [DW_LANG_C_plus_plus]
|
||||||
|
!1 = metadata !{metadata !"tu1.cpp", metadata !"/Users/manmanren/test-Nov/type_unique_air/ref_addr"}
|
||||||
|
!2 = metadata !{i32 0}
|
||||||
|
!3 = metadata !{metadata !4}
|
||||||
|
!4 = metadata !{i32 786451, metadata !5, null, metadata !"foo", i32 1, i64 8, i64 8, i32 0, i32 0, null, metadata !2, i32 0, null, null, metadata !"_ZTS3foo"} ; [ DW_TAG_structure_type ] [foo] [line 1, size 8, align 8, offset 0] [def] [from ]
|
||||||
|
!5 = metadata !{metadata !"./hdr.h", metadata !"/Users/manmanren/test-Nov/type_unique_air/ref_addr"}
|
||||||
|
!6 = metadata !{metadata !7}
|
||||||
|
!7 = metadata !{i32 786484, i32 0, null, metadata !"f", metadata !"f", metadata !"", metadata !8, i32 2, metadata !4, i32 0, i32 1, %struct.foo* @f, null} ; [ DW_TAG_variable ] [f] [line 2] [def]
|
||||||
|
!8 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/Users/manmanren/test-Nov/type_unique_air/ref_addr/tu1.cpp]
|
||||||
|
!9 = metadata !{i32 786449, metadata !10, i32 4, metadata !"clang version 3.4 (trunk 191799)", i1 false, metadata !"", i32 0, metadata !2, metadata !3, metadata !2, metadata !11, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/Users/manmanren/test-Nov/type_unique_air/ref_addr/tu2.cpp] [DW_LANG_C_plus_plus]
|
||||||
|
!10 = metadata !{metadata !"tu2.cpp", metadata !"/Users/manmanren/test-Nov/type_unique_air/ref_addr"}
|
||||||
|
!11 = metadata !{metadata !12}
|
||||||
|
!12 = metadata !{i32 786484, i32 0, null, metadata !"g", metadata !"g", metadata !"", metadata !13, i32 2, metadata !4, i32 0, i32 1, %struct.foo* @g, null} ; [ DW_TAG_variable ] [g] [line 2] [def]
|
||||||
|
!13 = metadata !{i32 786473, metadata !10} ; [ DW_TAG_file_type ] [/Users/manmanren/test-Nov/type_unique_air/ref_addr/tu2.cpp]
|
||||||
|
!14 = metadata !{i32 2, metadata !"Dwarf Version", i32 2}
|
|
@ -1,14 +1,18 @@
|
||||||
; CHECK: 0x[[INT:.*]]: DW_TAG_base_type
|
; Make sure the backend generates a single DIE and uses ref_addr.
|
||||||
; CHECK-NEXT: DW_AT_name {{.*}} = "int"
|
|
||||||
; CHECK-NOT: DW_TAG_base_type
|
|
||||||
; CHECK: 0x[[BASE:.*]]: DW_TAG_structure_type
|
; CHECK: 0x[[BASE:.*]]: DW_TAG_structure_type
|
||||||
; CHECK-NEXT: DW_AT_name {{.*}} = "Base"
|
; CHECK-NEXT: DW_AT_name {{.*}} = "Base"
|
||||||
; CHECK-NOT: DW_TAG_structure_type
|
; CHECK-NOT: DW_TAG_structure_type
|
||||||
|
; CHECK: 0x[[INT:.*]]: DW_TAG_base_type
|
||||||
|
; CHECK-NEXT: DW_AT_name {{.*}} = "int"
|
||||||
|
; CHECK-NOT: DW_TAG_base_type
|
||||||
|
|
||||||
|
; CHECK: DW_TAG_compile_unit
|
||||||
; CHECK: DW_TAG_formal_parameter
|
; CHECK: DW_TAG_formal_parameter
|
||||||
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[INT]])
|
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[INT]])
|
||||||
; CHECK: DW_TAG_variable
|
; CHECK: DW_TAG_variable
|
||||||
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[BASE]])
|
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[BASE]])
|
||||||
|
|
||||||
|
; Make sure llvm-link only generates a single copy of the struct.
|
||||||
; LINK: DW_TAG_structure_type
|
; LINK: DW_TAG_structure_type
|
||||||
; LINK-NOT: DW_TAG_structure_type
|
; LINK-NOT: DW_TAG_structure_type
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o - | FileCheck %s
|
; REQUIRES: object-emission
|
||||||
|
|
||||||
; CHECK: DW_TAG_structure_type
|
; RUN: llvm-link %s %p/type-unique-simple-b.ll -S -o %t
|
||||||
|
; RUN: cat %t | FileCheck %s -check-prefix=LINK
|
||||||
|
; RUN: llc -filetype=obj -O0 < %t > %t2
|
||||||
|
; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %s
|
||||||
|
|
||||||
|
; Make sure the backend generates a single DIE and uses ref_addr.
|
||||||
|
; CHECK: 0x[[BASE:.*]]: DW_TAG_structure_type
|
||||||
|
; CHECK-NEXT: DW_AT_name {{.*}} = "Base"
|
||||||
; CHECK-NOT: DW_TAG_structure_type
|
; CHECK-NOT: DW_TAG_structure_type
|
||||||
|
; CHECK: 0x[[INT:.*]]: DW_TAG_base_type
|
||||||
|
; CHECK-NEXT: DW_AT_name {{.*}} = "int"
|
||||||
|
; CHECK-NOT: DW_TAG_base_type
|
||||||
|
|
||||||
|
; CHECK: DW_TAG_compile_unit
|
||||||
|
; CHECK: DW_TAG_formal_parameter
|
||||||
|
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[INT]])
|
||||||
|
; CHECK: DW_TAG_variable
|
||||||
|
; CHECK: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[BASE]])
|
||||||
|
|
||||||
|
; Make sure llvm-link only generates a single copy of the struct.
|
||||||
|
; LINK: DW_TAG_structure_type
|
||||||
|
; LINK-NOT: DW_TAG_structure_type
|
||||||
; Content of header files:
|
; Content of header files:
|
||||||
; struct Base {
|
; struct Base {
|
||||||
; int a;
|
; int a;
|
||||||
|
|
|
@ -2,3 +2,5 @@
|
||||||
|
|
||||||
; RUN: llvm-link %S/Inputs/type-unique-simple2-a.ll %S/Inputs/type-unique-simple2-b.ll -S -o %t
|
; RUN: llvm-link %S/Inputs/type-unique-simple2-a.ll %S/Inputs/type-unique-simple2-b.ll -S -o %t
|
||||||
; RUN: cat %t | FileCheck %S/Inputs/type-unique-simple2-a.ll -check-prefix=LINK
|
; RUN: cat %t | FileCheck %S/Inputs/type-unique-simple2-a.ll -check-prefix=LINK
|
||||||
|
; RUN: llc -filetype=obj -O0 < %t > %t2
|
||||||
|
; RUN: llvm-dwarfdump -debug-dump=info %t2 | FileCheck %S/Inputs/type-unique-simple2-a.ll
|
||||||
|
|
Loading…
Reference in New Issue