diff options
-rw-r--r-- | llvm/include/llvm/MC/ELFObjectWriter.h | 5 | ||||
-rw-r--r-- | llvm/include/llvm/MC/MCAssembler.h | 13 | ||||
-rw-r--r-- | llvm/include/llvm/MC/MCObjectWriter.h | 10 | ||||
-rw-r--r-- | llvm/include/llvm/MC/MachObjectWriter.h | 5 | ||||
-rw-r--r-- | llvm/lib/MC/ELFObjectWriter.cpp | 55 | ||||
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 155 | ||||
-rw-r--r-- | llvm/lib/MC/MachObjectWriter.cpp | 118 | ||||
-rw-r--r-- | llvm/lib/MC/WinCOFFObjectWriter.cpp | 12 | ||||
-rw-r--r-- | llvm/test/MC/ELF/relax.s | 38 |
9 files changed, 274 insertions, 137 deletions
diff --git a/llvm/include/llvm/MC/ELFObjectWriter.h b/llvm/include/llvm/MC/ELFObjectWriter.h index e5071066200..c8a42fe57b5 100644 --- a/llvm/include/llvm/MC/ELFObjectWriter.h +++ b/llvm/include/llvm/MC/ELFObjectWriter.h @@ -39,6 +39,11 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; diff --git a/llvm/include/llvm/MC/MCAssembler.h b/llvm/include/llvm/MC/MCAssembler.h index 524f2abae28..8d899d30d21 100644 --- a/llvm/include/llvm/MC/MCAssembler.h +++ b/llvm/include/llvm/MC/MCAssembler.h @@ -621,17 +621,19 @@ private: /// \return Whether the fixup value was fully resolved. This is true if the /// \arg Value result is fixed, otherwise the value may change due to /// relocation. - bool EvaluateFixup(const MCAsmLayout &Layout, + bool EvaluateFixup(const MCObjectWriter &Writer, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, + bool FixupNeedsRelaxation(const MCObjectWriter &Writer, + const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. - bool FragmentNeedsRelaxation(const MCInstFragment *IF, + bool FragmentNeedsRelaxation(const MCObjectWriter &Writer, + const MCInstFragment *IF, const MCAsmLayout &Layout) const; /// Compute the effective fragment size assuming it is layed out at the given @@ -642,7 +644,7 @@ private: /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. - bool LayoutOnce(MCAsmLayout &Layout); + bool LayoutOnce(const MCObjectWriter &Writer, MCAsmLayout &Layout); /// FinishLayout - Finalize a layout, including fragment lowering. void FinishLayout(MCAsmLayout &Layout); @@ -664,7 +666,8 @@ public: void WriteSectionData(const MCSectionData *Section, const MCAsmLayout &Layout, MCObjectWriter *OW) const; - void AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout); + void AddSectionToTheEnd(const MCObjectWriter &Writer, MCSectionData &SD, + MCAsmLayout &Layout); public: /// Construct a new assembler instance. diff --git a/llvm/include/llvm/MC/MCObjectWriter.h b/llvm/include/llvm/MC/MCObjectWriter.h index f1c1cb8a599..7de37f762d3 100644 --- a/llvm/include/llvm/MC/MCObjectWriter.h +++ b/llvm/include/llvm/MC/MCObjectWriter.h @@ -75,6 +75,16 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; + /// Check if a fixup is fully resolved. + /// + /// This routine is used by the assembler to let the file format decide + /// if a fixup is not fully resolved. For example, one that crosses + /// two sections on ELF. + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const = 0; + /// Write the object file. /// /// This routine is called by the assembler after layout and relaxation is diff --git a/llvm/include/llvm/MC/MachObjectWriter.h b/llvm/include/llvm/MC/MachObjectWriter.h index 9b1ff1db847..198da8fc173 100644 --- a/llvm/include/llvm/MC/MachObjectWriter.h +++ b/llvm/include/llvm/MC/MachObjectWriter.h @@ -36,6 +36,11 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index b60271f1b20..94251d76b28 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -274,6 +274,11 @@ namespace { void WriteRelocationsFragment(const MCAssembler &Asm, MCDataFragment *F, const MCSectionData *SD); + bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; @@ -775,7 +780,7 @@ void ELFObjectWriterImpl::WriteRelocation(MCAssembler &Asm, MCAsmLayout &Layout, WriteRelocationsFragment(Asm, F, &SD); - Asm.AddSectionToTheEnd(RelaSD, Layout); + Asm.AddSectionToTheEnd(*Writer, RelaSD, Layout); } } @@ -873,11 +878,11 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm, // Symbol table F = new MCDataFragment(&SymtabSD); WriteSymbolTable(F, Asm, Layout, NumRegularSections); - Asm.AddSectionToTheEnd(SymtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, SymtabSD, Layout); F = new MCDataFragment(&StrtabSD); F->getContents().append(StringTable.begin(), StringTable.end()); - Asm.AddSectionToTheEnd(StrtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, StrtabSD, Layout); F = new MCDataFragment(&ShstrtabSD); @@ -903,7 +908,41 @@ void ELFObjectWriterImpl::CreateMetadataSections(MCAssembler &Asm, F->getContents() += '\x00'; } - Asm.AddSectionToTheEnd(ShstrtabSD, Layout); + Asm.AddSectionToTheEnd(*Writer, ShstrtabSD, Layout); +} + +bool ELFObjectWriterImpl::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + // If this is a PCrel relocation, find the section this fixup value is + // relative to. + const MCSection *BaseSection = 0; + if (IsPCRel) { + BaseSection = &DF->getParent()->getSection(); + assert(BaseSection); + } + + const MCSection *SectionA = 0; + const MCSymbol *SymbolA = 0; + if (const MCSymbolRefExpr *A = Target.getSymA()) { + SymbolA = &A->getSymbol(); + SectionA = &SymbolA->getSection(); + } + + const MCSection *SectionB = 0; + if (const MCSymbolRefExpr *B = Target.getSymB()) { + SectionB = &B->getSymbol().getSection(); + } + + if (!BaseSection) + return SectionA == SectionB; + + const MCSymbolData &DataA = Asm.getSymbolData(*SymbolA); + if (DataA.isExternal()) + return false; + + return !SectionB && BaseSection == SectionA; } void ELFObjectWriterImpl::WriteObject(const MCAssembler &Asm, @@ -1064,6 +1103,14 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, Target, FixedValue); } +bool ELFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return ((ELFObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, + IsPCRel, DF); +} + void ELFObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { ((ELFObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index 506f2a650a1..3d9dcba52d6 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -232,89 +232,6 @@ MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, MCAssembler::~MCAssembler() { } -static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm, - const MCFixup &Fixup, - const MCValue Target, - const MCSection *BaseSection) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr(<base symbol>) + <fixup offset from base symbol> - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0. - // - // The simple (Darwin, except on x86_64) way of dealing with this was to - // assume that any reference to a temporary symbol *must* be a temporary - // symbol in the same atom, unless the sections differ. Therefore, any PCrel - // relocation to a temporary symbol (in the same section) is fully - // resolved. This also works in conjunction with absolutized .set, which - // requires the compiler to use .set to absolutize the differences between - // symbols which the compiler knows to be assembly time constants, so we don't - // need to worry about considering symbol differences fully resolved. - - // Non-relative fixups are only resolved if constant. - if (!BaseSection) - return Target.isAbsolute(); - - // Otherwise, relative fixups are only resolved if not a difference and the - // target is a temporary in the same section. - if (Target.isAbsolute() || Target.getSymB()) - return false; - - const MCSymbol *A = &Target.getSymA()->getSymbol(); - if (!A->isTemporary() || !A->isInSection() || - &A->getSection() != BaseSection) - return false; - - return true; -} - -static bool isScatteredFixupFullyResolved(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFixup &Fixup, - const MCValue Target, - const MCSymbolData *BaseSymbol) { - // The effective fixup address is - // addr(atom(A)) + offset(A) - // - addr(atom(B)) - offset(B) - // - addr(BaseSymbol) + <fixup offset from base symbol> - // and the offsets are not relocatable, so the fixup is fully resolved when - // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0. - // - // Note that "false" is almost always conservatively correct (it means we emit - // a relocation which is unnecessary), except when it would force us to emit a - // relocation which the target cannot encode. - - const MCSymbolData *A_Base = 0, *B_Base = 0; - if (const MCSymbolRefExpr *A = Target.getSymA()) { - // Modified symbol references cannot be resolved. - if (A->getKind() != MCSymbolRefExpr::VK_None) - return false; - - A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); - if (!A_Base) - return false; - } - - if (const MCSymbolRefExpr *B = Target.getSymB()) { - // Modified symbol references cannot be resolved. - if (B->getKind() != MCSymbolRefExpr::VK_None) - return false; - - B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); - if (!B_Base) - return false; - } - - // If there is no base, A and B have to be the same atom for this fixup to be - // fully resolved. - if (!BaseSymbol) - return A_Base == B_Base; - - // Otherwise, B must be missing and A must be the base. - return !B_Base && BaseSymbol == A_Base; -} - bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { // Non-temporary labels should always be visible to the linker. if (!Symbol.isTemporary()) @@ -347,7 +264,8 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { return SD->getFragment()->getAtom(); } -bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, +bool MCAssembler::EvaluateFixup(const MCObjectWriter &Writer, + const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::EvaluateFixup; @@ -377,31 +295,8 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, IsResolved = false; } - // If we are using scattered symbols, determine whether this value is actually - // resolved; scattering may cause atoms to move. - if (IsResolved && getBackend().hasScatteredSymbols()) { - if (getBackend().hasReliableSymbolDifference()) { - // If this is a PCrel relocation, find the base atom (identified by its - // symbol) that the fixup value is relative to. - const MCSymbolData *BaseSymbol = 0; - if (IsPCRel) { - BaseSymbol = DF->getAtom(); - if (!BaseSymbol) - IsResolved = false; - } - - if (IsResolved) - IsResolved = isScatteredFixupFullyResolved(*this, Layout, Fixup, Target, - BaseSymbol); - } else { - const MCSection *BaseSection = 0; - if (IsPCRel) - BaseSection = &DF->getParent()->getSection(); - - IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, Target, - BaseSection); - } - } + if (IsResolved) + IsResolved = Writer.IsFixupFullyResolved(*this, Target, IsPCRel, DF); if (IsPCRel) Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset(); @@ -668,7 +563,8 @@ void MCAssembler::WriteSectionData(const MCSectionData *SD, assert(OW->getStream().tell() - Start == Layout.getSectionFileSize(SD)); } -void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) { +void MCAssembler::AddSectionToTheEnd(const MCObjectWriter &Writer, + MCSectionData &SD, MCAsmLayout &Layout) { // Create dummy fragments and assign section ordinals. unsigned SectionIndex = 0; for (MCAssembler::iterator it = begin(), ie = end(); it != ie; ++it) @@ -697,7 +593,7 @@ void MCAssembler::AddSectionToTheEnd(MCSectionData &SD, MCAsmLayout &Layout) { Layout.LayoutSection(&SD); // Layout until everything fits. - while (LayoutOnce(Layout)) + while (LayoutOnce(Writer, Layout)) continue; } @@ -756,8 +652,17 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { it2->setLayoutOrder(FragmentIndex++); } + llvm::OwningPtr<MCObjectWriter> OwnWriter(0); + if (Writer == 0) { + //no custom Writer_ : create the default one life-managed by OwningPtr + OwnWriter.reset(getBackend().createObjectWriter(OS)); + Writer = OwnWriter.get(); + if (!Writer) + report_fatal_error("unable to create object writer!"); + } + // Layout until everything fits. - while (LayoutOnce(Layout)) + while (LayoutOnce(*Writer, Layout)) continue; DEBUG_WITH_TYPE("mc-dump", { @@ -773,15 +678,6 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { uint64_t StartOffset = OS.tell(); - llvm::OwningPtr<MCObjectWriter> OwnWriter(0); - if (Writer == 0) { - //no custom Writer_ : create the default one life-managed by OwningPtr - OwnWriter.reset(getBackend().createObjectWriter(OS)); - Writer = OwnWriter.get(); - if (!Writer) - report_fatal_error("unable to create object writer!"); - } - // Allow the object writer a chance to perform post-layout binding (for // example, to set the index fields in the symbol data). Writer->ExecutePostLayoutBinding(*this); @@ -801,7 +697,7 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { // Evaluate the fixup. MCValue Target; uint64_t FixedValue; - if (!EvaluateFixup(Layout, Fixup, DF, Target, FixedValue)) { + if (!EvaluateFixup(*Writer, Layout, Fixup, DF, Target, FixedValue)) { // The fixup was unresolved, we need a relocation. Inform the object // writer of the relocation, and give it an opportunity to adjust the // fixup value if need be. @@ -819,7 +715,8 @@ void MCAssembler::Finish(MCObjectWriter *Writer) { stats::ObjectBytes += OS.tell() - StartOffset; } -bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, +bool MCAssembler::FixupNeedsRelaxation(const MCObjectWriter &Writer, + const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const { if (getRelaxAll()) @@ -828,7 +725,7 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, // If we cannot resolve the fixup value, it requires relaxation. MCValue Target; uint64_t Value; - if (!EvaluateFixup(Layout, Fixup, DF, Target, Value)) + if (!EvaluateFixup(Writer, Layout, Fixup, DF, Target, Value)) return true; // Otherwise, relax if the value is too big for a (signed) i8. @@ -837,7 +734,8 @@ bool MCAssembler::FixupNeedsRelaxation(const MCFixup &Fixup, return int64_t(Value) != int64_t(int8_t(Value)); } -bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, +bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer, + const MCInstFragment *IF, const MCAsmLayout &Layout) const { // If this inst doesn't ever need relaxation, ignore it. This occurs when we // are intentionally pushing out inst fragments, or because we relaxed a @@ -847,13 +745,14 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCInstFragment *IF, for (MCInstFragment::const_fixup_iterator it = IF->fixup_begin(), ie = IF->fixup_end(); it != ie; ++it) - if (FixupNeedsRelaxation(*it, IF, Layout)) + if (FixupNeedsRelaxation(Writer, *it, IF, Layout)) return true; return false; } -bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { +bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer, + MCAsmLayout &Layout) { ++stats::RelaxationSteps; // Layout the sections in order. @@ -868,7 +767,7 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { ie2 = SD.end(); it2 != ie2; ++it2) { // Check if this is an instruction fragment that needs relaxation. MCInstFragment *IF = dyn_cast<MCInstFragment>(it2); - if (!IF || !FragmentNeedsRelaxation(IF, Layout)) + if (!IF || !FragmentNeedsRelaxation(Writer, IF, Layout)) continue; ++stats::RelaxedInstructions; diff --git a/llvm/lib/MC/MachObjectWriter.cpp b/llvm/lib/MC/MachObjectWriter.cpp index f81862e9ab1..02a5575606d 100644 --- a/llvm/lib/MC/MachObjectWriter.cpp +++ b/llvm/lib/MC/MachObjectWriter.cpp @@ -75,6 +75,86 @@ static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) { return false; } +static bool isScatteredFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + const MCSymbolData *BaseSymbol) { + // The effective fixup address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // - addr(BaseSymbol) + <fixup offset from base symbol> + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0. + // + // Note that "false" is almost always conservatively correct (it means we emit + // a relocation which is unnecessary), except when it would force us to emit a + // relocation which the target cannot encode. + + const MCSymbolData *A_Base = 0, *B_Base = 0; + if (const MCSymbolRefExpr *A = Target.getSymA()) { + // Modified symbol references cannot be resolved. + if (A->getKind() != MCSymbolRefExpr::VK_None) + return false; + + A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol())); + if (!A_Base) + return false; + } + + if (const MCSymbolRefExpr *B = Target.getSymB()) { + // Modified symbol references cannot be resolved. + if (B->getKind() != MCSymbolRefExpr::VK_None) + return false; + + B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol())); + if (!B_Base) + return false; + } + + // If there is no base, A and B have to be the same atom for this fixup to be + // fully resolved. + if (!BaseSymbol) + return A_Base == B_Base; + + // Otherwise, B must be missing and A must be the base. + return !B_Base && BaseSymbol == A_Base; +} + +static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm, + const MCValue Target, + const MCSection *BaseSection) { + // The effective fixup address is + // addr(atom(A)) + offset(A) + // - addr(atom(B)) - offset(B) + // - addr(<base symbol>) + <fixup offset from base symbol> + // and the offsets are not relocatable, so the fixup is fully resolved when + // addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0. + // + // The simple (Darwin, except on x86_64) way of dealing with this was to + // assume that any reference to a temporary symbol *must* be a temporary + // symbol in the same atom, unless the sections differ. Therefore, any PCrel + // relocation to a temporary symbol (in the same section) is fully + // resolved. This also works in conjunction with absolutized .set, which + // requires the compiler to use .set to absolutize the differences between + // symbols which the compiler knows to be assembly time constants, so we don't + // need to worry about considering symbol differences fully resolved. + + // Non-relative fixups are only resolved if constant. + if (!BaseSection) + return Target.isAbsolute(); + + // Otherwise, relative fixups are only resolved if not a difference and the + // target is a temporary in the same section. + if (Target.isAbsolute() || Target.getSymB()) + return false; + + const MCSymbol *A = &Target.getSymA()->getSymbol(); + if (!A->isTemporary() || !A->isInSection() || + &A->getSection() != BaseSection) + return false; + + return true; +} + namespace { class MachObjectWriterImpl { @@ -1038,6 +1118,36 @@ public: UndefinedSymbolData); } + + bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + // If we are using scattered symbols, determine whether this value is + // actually resolved; scattering may cause atoms to move. + if (Asm.getBackend().hasScatteredSymbols()) { + if (Asm.getBackend().hasReliableSymbolDifference()) { + // If this is a PCrel relocation, find the base atom (identified by its + // symbol) that the fixup value is relative to. + const MCSymbolData *BaseSymbol = 0; + if (IsPCRel) { + BaseSymbol = DF->getAtom(); + if (!BaseSymbol) + return false; + } + + return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol); + } else { + const MCSection *BaseSection = 0; + if (IsPCRel) + BaseSection = &DF->getParent()->getSection(); + + return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection); + } + } + return true; + } + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { unsigned NumSections = Asm.size(); @@ -1224,6 +1334,14 @@ void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, Target, FixedValue); } +bool MachObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return ((MachObjectWriterImpl*) Impl)->IsFixupFullyResolved(Asm, Target, + IsPCRel, DF); +} + void MachObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { ((MachObjectWriterImpl*) Impl)->WriteObject(Asm, Layout); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 6bebe46f96b..1cc5c09a083 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -181,6 +181,11 @@ public: MCValue Target, uint64_t &FixedValue); + virtual bool IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const; + void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); }; } @@ -690,6 +695,13 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, coff_section->Relocations.push_back(Reloc); } +bool WinCOFFObjectWriter::IsFixupFullyResolved(const MCAssembler &Asm, + const MCValue Target, + bool IsPCRel, + const MCFragment *DF) const { + return false; +} + void WinCOFFObjectWriter::WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) { // Assign symbol and section indexes and offsets. diff --git a/llvm/test/MC/ELF/relax.s b/llvm/test/MC/ELF/relax.s new file mode 100644 index 00000000000..5c5e7e30dac --- /dev/null +++ b/llvm/test/MC/ELF/relax.s @@ -0,0 +1,38 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +// Test that we do a relaxation for foo but not for bar. Relaxing foo is +// probably not necessary, but matches what gnu as does. + +// Also test that the relaxation done for foo uses the symbol, not section and +// offset. + +bar: +.globl foo +foo: + jmp bar + jmp foo + +// CHECK: ('sh_name', 1) # '.text' +// CHECK-NEXT: ('sh_type', 1) +// CHECK-NEXT: ('sh_flags', 6) +// CHECK-NEXT: ('sh_addr', 0) +// CHECK-NEXT: ('sh_offset', 64) +// CHECK-NEXT: ('sh_size', 7) +// CHECK-NEXT: ('sh_link', 0) +// CHECK-NEXT: ('sh_info', 0) +// CHECK-NEXT: ('sh_addralign', 4) +// CHECK-NEXT: ('sh_entsize', 0) +// CHECK-NEXT: ('_section_data', 'ebfee900 000000') + +// CHECK: # Symbol 5 +// CHECK-NEXT: (('st_name', 5) # 'foo' + +// CHECK: .rela.text +// CHECK: ('_relocations', [ +// CHECK-NEXT: Relocation 0 +// CHECK-NEXT: (('r_offset', 3) +// CHECK-NEXT: ('r_sym', 5) +// CHECK-NEXT: ('r_type', 2) +// CHECK-NEXT: ('r_addend', -4) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) |