mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
Revert "[dsymutil] Don't mark forward declarations as canonical."
This reverts commit r312264. llvm-svn: 312271
This commit is contained in:
parent
149ba0c692
commit
f8170dbc97
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,127 +0,0 @@
|
||||
/* Compile with:
|
||||
for FILE in `seq 3`; do
|
||||
clang -g -c X86/odr-fwd-declaration.cpp -DFILE$FILE -o Inputs/odr-fwd-declaration/$FILE.o
|
||||
done
|
||||
*/
|
||||
|
||||
// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-fwd-declaration -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
|
||||
|
||||
#ifdef FILE1
|
||||
# 1 "Header.h" 1
|
||||
typedef struct S *Sptr;
|
||||
typedef Sptr *Sptrptr;
|
||||
# 3 "Source1.cpp" 2
|
||||
void foo() {
|
||||
Sptrptr ptr1 = 0;
|
||||
}
|
||||
|
||||
// First we confirm that the typedefs reference the forward declaration of the
|
||||
// struct S.
|
||||
//
|
||||
// CHECK: TAG_variable
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "ptr1"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF1:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[TYPEDEF1]]:{{.*}}TAG_typedef
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR1:[a-f0-9]*]]
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "Sptrptr"
|
||||
//
|
||||
// CHECK: [[PTR1]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF2:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[TYPEDEF2]]:{{.*}}TAG_typedef
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR2:[a-f0-9]*]]
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "Sptr"
|
||||
//
|
||||
// CHECK: [[PTR2]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[FWDSTRUCT:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[FWDSTRUCT]]:{{.*}}TAG_structure_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "S"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_declaration
|
||||
// CHECK-NOT AT_byte_size
|
||||
|
||||
#elif defined(FILE2)
|
||||
# 1 "Header.h" 1
|
||||
typedef struct S *Sptr;
|
||||
typedef Sptr *Sptrptr;
|
||||
# 3 "Source2.cpp" 2
|
||||
struct S {
|
||||
int field;
|
||||
};
|
||||
void bar() {
|
||||
Sptrptr ptr2 = 0;
|
||||
}
|
||||
|
||||
// Next we confirm that the typedefs reference the definition rather than the
|
||||
// previous declaration of S.
|
||||
//
|
||||
// CHECK: TAG_variable
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "ptr2"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF3:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[TYPEDEF3]]:{{.*}}TAG_typedef
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR3:[a-f0-9]*]]
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "Sptrptr"
|
||||
//
|
||||
// CHECK: [[PTR3]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF4:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[TYPEDEF4]]:{{.*}}TAG_typedef
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR4:[a-f0-9]*]]
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "Sptr"
|
||||
//
|
||||
// CHECK: [[PTR4]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[STRUCT]]:{{.*}}TAG_structure_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "S"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK-NOT: AT_declaration
|
||||
// CHECK: AT_byte_size
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: TAG_member
|
||||
|
||||
#elif defined(FILE3)
|
||||
# 1 "Header.h" 1
|
||||
typedef struct S *Sptr;
|
||||
typedef Sptr *Sptrptr;
|
||||
# 3 "Source1.cpp" 2
|
||||
void foo() {
|
||||
Sptrptr ptr1 = 0;
|
||||
}
|
||||
|
||||
// Finally we confirm that uniquing is not broken and the same typedef is
|
||||
// referenced by ptr1.
|
||||
//
|
||||
// CHECK: TAG_variable
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "ptr1"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF3]]
|
||||
// CHECK-NOT: TAG_typedef
|
||||
// CHECK-NOT: TAG_pointer
|
||||
// CHECK-NOT: TAG_structure_type
|
||||
|
||||
#else
|
||||
#error "You must define which file you generate"
|
||||
#endif
|
@ -1,151 +0,0 @@
|
||||
/* Compile with:
|
||||
for FILE in `seq 3`; do
|
||||
clang -g -c X86/odr-fwd-declaration2.cpp -DFILE$FILE -o Inputs/odr-fwd-declaration2/$FILE.o
|
||||
done
|
||||
*/
|
||||
|
||||
// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-fwd-declaration2 -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
|
||||
|
||||
#ifdef FILE1
|
||||
# 1 "Header.h" 1
|
||||
struct A {
|
||||
struct B;
|
||||
B *bPtr;
|
||||
B &bRef;
|
||||
int B::*bPtrToField;
|
||||
};
|
||||
# 3 "Source1.cpp" 2
|
||||
void foo() {
|
||||
A *ptr1 = 0;
|
||||
}
|
||||
|
||||
// First we confirm that bPtr, bRef and bPtrToField reference the forward
|
||||
// declaration of the struct B.
|
||||
//
|
||||
// CHECK: DW_TAG_member
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "bPtr"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR1:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[STRUCT1:[a-f0-9]*]]:{{.*}}TAG_structure_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "B"
|
||||
// CHECK-NOT: AT_byte_size
|
||||
// CHECK: DW_AT_declaration
|
||||
//
|
||||
// CHECK: DW_TAG_member
|
||||
// CHECK: AT_name{{.*}} "bRef"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[REF1:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: TAG_member
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "bPtrToField"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER1:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[PTR1]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]]
|
||||
//
|
||||
// CHECK: [[REF1]]:{{.*}}TAG_reference_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]]
|
||||
//
|
||||
// CHECK: [[PTRTOMEMBER1]]:{{.*}}TAG_ptr_to_member_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT1]]
|
||||
|
||||
#elif defined(FILE2)
|
||||
# 1 "Header.h" 1
|
||||
struct A {
|
||||
struct B;
|
||||
B *bPtr;
|
||||
B &bRef;
|
||||
int B::*bPtrToField;
|
||||
};
|
||||
# 3 "Source2.cpp" 2
|
||||
struct A::B {
|
||||
int x;
|
||||
};
|
||||
void bar() {
|
||||
A *ptr2 = 0;
|
||||
}
|
||||
|
||||
// Next we confirm that bPtr, bRef and bPtrToField reference the definition of
|
||||
// B, rather than its declaration.
|
||||
//
|
||||
// CHECK: [[STRUCTA:[a-f0-9]*]]:{{.*}}TAG_structure_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "A"
|
||||
// CHECK-NOT: AT_byte_size
|
||||
// CHECK: DW_AT_byte_size
|
||||
//
|
||||
// CHECK: DW_TAG_member
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "bPtr"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR2:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[STRUCT2:[a-f0-9]*]]:{{.*}}TAG_structure_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "B"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: DW_AT_byte_size
|
||||
//
|
||||
// CHECK: DW_TAG_member
|
||||
// CHECK: AT_name{{.*}} "bRef"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[REF2:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: TAG_member
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "bPtrToField"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER2:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[PTR2]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]]
|
||||
//
|
||||
// CHECK: [[REF2]]:{{.*}}TAG_reference_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]]
|
||||
//
|
||||
// CHECK: [[PTRTOMEMBER2]]:{{.*}}TAG_ptr_to_member_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT2:[a-f0-9]*]]
|
||||
|
||||
#elif defined(FILE3)
|
||||
# 1 "Header.h" 1
|
||||
struct A {
|
||||
struct B;
|
||||
B *bPtr;
|
||||
B &bRef;
|
||||
int B::*bPtrToField;
|
||||
};
|
||||
# 3 "Source2.cpp" 2
|
||||
struct A::B {
|
||||
int x;
|
||||
};
|
||||
void bar() {
|
||||
A *ptr2 = 0;
|
||||
}
|
||||
|
||||
// Finally we confirm that uniquing isn't broken by checking that further
|
||||
// references to 'struct A' point to its now complete definition.
|
||||
//
|
||||
// CHECK: TAG_variable
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_name{{.*}} "ptr2"
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[PTR3:[a-f0-9]*]]
|
||||
//
|
||||
// CHECK: [[PTR3]]:{{.*}}TAG_pointer_type
|
||||
// CHECK-NOT: {{DW_TAG|NULL}}
|
||||
// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCTA]]
|
||||
|
||||
#else
|
||||
#error "You must define which file you generate"
|
||||
#endif
|
@ -185,14 +185,13 @@ class CompileUnit {
|
||||
public:
|
||||
/// Information gathered about a DIE in the object file.
|
||||
struct DIEInfo {
|
||||
int64_t AddrAdjust; ///< Address offset to apply to the described entity.
|
||||
DeclContext *Ctxt; ///< ODR Declaration context.
|
||||
DIE *Clone; ///< Cloned version of that DIE.
|
||||
uint32_t ParentIdx; ///< The index of this DIE's parent.
|
||||
bool Keep : 1; ///< Is the DIE part of the linked output?
|
||||
bool InDebugMap : 1; ///< Was this DIE's entity found in the map?
|
||||
bool Prune : 1; ///< Is this a pure forward declaration we can strip?
|
||||
bool Incomplete : 1; ///< Does DIE transitively refer an incomplete decl?
|
||||
int64_t AddrAdjust; ///< Address offset to apply to the described entity.
|
||||
DeclContext *Ctxt; ///< ODR Declaration context.
|
||||
DIE *Clone; ///< Cloned version of that DIE.
|
||||
uint32_t ParentIdx; ///< The index of this DIE's parent.
|
||||
bool Keep : 1; ///< Is the DIE part of the linked output?
|
||||
bool InDebugMap : 1;///< Was this DIE's entity found in the map?
|
||||
bool Prune : 1; ///< Is this a pure forward declaration we can strip?
|
||||
};
|
||||
|
||||
CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
|
||||
@ -1199,9 +1198,8 @@ private:
|
||||
/// @{
|
||||
/// Recursively walk the \p DIE tree and look for DIEs to
|
||||
/// keep. Store that information in \p CU's DIEInfo.
|
||||
///
|
||||
/// The return value indicates whether the DIE is incomplete.
|
||||
bool lookForDIEsToKeep(RelocationManager &RelocMgr, const DWARFDie &DIE,
|
||||
void lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
const DWARFDie &DIE,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
unsigned Flags);
|
||||
|
||||
@ -2198,11 +2196,6 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
|
||||
DWARFUnit &Unit = CU.getOrigUnit();
|
||||
MyInfo.Keep = true;
|
||||
|
||||
// We're looking for incomplete types.
|
||||
MyInfo.Incomplete = Die.getTag() != dwarf::DW_TAG_subprogram &&
|
||||
Die.getTag() != dwarf::DW_TAG_member &&
|
||||
dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0);
|
||||
|
||||
// First mark all the parent chain as kept.
|
||||
unsigned AncestorIdx = MyInfo.ParentIdx;
|
||||
while (!CU.getInfo(AncestorIdx).Keep) {
|
||||
@ -2218,7 +2211,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
|
||||
const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
|
||||
uint32_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode());
|
||||
|
||||
// Mark all DIEs referenced through attributes as kept.
|
||||
// Mark all DIEs referenced through atttributes as kept.
|
||||
for (const auto &AttrSpec : Abbrev->attributes()) {
|
||||
DWARFFormValue Val(AttrSpec.Form);
|
||||
|
||||
@ -2258,16 +2251,6 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
|
||||
unsigned ODRFlag = UseODR ? TF_ODR : 0;
|
||||
lookForDIEsToKeep(RelocMgr, RefDie, DMO, *ReferencedCU,
|
||||
TF_Keep | TF_DependencyWalk | ODRFlag);
|
||||
|
||||
// The incomplete property is propagated if the current DIE is complete
|
||||
// but references an incomplete DIE.
|
||||
if (Info.Incomplete && !MyInfo.Incomplete &&
|
||||
(Die.getTag() == dwarf::DW_TAG_typedef ||
|
||||
Die.getTag() == dwarf::DW_TAG_member ||
|
||||
Die.getTag() == dwarf::DW_TAG_reference_type ||
|
||||
Die.getTag() == dwarf::DW_TAG_ptr_to_member_type ||
|
||||
Die.getTag() == dwarf::DW_TAG_pointer_type))
|
||||
MyInfo.Incomplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2284,9 +2267,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
|
||||
/// also called, but during these dependency walks the file order is
|
||||
/// not respected. The TF_DependencyWalk flag tells us which kind of
|
||||
/// traversal we are currently doing.
|
||||
///
|
||||
/// The return value indicates whether the DIE is incomplete.
|
||||
bool DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
const DWARFDie &Die,
|
||||
const DebugMapObject &DMO, CompileUnit &CU,
|
||||
unsigned Flags) {
|
||||
@ -2294,13 +2275,13 @@ bool DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx);
|
||||
bool AlreadyKept = MyInfo.Keep;
|
||||
if (MyInfo.Prune)
|
||||
return true;
|
||||
return;
|
||||
|
||||
// If the Keep flag is set, we are marking a required DIE's
|
||||
// dependencies. If our target is already marked as kept, we're all
|
||||
// set.
|
||||
if ((Flags & TF_DependencyWalk) && AlreadyKept)
|
||||
return MyInfo.Incomplete;
|
||||
return;
|
||||
|
||||
// We must not call shouldKeepDIE while called from keepDIEAndDependencies,
|
||||
// because it would screw up the relocation finding logic.
|
||||
@ -2322,19 +2303,10 @@ bool DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
|
||||
Flags &= ~TF_ParentWalk;
|
||||
|
||||
if (!Die.hasChildren() || (Flags & TF_ParentWalk))
|
||||
return MyInfo.Incomplete;
|
||||
return;
|
||||
|
||||
bool Incomplete = false;
|
||||
for (auto Child : Die.children()) {
|
||||
Incomplete |= lookForDIEsToKeep(RelocMgr, Child, DMO, CU, Flags);
|
||||
|
||||
// If any of the members are incomplete we propagate the incompleteness.
|
||||
if (!MyInfo.Incomplete && Incomplete &&
|
||||
(Die.getTag() == dwarf::DW_TAG_structure_type ||
|
||||
Die.getTag() == dwarf::DW_TAG_class_type))
|
||||
MyInfo.Incomplete = true;
|
||||
}
|
||||
return MyInfo.Incomplete;
|
||||
for (auto Child: Die.children())
|
||||
lookForDIEsToKeep(RelocMgr, Child, DMO, CU, Flags);
|
||||
}
|
||||
|
||||
/// Assign an abbreviation numer to \p Abbrev.
|
||||
@ -2744,7 +2716,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
|
||||
|
||||
assert(Die->getTag() == InputDIE.getTag());
|
||||
Die->setOffset(OutOffset);
|
||||
if ((Unit.hasODR() || Unit.isClangModule()) && !Info.Incomplete &&
|
||||
if ((Unit.hasODR() || Unit.isClangModule()) &&
|
||||
Die->getTag() != dwarf::DW_TAG_namespace && Info.Ctxt &&
|
||||
Info.Ctxt != Unit.getInfo(Info.ParentIdx).Ctxt &&
|
||||
!Info.Ctxt->getCanonicalDIEOffset()) {
|
||||
|
Loading…
Reference in New Issue
Block a user