mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 10:55:58 +08:00
Add the /order option.
With the /order option, you can give an order file. An order file contains symbol names, one per line, and the linker places comdat sections in that given order. The option is used often to optimize an output binary for (in particular, startup) speed by improving locality. Differential Revision: https://reviews.llvm.org/D42598 llvm-svn: 323579
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#ifndef LLD_COFF_CONFIG_H
|
||||
#define LLD_COFF_CONFIG_H
|
||||
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/COFF.h"
|
||||
#include "llvm/Support/CachePruning.h"
|
||||
@@ -153,6 +154,9 @@ struct Configuration {
|
||||
// Used for /alternatename.
|
||||
std::map<StringRef, StringRef> AlternateNames;
|
||||
|
||||
// Used for /order.
|
||||
llvm::StringMap<int> Order;
|
||||
|
||||
// Used for /lldmap.
|
||||
std::string MapFile;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "SymbolTable.h"
|
||||
#include "Symbols.h"
|
||||
#include "Writer.h"
|
||||
#include "lld/Common/Args.h"
|
||||
#include "lld/Common/Driver.h"
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "lld/Common/Memory.h"
|
||||
@@ -756,6 +757,33 @@ bool LinkerDriver::run() {
|
||||
return DidWork;
|
||||
}
|
||||
|
||||
// Parse an /order file. If an option is given, the linker places
|
||||
// COMDAT sections in the same order as their names appear in the
|
||||
// given file.
|
||||
static void parseOrderFile(StringRef Arg) {
|
||||
// For some reason, the MSVC linker requires a filename to be
|
||||
// preceded by "@".
|
||||
if (!Arg.startswith("@")) {
|
||||
error("malformed /order option: '@' missing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Open a file.
|
||||
StringRef Path = Arg.substr(1);
|
||||
std::unique_ptr<MemoryBuffer> MB = CHECK(
|
||||
MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);
|
||||
|
||||
// Parse a file. An order file contains one symbol per line.
|
||||
// All symbols that were not present in a given order file are
|
||||
// considered to have the lowest priority 0 and are placed at
|
||||
// end of an output section.
|
||||
for (std::string S : args::getLines(MB->getMemBufferRef())) {
|
||||
if (Config->Machine == I386 && !isDecorated(S))
|
||||
S = "_" + S;
|
||||
Config->Order[S] = INT_MIN + Config->Order.size();
|
||||
}
|
||||
}
|
||||
|
||||
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
// If the first command line argument is "/lib", link.exe acts like lib.exe.
|
||||
// We call our own implementation of lib.exe that understands bitcode files.
|
||||
@@ -1160,6 +1188,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle /order
|
||||
if (auto *Arg = Args.getLastArg(OPT_order))
|
||||
parseOrderFile(Arg->getValue());
|
||||
|
||||
// Handle /export
|
||||
for (auto *Arg : Args.filtered(OPT_export)) {
|
||||
Export E = parseExport(Arg->getValue());
|
||||
|
||||
@@ -42,6 +42,7 @@ def merge : P<"merge", "Combine sections">;
|
||||
def mllvm : P<"mllvm", "Options to pass to LLVM">;
|
||||
def nodefaultlib : P<"nodefaultlib", "Remove a default library">;
|
||||
def opt : P<"opt", "Control optimizations">;
|
||||
def order : P<"order", "Put functions in order">;
|
||||
def out : P<"out", "Path to file to write output">;
|
||||
def pdb : P<"pdb", "PDB file path">;
|
||||
def section : P<"section", "Specify section attributes">;
|
||||
|
||||
@@ -348,6 +348,21 @@ static StringRef getOutputSection(StringRef Name) {
|
||||
return It->second;
|
||||
}
|
||||
|
||||
// For /order.
|
||||
static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {
|
||||
auto GetPriority = [](const Chunk *C) {
|
||||
if (auto *Sec = dyn_cast<SectionChunk>(C))
|
||||
if (Sec->Sym)
|
||||
return Config->Order.lookup(Sec->Sym->getName());
|
||||
return 0;
|
||||
};
|
||||
|
||||
std::stable_sort(Chunks.begin(), Chunks.end(),
|
||||
[=](const Chunk *A, const Chunk *B) {
|
||||
return GetPriority(A) < GetPriority(B);
|
||||
});
|
||||
}
|
||||
|
||||
// Create output section objects and add them to OutputSections.
|
||||
void Writer::createSections() {
|
||||
// First, bin chunks by name.
|
||||
@@ -362,6 +377,11 @@ void Writer::createSections() {
|
||||
Map[C->getSectionName()].push_back(C);
|
||||
}
|
||||
|
||||
// Process an /order option.
|
||||
if (!Config->Order.empty())
|
||||
for (auto &Pair : Map)
|
||||
sortBySectionOrder(Pair.second);
|
||||
|
||||
// Then create an OutputSection for each section.
|
||||
// '$' and all following characters in input section names are
|
||||
// discarded when determining output section. So, .text$foo
|
||||
|
||||
76
lld/test/COFF/Inputs/order.yaml
Normal file
76
lld/test/COFF/Inputs/order.yaml
Normal file
@@ -0,0 +1,76 @@
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 1
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: unrelated2
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 2
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 1
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: fn4
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 3
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: fn1
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
69
lld/test/COFF/order-i386.test
Normal file
69
lld/test/COFF/order-i386.test
Normal file
@@ -0,0 +1,69 @@
|
||||
# RUN: yaml2obj < %s > %t.obj
|
||||
|
||||
# RUN: echo fn1 > %t.order
|
||||
# RUN: echo fn2 >> %t.order
|
||||
|
||||
# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref %t.obj \
|
||||
# RUN: -lldmap:- -out:%t.exe -order:@%t.order | FileCheck %s
|
||||
# CHECK: fn1
|
||||
# CHECK: fn2
|
||||
|
||||
# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref %t.obj \
|
||||
# RUN: -lldmap:- -out:%t.exe | FileCheck -check-prefix=DEFAULT %s
|
||||
# DEFAULT: fn2
|
||||
# DEFAULT: fn1
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_I386
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: '.text'
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: CC
|
||||
- Name: '.text'
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: CC
|
||||
symbols:
|
||||
- Name: '.text'
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: '.text'
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 0
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: _fn2
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: _fn1
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
|
||||
102
lld/test/COFF/order.test
Normal file
102
lld/test/COFF/order.test
Normal file
@@ -0,0 +1,102 @@
|
||||
# RUN: yaml2obj < %s > %t1.obj
|
||||
# RUN: yaml2obj < %p/Inputs/order.yaml > %t2.obj
|
||||
|
||||
# RUN: echo fn1 > %t.order
|
||||
# RUN: echo fn2 >> %t.order
|
||||
# RUN: echo fn3 >> %t.order
|
||||
# RUN: echo fn4 >> %t.order
|
||||
|
||||
# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref -debug %t1.obj %t2.obj \
|
||||
# RUN: -lldmap:- -out:%t.exe -order:@%t.order | FileCheck %s
|
||||
# CHECK: fn1
|
||||
# CHECK: fn2
|
||||
# CHECK: fn3
|
||||
# CHECK: fn4
|
||||
# CHECK: unrelated1
|
||||
# CHECK: unrelated2
|
||||
|
||||
# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref -debug %t1.obj %t2.obj \
|
||||
# RUN: -lldmap:- -out:%t.exe | FileCheck -check-prefix=DEFAULT %s
|
||||
# DEFAULT: fn2
|
||||
# DEFAULT: fn3
|
||||
# DEFAULT: unrelated1
|
||||
# DEFAULT: unrelated2
|
||||
# DEFAULT: fn4
|
||||
# DEFAULT: fn1
|
||||
|
||||
--- !COFF
|
||||
header:
|
||||
Machine: IMAGE_FILE_MACHINE_AMD64
|
||||
Characteristics: [ ]
|
||||
sections:
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
- Name: .text
|
||||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
|
||||
Alignment: 16
|
||||
SectionData: C3
|
||||
symbols:
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 1
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: fn2
|
||||
Value: 0
|
||||
SectionNumber: 1
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 2
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: fn3
|
||||
Value: 0
|
||||
SectionNumber: 2
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
- Name: .text
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_NULL
|
||||
StorageClass: IMAGE_SYM_CLASS_STATIC
|
||||
SectionDefinition:
|
||||
Length: 1
|
||||
NumberOfRelocations: 0
|
||||
NumberOfLinenumbers: 0
|
||||
CheckSum: 0
|
||||
Number: 3
|
||||
Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
|
||||
- Name: unrelated1
|
||||
Value: 0
|
||||
SectionNumber: 3
|
||||
SimpleType: IMAGE_SYM_TYPE_NULL
|
||||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
|
||||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
|
||||
...
|
||||
Reference in New Issue
Block a user