Skip to content
This repository has been archived by the owner on Mar 22, 2019. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/amd-common' into amd-hcc-merge
Browse files Browse the repository at this point in the history
  • Loading branch information
yxsamliu committed May 4, 2017
2 parents d6f824f + 0e1653f commit d841c3a
Show file tree
Hide file tree
Showing 117 changed files with 2,614 additions and 1,518 deletions.
41 changes: 39 additions & 2 deletions COFF/Chunks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,45 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
std::sort(Begin, Begin + Cnt);
}

// Windows-specific.
// This class represents a block in .reloc section.
// Windows-specific. This class represents a block in .reloc section.
// The format is described here.
//
// On Windows, each DLL is linked against a fixed base address and
// usually loaded to that address. However, if there's already another
// DLL that overlaps, the loader has to relocate it. To do that, DLLs
// contain .reloc sections which contain offsets that need to be fixed
// up at runtime. If the loader finds that a DLL cannot be loaded to its
// desired base address, it loads it to somewhere else, and add <actual
// base address> - <desired base address> to each offset that is
// specified by the .reloc section. In ELF terms, .reloc sections
// contain relative relocations in REL format (as opposed to RELA.)
//
// This already significantly reduces the size of relocations compared
// to ELF .rel.dyn, but Windows does more to reduce it (probably because
// it was invented for PCs in the late '80s or early '90s.) Offsets in
// .reloc are grouped by page where the page size is 12 bits, and
// offsets sharing the same page address are stored consecutively to
// represent them with less space. This is very similar to the page
// table which is grouped by (multiple stages of) pages.
//
// For example, let's say we have 0x00030, 0x00500, 0x00700, 0x00A00,
// 0x20004, and 0x20008 in a .reloc section for x64. The uppermost 4
// bits have a type IMAGE_REL_BASED_DIR64 or 0xA. In the section, they
// are represented like this:
//
// 0x00000 -- page address (4 bytes)
// 16 -- size of this block (4 bytes)
// 0xA030 -- entries (2 bytes each)
// 0xA500
// 0xA700
// 0xAA00
// 0x20000 -- page address (4 bytes)
// 12 -- size of this block (4 bytes)
// 0xA004 -- entries (2 bytes each)
// 0xA008
//
// Usually we have a lot of relocations for each page, so the number of
// bytes for one .reloc entry is close to 2 bytes on average.
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
// Block header consists of 4 byte page RVA and 4 byte block size.
// Each entry is 2 byte. Last entry may be padding.
Expand Down
4 changes: 3 additions & 1 deletion COFF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct Export {
bool Noname = false;
bool Data = false;
bool Private = false;
bool Constant = false;

// If an export is a form of /export:foo=dllname.bar, that means
// that foo should be exported as an alias to bar in the DLL.
Expand Down Expand Up @@ -115,7 +116,7 @@ struct Configuration {
unsigned LTOOptLevel = 2;

// Used for /opt:lldltojobs=N
unsigned LTOJobs = 1;
unsigned LTOJobs = 0;
// Used for /opt:lldltopartitions=N
unsigned LTOPartitions = 1;

Expand Down Expand Up @@ -160,6 +161,7 @@ struct Configuration {
bool TerminalServerAware = true;
bool LargeAddressAware = false;
bool HighEntropyVA = false;
bool AppContainer = false;

// This is for debugging.
bool DebugPdb = false;
Expand Down
32 changes: 26 additions & 6 deletions COFF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -509,9 +509,26 @@ filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) {

// Create response file contents and invoke the MSVC linker.
void LinkerDriver::invokeMSVC(opt::InputArgList &Args) {
std::string Rsp = "/nologo ";
std::string Rsp = "/nologo\n";
std::vector<std::string> Temps;

// Write out archive members that we used in symbol resolution and pass these
// to MSVC before any archives, so that MSVC uses the same objects to satisfy
// references.
for (const auto *O : Symtab.ObjectFiles) {
if (O->ParentName.empty())
continue;
SmallString<128> S;
int Fd;
if (auto EC = sys::fs::createTemporaryFile(
"lld-" + sys::path::filename(O->ParentName), ".obj", Fd, S))
fatal(EC, "cannot create a temporary file");
raw_fd_ostream OS(Fd, /*shouldClose*/ true);
OS << O->MB.getBuffer();
Temps.push_back(S.str());
Rsp += quote(S) + "\n";
}

for (auto *Arg : Args) {
switch (Arg->getOption().getID()) {
case OPT_linkrepro:
Expand All @@ -528,14 +545,14 @@ void LinkerDriver::invokeMSVC(opt::InputArgList &Args) {
case OPT_INPUT: {
if (Optional<StringRef> Path = doFindFile(Arg->getValue())) {
if (Optional<std::string> S = filterBitcodeFiles(*Path, Temps))
Rsp += quote(*S) + " ";
Rsp += quote(*S) + "\n";
continue;
}
Rsp += quote(Arg->getValue()) + " ";
Rsp += quote(Arg->getValue()) + "\n";
break;
}
default:
Rsp += toString(Arg) + " ";
Rsp += toString(Arg) + "\n";
}
}

Expand Down Expand Up @@ -616,7 +633,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
}
}

if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
if (!Args.hasArgNoClaim(OPT_INPUT))
fatal("no input files");

// Construct search path list.
Expand Down Expand Up @@ -674,6 +691,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
}
}

if (Args.hasArg(OPT_appcontainer))
Config->AppContainer = true;

// Handle /machine
if (auto *Arg = Args.getLastArg(OPT_machine))
Config->Machine = getMachineType(Arg->getValue());
Expand Down Expand Up @@ -914,7 +934,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Set default image name if neither /out or /def set it.
if (Config->OutputFile.empty()) {
Config->OutputFile =
getOutputPath((*Args.filtered_begin(OPT_INPUT))->getValue());
getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue());
}

// Put the PDB next to the image if no /pdb flag was passed.
Expand Down
2 changes: 1 addition & 1 deletion COFF/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ArgParser {
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);

// Concatenate LINK environment varirable and given arguments and parse them.
llvm::opt::InputArgList parseLINK(llvm::ArrayRef<const char *> Args);
llvm::opt::InputArgList parseLINK(std::vector<const char *> Args);

// Tokenizes a given string and then parses as command line options.
llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
Expand Down
29 changes: 18 additions & 11 deletions COFF/DriverUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ Export parseExport(StringRef Arg) {
E.Data = true;
continue;
}
if (Tok.equals_lower("constant")) {
E.Constant = true;
continue;
}
if (Tok.equals_lower("private")) {
E.Private = true;
continue;
Expand Down Expand Up @@ -634,7 +638,7 @@ void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) {
std::vector<TemporaryFile> Temps;
for (StringRef S : Objects) {
Temps.emplace_back("lto", "obj", S);
Rsp += quote(Temps.back().Path) + " ";
Rsp += quote(Temps.back().Path) + "\n";
}

log("link.exe " + Rsp);
Expand Down Expand Up @@ -695,17 +699,20 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
return Args;
}

// link.exe has an interesting feature. If LINK environment exists,
// its contents are handled as a command line string. So you can pass
// extra arguments using the environment variable.
opt::InputArgList ArgParser::parseLINK(ArrayRef<const char *> Args) {
// link.exe has an interesting feature. If LINK or _LINK_ environment
// variables exist, their contents are handled as command line strings.
// So you can pass extra arguments using them.
opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Args) {
// Concatenate LINK env and command line arguments, and then parse them.
Optional<std::string> Env = Process::GetEnv("LINK");
if (!Env)
return parse(Args);
std::vector<const char *> V = tokenize(*Env);
V.insert(V.end(), Args.begin(), Args.end());
return parse(V);
if (Optional<std::string> S = Process::GetEnv("LINK")) {
std::vector<const char *> V = tokenize(*S);
Args.insert(Args.begin(), V.begin(), V.end());
}
if (Optional<std::string> S = Process::GetEnv("_LINK_")) {
std::vector<const char *> V = tokenize(*S);
Args.insert(Args.begin(), V.begin(), V.end());
}
return parse(Args);
}

std::vector<const char *> ArgParser::tokenize(StringRef S) {
Expand Down
1 change: 1 addition & 0 deletions COFF/Error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ void log(const Twine &Msg) {
if (Config->Verbose) {
std::lock_guard<std::mutex> Lock(Mu);
outs() << Argv0 << ": " << Msg << "\n";
outs().flush();
}
}

Expand Down
10 changes: 9 additions & 1 deletion COFF/ICF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,18 @@ uint32_t ICF::getHash(SectionChunk *C) {
}

// Returns true if section S is subject of ICF.
//
// Microsoft's documentation
// (https://msdn.microsoft.com/en-us/library/bxwfs976.aspx; visited April
// 2017) says that /opt:icf folds both functions and read-only data.
// Despite that, the MSVC linker folds only functions. We found
// a few instances of programs that are not safe for data merging.
// Therefore, we merge only functions just like the MSVC tool.
bool ICF::isEligible(SectionChunk *C) {
bool Global = C->Sym && C->Sym->isExternal();
bool Executable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
bool Writable = C->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
return C->isCOMDAT() && C->isLive() && Global && !Writable;
return C->isCOMDAT() && C->isLive() && Global && Executable && !Writable;
}

// Split a range into smaller ranges by recoloring sections
Expand Down
9 changes: 4 additions & 5 deletions COFF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/COFF.h"
Expand Down Expand Up @@ -328,6 +327,9 @@ void ImportFile::parse() {

ImpSym = cast<DefinedImportData>(
Symtab->addImportData(ImpName, this)->body());
if (Hdr->getType() == llvm::COFF::IMPORT_CONST)
ConstSym =
cast<DefinedImportData>(Symtab->addImportData(Name, this)->body());

// If type is function, we need to create a thunk which jump to an
// address pointed by the __imp_ symbol. (This allows you to call
Expand Down Expand Up @@ -364,10 +366,7 @@ void BitcodeFile::parse() {
}

MachineTypes BitcodeFile::getMachineType() {
Expected<std::string> ET = getBitcodeTargetTriple(MB);
if (!ET)
return IMAGE_FILE_MACHINE_UNKNOWN;
switch (Triple(*ET).getArch()) {
switch (Triple(Obj->getTargetTriple()).getArch()) {
case Triple::x86_64:
return AMD64;
case Triple::x86:
Expand Down
6 changes: 3 additions & 3 deletions COFF/InputFiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class InputFile {
// Returns the CPU type this file was compiled to.
virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }

MemoryBufferRef MB;

// An archive file name if this file is created from an archive.
StringRef ParentName;

Expand All @@ -67,7 +69,6 @@ class InputFile {
protected:
InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}

MemoryBufferRef MB;
std::string Directives;

private:
Expand Down Expand Up @@ -166,13 +167,13 @@ class ImportFile : public InputFile {
static bool classof(const InputFile *F) { return F->kind() == ImportKind; }

DefinedImportData *ImpSym = nullptr;
DefinedImportData *ConstSym = nullptr;
DefinedImportThunk *ThunkSym = nullptr;
std::string DLLName;

private:
void parse() override;

llvm::BumpPtrAllocator Alloc;
llvm::BumpPtrAllocator StringAllocAux;
llvm::StringSaver StringAlloc;

Expand All @@ -195,7 +196,6 @@ class BitcodeFile : public InputFile {
void parse() override;

std::vector<SymbolBody *> SymbolBodies;
llvm::BumpPtrAllocator Alloc;
};
} // namespace coff

Expand Down
2 changes: 1 addition & 1 deletion COFF/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static std::unique_ptr<lto::LTO> createLTO() {
checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
/*UseInputModulePath*/ true));
lto::ThinBackend Backend;
if (Config->LTOJobs != -1u)
if (Config->LTOJobs != 0)
Backend = lto::createInProcessThinBackend(Config->LTOJobs);
return llvm::make_unique<lto::LTO>(std::move(Conf), Backend,
Config->LTOPartitions);
Expand Down
20 changes: 13 additions & 7 deletions COFF/Librarian.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class ObjectFactory {
// Create a short import file which is described in PE/COFF spec 7. Import
// Library Format.
NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
ImportNameType NameType, bool isData);
ImportType Type, ImportNameType NameType);
};
}

Expand Down Expand Up @@ -440,8 +440,8 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {

NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
uint16_t Ordinal,
ImportNameType NameType,
bool isData) {
ImportType ImportType,
ImportNameType NameType) {
size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
size_t Size = sizeof(coff_import_header) + ImpSize;
char *Buf = Alloc.Allocate<char>(Size);
Expand All @@ -456,8 +456,7 @@ NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
Imp->SizeOfData = ImpSize;
if (Ordinal > 0)
Imp->OrdinalHint = Ordinal;
Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE);
Imp->TypeInfo |= NameType << 2;
Imp->TypeInfo = (NameType << 2) | ImportType;

// Write symbol name and DLL name.
memcpy(P, Sym.data(), Sym.size());
Expand Down Expand Up @@ -490,11 +489,18 @@ void lld::coff::writeImportLibrary() {
if (E.Private)
continue;

ImportNameType Type = getNameType(E.SymbolName, E.Name);
ImportType ImportType = IMPORT_CODE;
if (E.Data)
ImportType = IMPORT_DATA;
if (E.Constant)
ImportType = IMPORT_CONST;

ImportNameType NameType = getNameType(E.SymbolName, E.Name);
std::string Name = E.ExtName.empty()
? std::string(E.SymbolName)
: replace(E.SymbolName, E.Name, E.ExtName);
Members.push_back(OF.createShortImport(Name, E.Ordinal, Type, E.Data));
Members.push_back(OF.createShortImport(Name, E.Ordinal, ImportType,
NameType));
}

std::pair<StringRef, std::error_code> Result =
Expand Down
Loading

0 comments on commit d841c3a

Please sign in to comment.