diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 031ca18d748..c1b60f011fd 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -624,6 +624,7 @@ private: std::vector IndirectSymbols; + unsigned RelaxAll : 1; unsigned SubsectionsViaSymbols : 1; private: @@ -727,6 +728,9 @@ public: SubsectionsViaSymbols = Value; } + bool getRelaxAll() const { return RelaxAll; } + void setRelaxAll(bool Value) { RelaxAll = Value; } + /// @name Section List Access /// @{ diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index ce67b3aebfd..bdcfdb2debe 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -308,7 +308,8 @@ class TargetAsmBackend; /// createMachOStream - Create a machine code streamer which will generative /// Mach-O format object files. MCStreamer *createMachOStreamer(MCContext &Ctx, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE); + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll = false); } // end namespace llvm diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 79a8436bc24..03b8bd340b4 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -19,9 +19,9 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Debug.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Target/TargetAsmBackend.h" @@ -30,11 +30,13 @@ using namespace llvm; namespace { namespace stats { -STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); -STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); STATISTIC(EmittedFragments, "Number of emitted assembler fragments"); STATISTIC(EvaluateFixup, "Number of evaluated fixups"); +STATISTIC(FragmentLayouts, "Number of fragment layouts"); STATISTIC(ObjectBytes, "Number of emitted object file bytes"); +STATISTIC(RelaxationSteps, "Number of assembler layout and relaxation steps"); +STATISTIC(RelaxedInstructions, "Number of relaxed instructions"); +STATISTIC(SectionLayouts, "Number of section layouts"); } } @@ -185,7 +187,7 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, MCAssembler::MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, MCCodeEmitter &_Emitter, raw_ostream &_OS) : Context(_Context), Backend(_Backend), Emitter(_Emitter), - OS(_OS), SubsectionsViaSymbols(false) + OS(_OS), RelaxAll(false), SubsectionsViaSymbols(false) { } @@ -402,6 +404,8 @@ uint64_t MCAssembler::LayoutSection(MCSectionData &SD, uint64_t StartAddress) { bool IsVirtual = getBackend().isVirtualSection(SD.getSection()); + ++stats::SectionLayouts; + // Align this section if necessary by adding padding bytes to the previous // section. It is safe to adjust this out-of-band, because no symbol or // fragment is allowed to point past the end of the section at any time. @@ -426,6 +430,8 @@ uint64_t MCAssembler::LayoutSection(MCSectionData &SD, for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) { MCFragment &F = *it; + ++stats::FragmentLayouts; + uint64_t FragmentOffset = Address - StartAddress; Layout.setFragmentOffset(&F, FragmentOffset); @@ -699,6 +705,9 @@ void MCAssembler::Finish() { bool MCAssembler::FixupNeedsRelaxation(const MCAsmFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const { + if (getRelaxAll()) + return true; + // If we cannot resolve the fixup value, it requires relaxation. MCValue Target; uint64_t Value; @@ -791,8 +800,11 @@ bool MCAssembler::LayoutOnce(MCAsmLayout &Layout) { F.getKind())); } - // Update the layout, and remember that we relaxed. - Layout.UpdateForSlide(IF, SlideAmount); + // Update the layout, and remember that we relaxed. If we are relaxing + // everything, we can skip this step since nothing will depend on updating + // the values. + if (!getRelaxAll()) + Layout.UpdateForSlide(IF, SlideAmount); WasRelaxed = true; } } diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 9141a903dd9..120f837b26f 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -75,6 +75,8 @@ public: CurSectionData(0) {} ~MCMachOStreamer() {} + MCAssembler &getAssembler() { return Assembler; } + const MCExpr *AddValueSymbols(const MCExpr *Value) { switch (Value->getKind()) { case MCExpr::Target: assert(0 && "Can't handle target exprs yet!"); @@ -433,6 +435,10 @@ void MCMachOStreamer::Finish() { } MCStreamer *llvm::createMachOStreamer(MCContext &Context, TargetAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE) { - return new MCMachOStreamer(Context, TAB, OS, CE); + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll) { + MCMachOStreamer *S = new MCMachOStreamer(Context, TAB, OS, CE); + if (RelaxAll) + S->getAssembler().setRelaxAll(true); + return S; } diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 0e183b05045..6dce5cc96c7 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -55,6 +55,9 @@ static cl::opt OutputAsmVariant("output-asm-variant", cl::desc("Syntax variant to use for output printing")); +static cl::opt +RelaxAll("mc-relax-all", cl::desc("Relax all fixups")); + enum OutputFileType { OFT_Null, OFT_AssemblyFile, @@ -298,7 +301,7 @@ static int AssembleInput(const char *ProgName) { assert(FileType == OFT_ObjectFile && "Invalid file type!"); CE.reset(TheTarget->createCodeEmitter(*TM, Ctx)); TAB.reset(TheTarget->createAsmBackend(TripleName)); - Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get())); + Str.reset(createMachOStreamer(Ctx, *TAB, *Out, CE.get(), RelaxAll)); } AsmParser Parser(SrcMgr, Ctx, *Str.get(), *MAI);