mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-18 13:34:04 +00:00
[dsymutil] Support cloning DIE reference attributes.
Reference attributes are mainly handled by just creating DIEEntry attributes for them. There is a special case for DW_FORM_ref_addr attributes though, because the DIEEntry code needs a DwarfDebug code to emit them (and we don't have one as we do no CodeGen). In that case, just use DIEInteger attributes with the right form. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231531 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1edd6edd60
commit
fe78287585
@ -21,17 +21,20 @@ CHECK: DW_TAG_subprogram [2] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
|
||||
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
|
||||
CHECK: DW_AT_prototyped [DW_FORM_flag] (0x01)
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
|
||||
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
|
||||
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 78 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005b] = "argv")
|
||||
CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01)
|
||||
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x006a => {0x0000006a})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 70 )
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_base_type [4]
|
||||
@ -39,8 +42,11 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
|
||||
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
|
||||
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x04)
|
||||
CHECK: DW_TAG_pointer_type [5]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x006f => {0x0000006f})
|
||||
CHECK: DW_TAG_pointer_type [5]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0074 => {0x00000074})
|
||||
CHECK: DW_TAG_const_type [6]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0079 => {0x00000079})
|
||||
CHECK: DW_TAG_base_type [4]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000064] = "char")
|
||||
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed_char)
|
||||
@ -57,17 +63,22 @@ CHECK: DW_TAG_base_type [4]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
|
||||
CHECK: DW_TAG_variable [7]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
|
||||
CHECK: DW_TAG_variable [7]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007e] = "baz")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
|
||||
CHECK: DW_TAG_subprogram [2] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 7c )
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_subprogram [8]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0026 => {0x000000a7})
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: NULL
|
||||
|
||||
@ -79,18 +90,23 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
|
||||
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
|
||||
CHECK: DW_TAG_variable [9]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000162})
|
||||
CHECK: DW_TAG_volatile_type [10]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
|
||||
CHECK: DW_TAG_base_type [4]
|
||||
CHACK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
|
||||
CHECK: DW_TAG_subprogram [2] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x02> 91 78 )
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_subprogram [8]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0041 => {0x00000167})
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
|
||||
CHECK: NULL
|
||||
|
@ -15,14 +15,17 @@ CHECK: DW_TAG_subprogram [2] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000051] = "main")
|
||||
CHECK: DW_AT_decl_line [DW_FORM_data1] (23)
|
||||
CHECK: DW_AT_prototyped [DW_FORM_flag] (0x01)
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
CHECK: DW_AT_external [DW_FORM_flag] (0x01)
|
||||
CHECK: DW_AT_accessibility [DW_FORM_data1] (DW_ACCESS_public)
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000056] = "argc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0063 => {0x00000063})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x03> 55 93 04 )
|
||||
CHECK: DW_TAG_formal_parameter [3]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000005b] = "argv")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x006a => {0x0000006a})
|
||||
CHECK: DW_AT_location [DW_FORM_block1] (<0x01> 54 )
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_base_type [4]
|
||||
@ -30,8 +33,11 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000060] = "int")
|
||||
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed)
|
||||
CHECK: DW_AT_byte_size [DW_FORM_data1] (0x04)
|
||||
CHECK: DW_TAG_pointer_type [5]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x006f => {0x0000006f})
|
||||
CHECK: DW_TAG_pointer_type [5]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0074 => {0x00000074})
|
||||
CHECK: DW_TAG_const_type [6]
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x0079 => {0x00000079})
|
||||
CHECK: DW_TAG_base_type [4]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000064] = "char")
|
||||
CHECK: DW_AT_encoding [DW_FORM_data1] (DW_ATE_signed_char)
|
||||
@ -46,18 +52,24 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000069] = "basic2.c")
|
||||
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
|
||||
CHECK: DW_TAG_variable [7]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000072] = "private_int")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_TAG_variable [7]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000007e] = "baz")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_TAG_subprogram [8] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000082] = "foo")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [9]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_TAG_inlined_subroutine [10]
|
||||
CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x00a7 => {0x00000128} "inc")
|
||||
CHECK: DW_AT_call_line [DW_FORM_data1] (20)
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_subprogram [11]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_AT_inline [DW_FORM_data1] (DW_INL_inlined)
|
||||
CHECK: NULL
|
||||
|
||||
@ -69,16 +81,23 @@ CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008e] = "basic3.c")
|
||||
CHECK: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000049] = "/Inputs")
|
||||
CHECK: DW_TAG_variable [12]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000097] = "val")
|
||||
CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x003c => {0x00000176})
|
||||
CHECK: DW_TAG_volatile_type [13]
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_TAG_subprogram [8] *
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000009b] = "bar")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_AT_frame_base [DW_FORM_block1] (<0x01> 56 )
|
||||
CHECK: DW_TAG_formal_parameter [9]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000086] = "arg")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: DW_TAG_lexical_block [14] *
|
||||
CHECK: DW_TAG_inlined_subroutine [15]
|
||||
CHECK: DW_AT_abstract_origin [DW_FORM_ref4] (cu + 0x009a => {0x000001d4} "inc")
|
||||
|
||||
CHECK: NULL
|
||||
CHECK: NULL
|
||||
CHECK: DW_TAG_subprogram [11]
|
||||
CHECK: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000008a] = "inc")
|
||||
CHECK: DW_AT_type [DW_FORM_ref_addr] (0x0000000000000063)
|
||||
CHECK: NULL
|
||||
|
@ -55,6 +55,7 @@ public:
|
||||
/// \brief Information gathered about a DIE in the object file.
|
||||
struct DIEInfo {
|
||||
uint64_t Address; ///< Linked address of the described entity.
|
||||
DIE *Clone; ///< Cloned version of that DIE.
|
||||
uint32_t ParentIdx; ///< The index of this DIE's parent.
|
||||
bool Keep; ///< Is the DIE part of the linked output?
|
||||
bool InDebugMap; ///< Was this DIE's entity found in the map?
|
||||
@ -89,6 +90,14 @@ public:
|
||||
/// debug_info section size).
|
||||
uint64_t computeNextUnitOffset();
|
||||
|
||||
/// \brief Keep track of a forward reference to DIE \p Die by
|
||||
/// \p Attr. The attribute should be fixed up later to point to the
|
||||
/// absolute offset of \p Die in the debug_info section.
|
||||
void noteForwardReference(DIE *Die, DIEInteger *Attr);
|
||||
|
||||
/// \brief Apply all fixups recored by noteForwardReference().
|
||||
void fixupForwardReferences();
|
||||
|
||||
private:
|
||||
DWARFUnit &OrigUnit;
|
||||
std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
|
||||
@ -96,6 +105,14 @@ private:
|
||||
|
||||
uint64_t StartOffset;
|
||||
uint64_t NextUnitOffset;
|
||||
|
||||
/// \brief A list of attributes to fixup with the absolute offset of
|
||||
/// a DIE in the debug_info section.
|
||||
///
|
||||
/// The offsets for the attributes in this array couldn't be set while
|
||||
/// cloning because for forward refences the target DIE's offset isn't
|
||||
/// known you emit the reference attribute.
|
||||
std::vector<std::pair<DIE *, DIEInteger *>> ForwardDIEReferences;
|
||||
};
|
||||
|
||||
uint64_t CompileUnit::computeNextUnitOffset() {
|
||||
@ -108,6 +125,17 @@ uint64_t CompileUnit::computeNextUnitOffset() {
|
||||
return NextUnitOffset;
|
||||
}
|
||||
|
||||
/// \brief Keep track of a forward reference to \p Die.
|
||||
void CompileUnit::noteForwardReference(DIE *Die, DIEInteger *Attr) {
|
||||
ForwardDIEReferences.emplace_back(Die, Attr);
|
||||
}
|
||||
|
||||
/// \brief Apply all fixups recorded by noteForwardReference().
|
||||
void CompileUnit::fixupForwardReferences() {
|
||||
for (const auto &Ref : ForwardDIEReferences)
|
||||
Ref.second->setValue(Ref.first->getOffset() + getStartOffset());
|
||||
}
|
||||
|
||||
/// \brief A string table that doesn't need relocations.
|
||||
///
|
||||
/// We are doing a final link, no need for a string table that
|
||||
@ -518,8 +546,11 @@ private:
|
||||
const DWARFFormValue &Val, const DWARFUnit &U);
|
||||
|
||||
/// \brief Helper for cloneDIE.
|
||||
unsigned cloneDieReferenceAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
unsigned AttrSize);
|
||||
unsigned
|
||||
cloneDieReferenceAttribute(DIE &Die,
|
||||
const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
AttributeSpec AttrSpec, unsigned AttrSize,
|
||||
const DWARFFormValue &Val, const DWARFUnit &U);
|
||||
|
||||
/// \brief Helper for cloneDIE.
|
||||
unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
@ -1059,12 +1090,60 @@ unsigned DwarfLinker::cloneStringAttribute(DIE &Die, AttributeSpec AttrSpec,
|
||||
/// \brief Clone an attribute referencing another DIE and add
|
||||
/// it to \p Die.
|
||||
/// \returns the size of the new attribute.
|
||||
unsigned DwarfLinker::cloneDieReferenceAttribute(DIE &Die,
|
||||
AttributeSpec AttrSpec,
|
||||
unsigned AttrSize) {
|
||||
// FIXME: Handle DIE references.
|
||||
unsigned DwarfLinker::cloneDieReferenceAttribute(
|
||||
DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val,
|
||||
const DWARFUnit &U) {
|
||||
uint32_t Ref = *Val.getAsReference(&U);
|
||||
DIE *NewRefDie = nullptr;
|
||||
CompileUnit *RefUnit = nullptr;
|
||||
const DWARFDebugInfoEntryMinimal *RefDie = nullptr;
|
||||
|
||||
if (!(RefUnit = getUnitForOffset(Ref)) ||
|
||||
!(RefDie = RefUnit->getOrigUnit().getDIEForOffset(Ref))) {
|
||||
const char *AttributeString = dwarf::AttributeString(AttrSpec.Attr);
|
||||
if (!AttributeString)
|
||||
AttributeString = "DW_AT_???";
|
||||
reportWarning(Twine("Missing DIE for ref in attribute ") + AttributeString +
|
||||
". Dropping.",
|
||||
&U, &InputDIE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned Idx = RefUnit->getOrigUnit().getDIEIndex(RefDie);
|
||||
CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(Idx);
|
||||
if (!RefInfo.Clone) {
|
||||
assert(Ref > InputDIE.getOffset());
|
||||
// We haven't cloned this DIE yet. Just create an empty one and
|
||||
// store it. It'll get really cloned when we process it.
|
||||
RefInfo.Clone = new DIE(dwarf::Tag(RefDie->getTag()));
|
||||
}
|
||||
NewRefDie = RefInfo.Clone;
|
||||
|
||||
if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) {
|
||||
// We cannot currently rely on a DIEEntry to emit ref_addr
|
||||
// references, because the implementation calls back to DwarfDebug
|
||||
// to find the unit offset. (We don't have a DwarfDebug)
|
||||
// FIXME: we should be able to design DIEEntry reliance on
|
||||
// DwarfDebug away.
|
||||
DIEInteger *Attr;
|
||||
if (Ref < InputDIE.getOffset()) {
|
||||
// We must have already cloned that DIE.
|
||||
uint32_t NewRefOffset =
|
||||
RefUnit->getStartOffset() + NewRefDie->getOffset();
|
||||
Attr = new (DIEAlloc) DIEInteger(NewRefOffset);
|
||||
} else {
|
||||
// A forward reference. Note and fixup later.
|
||||
Attr = new (DIEAlloc) DIEInteger(0xBADDEF);
|
||||
RefUnit->noteForwardReference(NewRefDie, Attr);
|
||||
}
|
||||
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr,
|
||||
Attr);
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
|
||||
new (DIEAlloc) DIEInteger(0));
|
||||
new (DIEAlloc) DIEEntry(*NewRefDie));
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
@ -1150,7 +1229,8 @@ unsigned DwarfLinker::cloneAttribute(DIE &Die,
|
||||
case dwarf::DW_FORM_ref2:
|
||||
case dwarf::DW_FORM_ref4:
|
||||
case dwarf::DW_FORM_ref8:
|
||||
return cloneDieReferenceAttribute(Die, AttrSpec, AttrSize);
|
||||
return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val,
|
||||
U);
|
||||
case dwarf::DW_FORM_block:
|
||||
case dwarf::DW_FORM_block1:
|
||||
case dwarf::DW_FORM_block2:
|
||||
@ -1187,14 +1267,19 @@ DIE *DwarfLinker::cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE,
|
||||
CompileUnit &Unit, uint32_t OutOffset) {
|
||||
DWARFUnit &U = Unit.getOrigUnit();
|
||||
unsigned Idx = U.getDIEIndex(&InputDIE);
|
||||
CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
|
||||
|
||||
// Should the DIE appear in the output?
|
||||
if (!Unit.getInfo(Idx).Keep)
|
||||
return nullptr;
|
||||
|
||||
uint32_t Offset = InputDIE.getOffset();
|
||||
|
||||
DIE *Die = new DIE(static_cast<dwarf::Tag>(InputDIE.getTag()));
|
||||
// The DIE might have been already created by a forward reference
|
||||
// (see cloneDieReferenceAttribute()).
|
||||
DIE *Die = Info.Clone;
|
||||
if (!Die)
|
||||
Die = Info.Clone = new DIE(dwarf::Tag(InputDIE.getTag()));
|
||||
assert(Die->getTag() == InputDIE.getTag());
|
||||
Die->setOffset(OutOffset);
|
||||
|
||||
// Extract and clone every attribute.
|
||||
@ -1317,6 +1402,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
|
||||
// Emit all the compile unit's debug information.
|
||||
if (!ValidRelocs.empty() && !Options.NoOutput)
|
||||
for (auto &CurrentUnit : Units) {
|
||||
CurrentUnit.fixupForwardReferences();
|
||||
Streamer->emitCompileUnitHeader(CurrentUnit);
|
||||
if (!CurrentUnit.getOutputUnitDIE())
|
||||
continue;
|
||||
|
Loading…
x
Reference in New Issue
Block a user