Skip to content

Commit

Permalink
[MC, COFF] Support link /incremental conditionally
Browse files Browse the repository at this point in the history
Today, we always take into account the possibility that object files
produced by MC may be consumed by an incremental linker.  This results
in us initialing fields which vary with time (TimeDateStamp) which harms
hermetic builds (e.g. verifying a self-host went well) and produces
sub-optimal code because we cannot assume anything about the relative
position of functions within a section (call sites can get redirected
through incremental linker thunks).

Let's provide an MCTargetOption which controls this behavior so that we
can disable this functionality if we know a-priori that the build will
not rely on /incremental.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256203 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
majnemer committed Dec 21, 2015
1 parent e7f0062 commit 56afa6e
Show file tree
Hide file tree
Showing 18 changed files with 71 additions and 30 deletions.
8 changes: 8 additions & 0 deletions include/llvm/MC/MCAssembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ class MCAssembler {

unsigned RelaxAll : 1;
unsigned SubsectionsViaSymbols : 1;
unsigned IncrementalLinkerCompatible : 1;

/// ELF specific e_header flags
// It would be good if there were an MCELFAssembler class to hold this.
Expand Down Expand Up @@ -750,6 +751,13 @@ class MCAssembler {
bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; }
void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; }

bool isIncrementalLinkerCompatible() const {
return IncrementalLinkerCompatible;
}
void setIncrementalLinkerCompatible(bool Value) {
IncrementalLinkerCompatible = Value;
}

bool getRelaxAll() const { return RelaxAll; }
void setRelaxAll(bool Value) { RelaxAll = Value; }

Expand Down
2 changes: 2 additions & 0 deletions include/llvm/MC/MCTargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class MCTargetOptions {
bool MCNoWarn : 1;
bool MCSaveTempLabels : 1;
bool MCUseDwarfDirectory : 1;
bool MCIncrementalLinkerCompatible : 1;
bool ShowMCEncoding : 1;
bool ShowMCInst : 1;
bool AsmVerbose : 1;
Expand All @@ -53,6 +54,7 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) {
ARE_EQUAL(MCNoWarn) &&
ARE_EQUAL(MCSaveTempLabels) &&
ARE_EQUAL(MCUseDwarfDirectory) &&
ARE_EQUAL(MCIncrementalLinkerCompatible) &&
ARE_EQUAL(ShowMCEncoding) &&
ARE_EQUAL(ShowMCInst) &&
ARE_EQUAL(AsmVerbose) &&
Expand Down
7 changes: 7 additions & 0 deletions include/llvm/MC/MCTargetOptionsCommandFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ cl::opt<bool> RelaxAll("mc-relax-all",
cl::desc("When used with filetype=obj, "
"relax all fixups in the emitted object file"));

cl::opt<bool> IncrementalLinkerCompatible(
"incremental-linker-compatible",
cl::desc(
"When used with filetype=obj, "
"emit an object file which can be used with an incremental linker"));

cl::opt<int> DwarfVersion("dwarf-version", cl::desc("Dwarf version"),
cl::init(0));

Expand All @@ -56,6 +62,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() {
Options.SanitizeAddress =
(AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress);
Options.MCRelaxAll = RelaxAll;
Options.MCIncrementalLinkerCompatible = IncrementalLinkerCompatible;
Options.DwarfVersion = DwarfVersion;
Options.ShowMCInst = ShowMCInst;
Options.ABIName = ABIName;
Expand Down
7 changes: 5 additions & 2 deletions include/llvm/Support/TargetRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ class Target {
typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter,
bool RelaxAll);
bool RelaxAll,
bool IncrementalLinkerCompatible);
typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S);
typedef MCTargetStreamer *(*AsmTargetStreamerCtorTy)(
MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint,
Expand Down Expand Up @@ -437,14 +438,16 @@ class Target {
MCAsmBackend &TAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter,
const MCSubtargetInfo &STI, bool RelaxAll,
bool IncrementalLinkerCompatible,
bool DWARFMustBeAtTheEnd) const {
MCStreamer *S;
switch (T.getObjectFormat()) {
default:
llvm_unreachable("Unknown object format");
case Triple::COFF:
assert(T.isOSWindows() && "only Windows COFF is supported");
S = COFFStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll);
S = COFFStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll,
IncrementalLinkerCompatible);
break;
case Triple::MachO:
if (MachOStreamerCtorFn)
Expand Down
2 changes: 2 additions & 0 deletions lib/CodeGen/LLVMTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ bool LLVMTargetMachine::addPassesToEmitFile(
Triple T(getTargetTriple().str());
AsmStreamer.reset(getTarget().createMCObjectStreamer(
T, *Context, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll,
Options.MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));
break;
}
Expand Down Expand Up @@ -255,6 +256,7 @@ bool LLVMTargetMachine::addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx,
const MCSubtargetInfo &STI = *getMCSubtargetInfo();
std::unique_ptr<MCStreamer> AsmStreamer(getTarget().createMCObjectStreamer(
T, *Ctx, *MAB, Out, MCE, STI, Options.MCOptions.MCRelaxAll,
Options.MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ true));

// Create the AsmPrinter, which takes ownership of AsmStreamer if successful.
Expand Down
3 changes: 2 additions & 1 deletion lib/MC/MCAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_,
MCCodeEmitter &Emitter_, MCObjectWriter &Writer_)
: Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_),
BundleAlignSize(0), RelaxAll(false), SubsectionsViaSymbols(false),
ELFHeaderEFlags(0) {
IncrementalLinkerCompatible(false), ELFHeaderEFlags(0) {
VersionMinInfo.Major = 0; // Major version == 0 for "none specified"
}

Expand All @@ -355,6 +355,7 @@ void MCAssembler::reset() {
BundleAlignSize = 0;
RelaxAll = false;
SubsectionsViaSymbols = false;
IncrementalLinkerCompatible = false;
ELFHeaderEFlags = 0;
LOHContainer.reset();
VersionMinInfo.Major = 0;
Expand Down
5 changes: 3 additions & 2 deletions lib/MC/MCTargetOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ namespace llvm {
MCTargetOptions::MCTargetOptions()
: SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false),
MCFatalWarnings(false), MCNoWarn(false), MCSaveTempLabels(false),
MCUseDwarfDirectory(false), ShowMCEncoding(false), ShowMCInst(false),
AsmVerbose(false), DwarfVersion(0), ABIName() {}
MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
DwarfVersion(0), ABIName() {}

StringRef MCTargetOptions::getABIName() const {
return ABIName;
Expand Down
17 changes: 12 additions & 5 deletions lib/MC/WinCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,8 @@ bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
// thunk to implement their /INCREMENTAL feature. Make sure we don't optimize
// away any relocations to functions.
uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
if (Asm.isIncrementalLinkerCompatible() &&
(Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
return false;
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
Expand Down Expand Up @@ -968,13 +969,19 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,

Header.PointerToSymbolTable = offset;

// FIXME: Remove the #else branch and make the #if branch unconditional once
// LLVM's self host configuration is aware of /Brepro.
#if (ENABLE_TIMESTAMPS == 1)
// MS LINK expects to be able to use this timestamp to implement their
// /INCREMENTAL feature.
std::time_t Now = time(nullptr);
if (Now < 0 || !isUInt<32>(Now))
Now = UINT32_MAX;
Header.TimeDateStamp = Now;
if (Asm.isIncrementalLinkerCompatible()) {
std::time_t Now = time(nullptr);
if (Now < 0 || !isUInt<32>(Now))
Now = UINT32_MAX;
Header.TimeDateStamp = Now;
} else {
Header.TimeDateStamp = 0;
}
#else
// We want a deterministic output. It looks like GNU as also writes 0 in here.
Header.TimeDateStamp = 0;
Expand Down
3 changes: 2 additions & 1 deletion lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ MCAsmBackend *createThumbBEAsmBackend(const Target &T,
// object file.
MCStreamer *createARMWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll);
MCCodeEmitter *Emitter, bool RelaxAll,
bool IncrementalLinkerCompatible);

/// Construct an ELF Mach-O object writer.
MCObjectWriter *createARMELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI,
Expand Down
12 changes: 6 additions & 6 deletions lib/Target/ARM/MCTargetDesc/ARMWinCOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ void ARMWinCOFFStreamer::EmitThumbFunc(MCSymbol *Symbol) {
}
}

MCStreamer *llvm::createARMWinCOFFStreamer(MCContext &Context,
MCAsmBackend &MAB,
raw_pwrite_stream &OS,
MCCodeEmitter *Emitter,
bool RelaxAll) {
return new ARMWinCOFFStreamer(Context, MAB, *Emitter, OS);
MCStreamer *llvm::createARMWinCOFFStreamer(
MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS,
MCCodeEmitter *Emitter, bool RelaxAll, bool IncrementalLinkerCompatible) {
auto *S = new ARMWinCOFFStreamer(Context, MAB, *Emitter, OS);
S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
return S;
}

2 changes: 1 addition & 1 deletion lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ MCAsmBackend *createX86_64AsmBackend(const Target &T, const MCRegisterInfo &MRI,
/// Takes ownership of \p AB and \p CE.
MCStreamer *createX86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB,
raw_pwrite_stream &OS, MCCodeEmitter *CE,
bool RelaxAll);
bool RelaxAll, bool IncrementalLinkerCompatible);

/// Construct an X86 Mach-O object writer.
MCObjectWriter *createX86MachObjectWriter(raw_pwrite_stream &OS, bool Is64Bit,
Expand Down
4 changes: 3 additions & 1 deletion lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ void X86WinCOFFStreamer::FinishImpl() {

MCStreamer *llvm::createX86WinCOFFStreamer(MCContext &C, MCAsmBackend &AB,
raw_pwrite_stream &OS,
MCCodeEmitter *CE, bool RelaxAll) {
MCCodeEmitter *CE, bool RelaxAll,
bool IncrementalLinkerCompatible) {
X86WinCOFFStreamer *S = new X86WinCOFFStreamer(C, AB, CE, OS);
S->getAssembler().setRelaxAll(RelaxAll);
S->getAssembler().setIncrementalLinkerCompatible(IncrementalLinkerCompatible);
return S;
}

2 changes: 1 addition & 1 deletion test/MC/ARM/Windows/invalid-relocation.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# RUN: not llvm-mc -triple thumbv7-windows -filetype obj -o /dev/null 2>&1 %s \
# RUN: not llvm-mc -triple thumbv7-windows -incremental-linker-compatible -filetype obj -o /dev/null 2>&1 %s \
# RUN: | FileCheck %s

.def invalid_relocation
Expand Down
4 changes: 2 additions & 2 deletions test/MC/COFF/simple-fixups.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// references to functions. Failing to do so might cause pointer-to-function
// equality to fail if /INCREMENTAL links are used.

// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | llvm-readobj -s | FileCheck %s
// RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -s | FileCheck %s
// RUN: llvm-mc -filetype=obj -incremental-linker-compatible -triple i686-pc-win32 %s | llvm-readobj -s | FileCheck %s
// RUN: llvm-mc -filetype=obj -incremental-linker-compatible -triple x86_64-pc-win32 %s | llvm-readobj -s | FileCheck %s

.def _foo;
.scl 2;
Expand Down
2 changes: 1 addition & 1 deletion test/MC/COFF/timestamp.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s -o - | llvm-readobj -h | FileCheck %s
// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 -incremental-linker-compatible %s -o - | llvm-readobj -h | FileCheck %s
// REQUIRES: timestamps

// CHECK: ImageFileHeader {
Expand Down
9 changes: 6 additions & 3 deletions tools/dsymutil/DwarfLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/LEB128.h"
Expand Down Expand Up @@ -618,9 +619,11 @@ bool DwarfStreamer::init(Triple TheTriple, StringRef OutputFilename) {
if (EC)
return error(Twine(OutputFilename) + ": " + EC.message(), Context);

MS = TheTarget->createMCObjectStreamer(TheTriple, *MC, *MAB, *OutFile, MCE,
*MSTI, false,
/*DWARFMustBeAtTheEnd*/ false);
MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
MS = TheTarget->createMCObjectStreamer(
TheTriple, *MC, *MAB, *OutFile, MCE, *MSTI, MCOptions.MCRelaxAll,
MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false);
if (!MS)
return error("no object streamer for target " + TripleName, Context);

Expand Down
5 changes: 4 additions & 1 deletion tools/llvm-dwp/llvm-dwp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/FileSystem.h"
Expand Down Expand Up @@ -404,8 +405,10 @@ int main(int argc, char **argv) {
if (EC)
return error(Twine(OutputFilename) + ": " + EC.message(), Context);

MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
TheTriple, MC, *MAB, OutFile, MCE, *MSTI, false,
TheTriple, MC, *MAB, OutFile, MCE, *MSTI, MCOptions.MCRelaxAll,
MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false));
if (!MS)
return error("no object streamer for target " + TripleName, Context);
Expand Down
7 changes: 4 additions & 3 deletions tools/llvm-mc/llvm-mc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,10 @@ int main(int argc, char **argv) {

MCCodeEmitter *CE = TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx);
MCAsmBackend *MAB = TheTarget->createMCAsmBackend(*MRI, TripleName, MCPU);
Str.reset(TheTarget->createMCObjectStreamer(TheTriple, Ctx, *MAB, *OS, CE,
*STI, RelaxAll,
/*DWARFMustBeAtTheEnd*/ false));
Str.reset(TheTarget->createMCObjectStreamer(
TheTriple, Ctx, *MAB, *OS, CE, *STI, MCOptions.MCRelaxAll,
MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false));
if (NoExecStack)
Str->InitSections(true);
}
Expand Down

0 comments on commit 56afa6e

Please sign in to comment.