Date: Sun, 16 Apr 2017 16:35:48 +0000 (UTC) From: Dimitry Andric <dim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r317031 - in projects/clang500-import/contrib/llvm/tools/lld: . COFF ELF include/lld/Core include/lld/Driver lib/Core lib/ReaderWriter/MachO tools/lld Message-ID: <201704161635.v3GGZmcI010003@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dim Date: Sun Apr 16 16:35:48 2017 New Revision: 317031 URL: https://svnweb.freebsd.org/changeset/base/317031 Log: Merge lld trunk r300422 and resolve conflicts. Added: projects/clang500-import/contrib/llvm/tools/lld/COFF/LTO.cpp - copied unchanged from r317030, vendor/lld/dist/COFF/LTO.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/LTO.h - copied unchanged from r317030, vendor/lld/dist/COFF/LTO.h projects/clang500-import/contrib/llvm/tools/lld/COFF/MapFile.cpp - copied unchanged from r317030, vendor/lld/dist/COFF/MapFile.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/MapFile.h - copied unchanged from r317030, vendor/lld/dist/COFF/MapFile.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Filesystem.cpp - copied unchanged from r317030, vendor/lld/dist/ELF/Filesystem.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Filesystem.h - copied unchanged from r317030, vendor/lld/dist/ELF/Filesystem.h projects/clang500-import/contrib/llvm/tools/lld/ELF/MapFile.cpp - copied unchanged from r317030, vendor/lld/dist/ELF/MapFile.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/MapFile.h - copied unchanged from r317030, vendor/lld/dist/ELF/MapFile.h projects/clang500-import/contrib/llvm/tools/lld/ELF/ScriptLexer.cpp - copied unchanged from r317030, vendor/lld/dist/ELF/ScriptLexer.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/ScriptLexer.h - copied unchanged from r317030, vendor/lld/dist/ELF/ScriptLexer.h projects/clang500-import/contrib/llvm/tools/lld/include/lld/Core/TargetOptionsCommandFlags.h - copied unchanged from r317030, vendor/lld/dist/include/lld/Core/TargetOptionsCommandFlags.h projects/clang500-import/contrib/llvm/tools/lld/lib/Core/TargetOptionsCommandFlags.cpp - copied unchanged from r317030, vendor/lld/dist/lib/Core/TargetOptionsCommandFlags.cpp Modified: projects/clang500-import/contrib/llvm/tools/lld/CMakeLists.txt projects/clang500-import/contrib/llvm/tools/lld/COFF/CMakeLists.txt projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.h projects/clang500-import/contrib/llvm/tools/lld/COFF/Config.h projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.h projects/clang500-import/contrib/llvm/tools/lld/COFF/DriverUtils.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.h projects/clang500-import/contrib/llvm/tools/lld/COFF/ICF.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/InputFiles.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/InputFiles.h projects/clang500-import/contrib/llvm/tools/lld/COFF/Librarian.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/ModuleDef.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Options.td projects/clang500-import/contrib/llvm/tools/lld/COFF/PDB.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/SymbolTable.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/SymbolTable.h projects/clang500-import/contrib/llvm/tools/lld/COFF/Symbols.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Symbols.h projects/clang500-import/contrib/llvm/tools/lld/COFF/Writer.cpp projects/clang500-import/contrib/llvm/tools/lld/COFF/Writer.h projects/clang500-import/contrib/llvm/tools/lld/ELF/CMakeLists.txt projects/clang500-import/contrib/llvm/tools/lld/ELF/Config.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Driver.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Driver.h projects/clang500-import/contrib/llvm/tools/lld/ELF/DriverUtils.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/EhFrame.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/EhFrame.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Error.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Error.h projects/clang500-import/contrib/llvm/tools/lld/ELF/GdbIndex.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/GdbIndex.h projects/clang500-import/contrib/llvm/tools/lld/ELF/ICF.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/InputFiles.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/InputFiles.h projects/clang500-import/contrib/llvm/tools/lld/ELF/InputSection.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/InputSection.h projects/clang500-import/contrib/llvm/tools/lld/ELF/LTO.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/LTO.h projects/clang500-import/contrib/llvm/tools/lld/ELF/LinkerScript.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/LinkerScript.h projects/clang500-import/contrib/llvm/tools/lld/ELF/MarkLive.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Options.td projects/clang500-import/contrib/llvm/tools/lld/ELF/OutputSections.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/OutputSections.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Relocations.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Relocations.h projects/clang500-import/contrib/llvm/tools/lld/ELF/ScriptParser.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/ScriptParser.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Strings.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/SymbolTable.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/SymbolTable.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Symbols.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Symbols.h projects/clang500-import/contrib/llvm/tools/lld/ELF/SyntheticSections.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/SyntheticSections.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Target.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Target.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Threads.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Thunks.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Thunks.h projects/clang500-import/contrib/llvm/tools/lld/ELF/Writer.cpp projects/clang500-import/contrib/llvm/tools/lld/ELF/Writer.h projects/clang500-import/contrib/llvm/tools/lld/include/lld/Core/Parallel.h projects/clang500-import/contrib/llvm/tools/lld/include/lld/Driver/Driver.h projects/clang500-import/contrib/llvm/tools/lld/lib/Core/CMakeLists.txt projects/clang500-import/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp projects/clang500-import/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp projects/clang500-import/contrib/llvm/tools/lld/lib/ReaderWriter/MachO/CMakeLists.txt projects/clang500-import/contrib/llvm/tools/lld/tools/lld/lld.cpp Directory Properties: projects/clang500-import/contrib/llvm/tools/lld/ (props changed) Modified: projects/clang500-import/contrib/llvm/tools/lld/CMakeLists.txt ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/CMakeLists.txt Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/CMakeLists.txt Sun Apr 16 16:35:48 2017 (r317031) @@ -11,8 +11,11 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRE message(FATAL_ERROR "llvm-config not found: specify LLVM_CONFIG_PATH") endif() - execute_process(COMMAND "${LLVM_CONFIG_PATH}" "--obj-root" "--includedir" + execute_process(COMMAND "${LLVM_CONFIG_PATH}" + "--obj-root" + "--includedir" "--cmakedir" + "--src-root" RESULT_VARIABLE HAD_ERROR OUTPUT_VARIABLE LLVM_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -25,9 +28,11 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRE list(GET LLVM_CONFIG_OUTPUT 0 OBJ_ROOT) list(GET LLVM_CONFIG_OUTPUT 1 MAIN_INCLUDE_DIR) list(GET LLVM_CONFIG_OUTPUT 2 LLVM_CMAKE_PATH) + list(GET LLVM_CONFIG_OUTPUT 3 MAIN_SRC_DIR) set(LLVM_OBJ_ROOT ${OBJ_ROOT} CACHE PATH "path to LLVM build tree") set(LLVM_MAIN_INCLUDE_DIR ${MAIN_INCLUDE_DIR} CACHE PATH "path to llvm/include") + set(LLVM_MAIN_SRC_DIR ${MAIN_SRC_DIR} CACHE PATH "Path to LLVM source tree") file(TO_CMAKE_PATH ${LLVM_OBJ_ROOT} LLVM_BINARY_DIR) @@ -49,6 +54,67 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRE include(AddLLVM) include(TableGen) include(HandleLLVMOptions) + + if(LLVM_INCLUDE_TESTS) + set(Python_ADDITIONAL_VERSIONS 2.7) + include(FindPythonInterp) + if(NOT PYTHONINTERP_FOUND) + message(FATAL_ERROR +"Unable to find Python interpreter, required for testing. + +Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") + endif() + + if(${PYTHON_VERSION_STRING} VERSION_LESS 2.7) + message(FATAL_ERROR "Python 2.7 or newer is required") + endif() + + # Check prebuilt llvm/utils. + if(EXISTS ${LLVM_TOOLS_BINARY_DIR}/FileCheck${CMAKE_EXECUTABLE_SUFFIX} + AND EXISTS ${LLVM_TOOLS_BINARY_DIR}/not${CMAKE_EXECUTABLE_SUFFIX}) + set(LLVM_UTILS_PROVIDED ON) + endif() + + if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) + # Note: path not really used, except for checking if lit was found + set(LLVM_LIT ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) + if(NOT LLVM_UTILS_PROVIDED) + add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/FileCheck utils/FileCheck) + add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/not utils/not) + set(LLVM_UTILS_PROVIDED ON) + set(LLD_TEST_DEPS FileCheck not) + endif() + set(UNITTEST_DIR ${LLVM_MAIN_SRC_DIR}/utils/unittest) + if(EXISTS ${UNITTEST_DIR}/googletest/include/gtest/gtest.h + AND NOT EXISTS ${LLVM_LIBRARY_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX} + AND EXISTS ${UNITTEST_DIR}/CMakeLists.txt) + add_subdirectory(${UNITTEST_DIR} utils/unittest) + endif() + else() + # Seek installed Lit. + find_program(LLVM_LIT + NAMES llvm-lit lit.py lit + PATHS "${LLVM_MAIN_SRC_DIR}/utils/lit" + DOC "Path to lit.py") + endif() + + if(LLVM_LIT) + # Define the default arguments to use with 'lit', and an option for the user + # to override. + set(LIT_ARGS_DEFAULT "-sv") + if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") + endif() + set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") + + # On Win32 hosts, provide an option to specify the path to the GnuWin32 tools. + if(WIN32 AND NOT CYGWIN) + set(LLVM_LIT_TOOLS_DIR "" CACHE PATH "Path to GnuWin32 tools") + endif() + else() + set(LLVM_INCLUDE_TESTS OFF) + endif() + endif() endif() set(LLD_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/CMakeLists.txt ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/CMakeLists.txt Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/CMakeLists.txt Sun Apr 16 16:35:48 2017 (r317031) @@ -15,6 +15,8 @@ add_lld_library(lldCOFF ICF.cpp InputFiles.cpp Librarian.cpp + LTO.cpp + MapFile.cpp MarkLive.cpp ModuleDef.cpp PDB.cpp @@ -25,6 +27,7 @@ add_lld_library(lldCOFF LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} + BitReader Core DebugInfoCodeView DebugInfoMSF @@ -40,7 +43,7 @@ add_lld_library(lldCOFF LINK_LIBS lldCore - ${PTHREAD_LIB} + ${LLVM_PTHREAD_LIB} DEPENDS COFFOptionsTableGen Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.cpp ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.cpp Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.cpp Sun Apr 16 16:35:48 2017 (r317031) @@ -11,6 +11,7 @@ #include "Error.h" #include "InputFiles.h" #include "Symbols.h" +#include "llvm/ADT/Twine.h" #include "llvm/Object/COFF.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" @@ -61,7 +62,7 @@ void SectionChunk::applyRelX64(uint8_t * case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break; case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break; default: - fatal("unsupported relocation type"); + fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } @@ -76,7 +77,7 @@ void SectionChunk::applyRelX86(uint8_t * case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break; case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break; default: - fatal("unsupported relocation type"); + fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } @@ -136,7 +137,7 @@ void SectionChunk::applyRelARM(uint8_t * case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break; case IMAGE_REL_ARM_SECREL: add32(Off, Sym->getSecrel()); break; default: - fatal("unsupported relocation type"); + fatal("unsupported relocation type 0x" + Twine::utohexstr(Type)); } } @@ -226,7 +227,7 @@ void SectionChunk::printDiscardedMessage // Removed by dead-stripping. If it's removed by ICF, ICF already // printed out the name, so don't repeat that here. if (Sym && this == Repl) - outs() << "Discarded " << Sym->getName() << "\n"; + message("Discarded " + Sym->getName()); } StringRef SectionChunk::getDebugName() { Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.h ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.h Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Chunks.h Sun Apr 16 16:35:48 2017 (r317031) @@ -187,10 +187,10 @@ public: const coff_section *Header; -private: - // A file this chunk was created from. + // The file that this chunk was created from. ObjectFile *File; +private: StringRef SectionName; std::vector<SectionChunk *> AssocChildren; llvm::iterator_range<const coff_relocation *> Relocs; Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Config.h ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Config.h Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Config.h Sun Apr 16 16:35:48 2017 (r317031) @@ -80,14 +80,16 @@ struct Configuration { SymbolBody *Entry = nullptr; bool NoEntry = false; std::string OutputFile; + bool ColorDiagnostics; bool DoGC = true; bool DoICF = true; + uint64_t ErrorLimit = 20; bool Relocatable = true; bool Force = false; bool Debug = false; bool WriteSymtab = true; unsigned DebugTypes = static_cast<unsigned>(DebugType::None); - StringRef PDBPath; + llvm::SmallString<128> PDBPath; // Symbols in this set are considered as live by the garbage collector. std::set<SymbolBody *> GCRoot; @@ -103,6 +105,8 @@ struct Configuration { std::map<std::string, int> DLLOrder; SymbolBody *DelayLoadHelper = nullptr; + bool SaveTemps = false; + // Used for SafeSEH. Symbol *SEHTable = nullptr; Symbol *SEHCount = nullptr; @@ -111,7 +115,9 @@ struct Configuration { unsigned LTOOptLevel = 2; // Used for /opt:lldltojobs=N - unsigned LTOJobs = 1; + unsigned LTOJobs = 0; + // Used for /opt:lldltopartitions=N + unsigned LTOPartitions = 1; // Used for /merge:from=to (e.g. /merge:.rdata=.text) std::map<StringRef, StringRef> Merge; @@ -135,6 +141,9 @@ struct Configuration { // Used for /alternatename. std::map<StringRef, StringRef> AlternateNames; + // Used for /lldmap. + std::string MapFile; + uint64_t ImageBase = -1; uint64_t StackReserve = 1024 * 1024; uint64_t StackCommit = 4096; @@ -151,6 +160,7 @@ struct Configuration { bool TerminalServerAware = true; bool LargeAddressAware = false; bool HighEntropyVA = false; + bool AppContainer = false; // This is for debugging. bool DebugPdb = false; Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.cpp ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.cpp Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.cpp Sun Apr 16 16:35:48 2017 (r317031) @@ -19,6 +19,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/LibDriver/LibDriver.h" +#include "llvm/Object/ArchiveWriter.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -31,17 +32,11 @@ #include <algorithm> #include <memory> -#ifdef _MSC_VER -// <future> depends on <eh.h> for __uncaught_exception. -#include <eh.h> -#endif - #include <future> using namespace llvm; using namespace llvm::COFF; using llvm::sys::Process; -using llvm::sys::fs::OpenFlags; using llvm::sys::fs::file_magic; using llvm::sys::fs::identify_magic; @@ -55,11 +50,16 @@ BumpPtrAllocator BAlloc; StringSaver Saver{BAlloc}; std::vector<SpecificAllocBase *> SpecificAllocBase::Instances; -bool link(ArrayRef<const char *> Args) { +bool link(ArrayRef<const char *> Args, raw_ostream &Diag) { + ErrorCount = 0; + ErrorOS = &Diag; + Argv0 = Args[0]; Config = make<Configuration>(); + Config->ColorDiagnostics = + (ErrorOS == &llvm::errs() && Process::StandardErrHasColors()); Driver = make<LinkerDriver>(); Driver->link(Args); - return true; + return !ErrorCount; } // Drop directory components and replace extension with ".exe" or ".dll". @@ -121,10 +121,12 @@ void LinkerDriver::addBuffer(std::unique return Symtab.addFile(make<ArchiveFile>(MBRef)); if (Magic == file_magic::bitcode) return Symtab.addFile(make<BitcodeFile>(MBRef)); + if (Magic == file_magic::coff_cl_gl_object) - fatal(MBRef.getBufferIdentifier() + ": is not a native COFF file. " + error(MBRef.getBufferIdentifier() + ": is not a native COFF file. " "Recompile without /GL"); - Symtab.addFile(make<ObjectFile>(MBRef)); + else + Symtab.addFile(make<ObjectFile>(MBRef)); } void LinkerDriver::enqueuePath(StringRef Path) { @@ -134,12 +136,10 @@ void LinkerDriver::enqueuePath(StringRef enqueueTask([=]() { auto MBOrErr = Future->get(); if (MBOrErr.second) - fatal(MBOrErr.second, "could not open " + PathStr); - Driver->addBuffer(std::move(MBOrErr.first)); + error("could not open " + PathStr + ": " + MBOrErr.second.message()); + else + Driver->addBuffer(std::move(MBOrErr.first)); }); - - if (Config->OutputFile == "") - Config->OutputFile = getOutputPath(Path); } void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName, @@ -151,17 +151,18 @@ void LinkerDriver::addArchiveBuffer(Memo } InputFile *Obj; - if (Magic == file_magic::coff_object) + if (Magic == file_magic::coff_object) { Obj = make<ObjectFile>(MB); - else if (Magic == file_magic::bitcode) + } else if (Magic == file_magic::bitcode) { Obj = make<BitcodeFile>(MB); - else - fatal("unknown file type: " + MB.getBufferIdentifier()); + } else { + error("unknown file type: " + MB.getBufferIdentifier()); + return; + } Obj->ParentName = ParentName; Symtab.addFile(Obj); - if (Config->Verbose) - outs() << "Loaded " << toString(Obj) << " for " << SymName << "\n"; + log("Loaded " + toString(Obj) + " for " + SymName); } void LinkerDriver::enqueueArchiveMember(const Archive::Child &C, @@ -234,7 +235,7 @@ void LinkerDriver::parseDirectives(Strin case OPT_throwingnew: break; default: - fatal(Arg->getSpelling() + " is not allowed in .drectve"); + error(Arg->getSpelling() + " is not allowed in .drectve"); } } } @@ -402,7 +403,8 @@ static unsigned parseDebugType(StringRef DebugTypes |= StringSwitch<unsigned>(Type.lower()) .Case("cv", static_cast<unsigned>(DebugType::CV)) .Case("pdata", static_cast<unsigned>(DebugType::PData)) - .Case("fixup", static_cast<unsigned>(DebugType::Fixup)); + .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) + .Default(0); return DebugTypes; } @@ -418,6 +420,132 @@ static std::string getMapFile(const opt: return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str(); } +std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) { + std::vector<MemoryBufferRef> V; + Error Err = Error::success(); + for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { + Archive::Child C = + check(COrErr, + File->getFileName() + ": could not get the child of the archive"); + MemoryBufferRef MBRef = + check(C.getMemoryBufferRef(), + File->getFileName() + + ": could not get the buffer for a child of the archive"); + V.push_back(MBRef); + } + if (Err) + fatal(File->getFileName() + + ": Archive::children failed: " + toString(std::move(Err))); + return V; +} + +// A helper function for filterBitcodeFiles. +static bool needsRebuilding(MemoryBufferRef MB) { + // The MSVC linker doesn't support thin archives, so if it's a thin + // archive, we always need to rebuild it. + std::unique_ptr<Archive> File = + check(Archive::create(MB), "Failed to read " + MB.getBufferIdentifier()); + if (File->isThin()) + return true; + + // Returns true if the archive contains at least one bitcode file. + for (MemoryBufferRef Member : getArchiveMembers(File.get())) + if (identify_magic(Member.getBuffer()) == file_magic::bitcode) + return true; + return false; +} + +// Opens a given path as an archive file and removes bitcode files +// from them if exists. This function is to appease the MSVC linker as +// their linker doesn't like archive files containing non-native +// object files. +// +// If a given archive doesn't contain bitcode files, the archive path +// is returned as-is. Otherwise, a new temporary file is created and +// its path is returned. +static Optional<std::string> +filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { + std::unique_ptr<MemoryBuffer> MB = check( + MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); + MemoryBufferRef MBRef = MB->getMemBufferRef(); + file_magic Magic = identify_magic(MBRef.getBuffer()); + + if (Magic == file_magic::bitcode) + return None; + if (Magic != file_magic::archive) + return Path.str(); + if (!needsRebuilding(MBRef)) + return Path.str(); + + std::unique_ptr<Archive> File = + check(Archive::create(MBRef), + MBRef.getBufferIdentifier() + ": failed to parse archive"); + + std::vector<NewArchiveMember> New; + for (MemoryBufferRef Member : getArchiveMembers(File.get())) + if (identify_magic(Member.getBuffer()) != file_magic::bitcode) + New.emplace_back(Member); + + if (New.empty()) + return None; + + log("Creating a temporary archive for " + Path + " to remove bitcode files"); + + SmallString<128> S; + if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path), + ".lib", S)) + fatal(EC, "cannot create a temporary file"); + std::string Temp = S.str(); + TemporaryFiles.push_back(Temp); + + std::pair<StringRef, std::error_code> Ret = + llvm::writeArchive(Temp, New, /*WriteSymtab=*/true, Archive::Kind::K_GNU, + /*Deterministics=*/true, + /*Thin=*/false); + if (Ret.second) + error("failed to create a new archive " + S.str() + ": " + Ret.first); + return Temp; +} + +// Create response file contents and invoke the MSVC linker. +void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { + std::string Rsp = "/nologo "; + std::vector<std::string> Temps; + + for (auto *Arg : Args) { + switch (Arg->getOption().getID()) { + case OPT_linkrepro: + case OPT_lldmap: + case OPT_lldmap_file: + case OPT_lldsavetemps: + case OPT_msvclto: + // LLD-specific options are stripped. + break; + case OPT_opt: + if (!StringRef(Arg->getValue()).startswith("lld")) + Rsp += toString(Arg) + " "; + break; + case OPT_INPUT: { + if (Optional<StringRef> Path = doFindFile(Arg->getValue())) { + if (Optional<std::string> S = filterBitcodeFiles(*Path, Temps)) + Rsp += quote(*S) + " "; + continue; + } + Rsp += quote(Arg->getValue()) + " "; + break; + } + default: + Rsp += toString(Arg) + " "; + } + } + + std::vector<StringRef> ObjectFiles = Symtab.compileBitcodeFiles(); + runMSVCLinker(Rsp, ObjectFiles); + + for (StringRef Path : Temps) + sys::fs::remove(Path); +} + void LinkerDriver::enqueueTask(std::function<void()> Task) { TaskQueue.push_back(std::move(Task)); } @@ -451,6 +579,22 @@ void LinkerDriver::link(ArrayRef<const c // Parse command line options. opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1)); + // Parse and evaluate -mllvm options. + std::vector<const char *> V; + V.push_back("lld-link (LLVM option parsing)"); + for (auto *Arg : Args.filtered(OPT_mllvm)) + V.push_back(Arg->getValue()); + cl::ParseCommandLineOptions(V.size(), V.data()); + + // Handle /errorlimit early, because error() depends on it. + if (auto *Arg = Args.getLastArg(OPT_errorlimit)) { + int N = 20; + StringRef S = Arg->getValue(); + if (S.getAsInteger(10, N)) + error(Arg->getSpelling() + " number expected, but got " + S); + Config->ErrorLimit = N; + } + // Handle /help if (Args.hasArg(OPT_help)) { printHelp(ArgsArr[0]); @@ -467,12 +611,12 @@ void LinkerDriver::link(ArrayRef<const c if (ErrOrWriter) { Tar = std::move(*ErrOrWriter); } else { - errs() << "/linkrepro: failed to open " << Path << ": " - << toString(ErrOrWriter.takeError()) << '\n'; + error("/linkrepro: failed to open " + Path + ": " + + toString(ErrOrWriter.takeError())); } } - if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) + if (!Args.hasArgNoClaim(OPT_INPUT)) fatal("no input files"); // Construct search path list. @@ -508,9 +652,10 @@ void LinkerDriver::link(ArrayRef<const c // Handle /noentry if (Args.hasArg(OPT_noentry)) { - if (!Args.hasArg(OPT_dll)) - fatal("/noentry must be specified with /dll"); - Config->NoEntry = true; + if (Args.hasArg(OPT_dll)) + Config->NoEntry = true; + else + error("/noentry must be specified with /dll"); } // Handle /dll @@ -521,12 +666,17 @@ void LinkerDriver::link(ArrayRef<const c // Handle /fixed if (Args.hasArg(OPT_fixed)) { - if (Args.hasArg(OPT_dynamicbase)) - fatal("/fixed must not be specified with /dynamicbase"); - Config->Relocatable = false; - Config->DynamicBase = false; + if (Args.hasArg(OPT_dynamicbase)) { + error("/fixed must not be specified with /dynamicbase"); + } else { + Config->Relocatable = false; + Config->DynamicBase = false; + } } + if (Args.hasArg(OPT_appcontainer)) + Config->AppContainer = true; + // Handle /machine if (auto *Arg = Args.getLastArg(OPT_machine)) Config->Machine = getMachineType(Arg->getValue()); @@ -596,20 +746,31 @@ void LinkerDriver::link(ArrayRef<const c StringRef OptLevel = StringRef(S).substr(7); if (OptLevel.getAsInteger(10, Config->LTOOptLevel) || Config->LTOOptLevel > 3) - fatal("/opt:lldlto: invalid optimization level: " + OptLevel); + error("/opt:lldlto: invalid optimization level: " + OptLevel); continue; } if (StringRef(S).startswith("lldltojobs=")) { StringRef Jobs = StringRef(S).substr(11); if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0) - fatal("/opt:lldltojobs: invalid job count: " + Jobs); + error("/opt:lldltojobs: invalid job count: " + Jobs); + continue; + } + if (StringRef(S).startswith("lldltopartitions=")) { + StringRef N = StringRef(S).substr(17); + if (N.getAsInteger(10, Config->LTOPartitions) || + Config->LTOPartitions == 0) + error("/opt:lldltopartitions: invalid partition count: " + N); continue; } if (S != "ref" && S != "lbr" && S != "nolbr") - fatal("/opt: unknown option: " + S); + error("/opt: unknown option: " + S); } } + // Handle /lldsavetemps + if (Args.hasArg(OPT_lldsavetemps)) + Config->SaveTemps = true; + // Handle /failifmismatch for (auto *Arg : Args.filtered(OPT_failifmismatch)) checkFailIfMismatch(Arg->getValue()); @@ -658,6 +819,11 @@ void LinkerDriver::link(ArrayRef<const c Config->DumpPdb = Args.hasArg(OPT_dumppdb); Config->DebugPdb = Args.hasArg(OPT_debugpdb); + Config->MapFile = getMapFile(Args); + + if (ErrorCount) + return; + // Create a list of input files. Files can be given as arguments // for /defaultlib option. std::vector<MemoryBufferRef> MBs; @@ -678,7 +844,7 @@ void LinkerDriver::link(ArrayRef<const c // We should have inferred a machine type by now from the input files, but if // not we assume x64. if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { - errs() << "warning: /machine is not specified. x64 is assumed.\n"; + warn("/machine is not specified. x64 is assumed"); Config->Machine = AMD64; } @@ -715,8 +881,7 @@ void LinkerDriver::link(ArrayRef<const c if (S.empty()) fatal("entry point must be defined"); Config->Entry = addUndefined(S); - if (Config->Verbose) - outs() << "Entry name inferred: " << S << "\n"; + log("Entry name inferred: " + S); } // Handle /export @@ -749,6 +914,22 @@ void LinkerDriver::link(ArrayRef<const c } } + // Set default image name if neither /out or /def set it. + if (Config->OutputFile.empty()) { + Config->OutputFile = + getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue()); + } + + // Put the PDB next to the image if no /pdb flag was passed. + if (Config->Debug && Config->PDBPath.empty()) { + Config->PDBPath = Config->OutputFile; + sys::path::replace_extension(Config->PDBPath, ".pdb"); + } + + // Disable PDB generation if the user requested it. + if (Args.hasArg(OPT_nopdb)) + Config->PDBPath = ""; + // Set default image base if /base is not given. if (Config->ImageBase == uint64_t(-1)) Config->ImageBase = getDefaultImageBase(); @@ -801,6 +982,16 @@ void LinkerDriver::link(ArrayRef<const c addUndefined(mangle("_load_config_used")); } while (run()); + if (ErrorCount) + return; + + // If /msvclto is given, we use the MSVC linker to link LTO output files. + // This is useful because MSVC link.exe can generate complete PDBs. + if (Args.hasArg(OPT_msvclto)) { + invokeMSVC(Args); + exit(0); + } + // Do LTO by compiling bitcode input files to a set of native COFF files then // link those files. Symtab.addCombinedLTOObjects(); @@ -818,10 +1009,13 @@ void LinkerDriver::link(ArrayRef<const c } // Handle /safeseh. - if (Args.hasArg(OPT_safeseh)) + if (Args.hasArg(OPT_safeseh)) { for (ObjectFile *File : Symtab.ObjectFiles) if (!File->SEHCompat) - fatal("/safeseh: " + File->getName() + " is not compatible with SEH"); + error("/safeseh: " + File->getName() + " is not compatible with SEH"); + if (ErrorCount) + return; + } // Windows specific -- when we are creating a .dll file, we also // need to create a .lib file. @@ -846,17 +1040,6 @@ void LinkerDriver::link(ArrayRef<const c // Write the result. writeResult(&Symtab); - // Create a symbol map file containing symbol VAs and their names - // to help debugging. - std::string MapFile = getMapFile(Args); - if (!MapFile.empty()) { - std::error_code EC; - raw_fd_ostream Out(MapFile, EC, OpenFlags::F_Text); - if (EC) - fatal(EC, "could not create the symbol map " + MapFile); - Symtab.printMap(Out); - } - // Call exit to avoid calling destructors. exit(0); } Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.h ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.h Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Driver.h Sun Apr 16 16:35:48 2017 (r317031) @@ -107,6 +107,8 @@ private: StringRef findDefaultEntry(); WindowsSubsystem inferSubsystem(); + void invokeMSVC(llvm::opt::InputArgList &Args); + MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> MB); void addBuffer(std::unique_ptr<MemoryBuffer> MB); void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, @@ -178,6 +180,8 @@ void checkFailIfMismatch(StringRef Arg); std::unique_ptr<MemoryBuffer> convertResToCOFF(const std::vector<MemoryBufferRef> &MBs); +void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects); + // Create enum with OPT_xxx values for each option in Options.td enum { OPT_INVALID = 0, Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/DriverUtils.cpp ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/DriverUtils.cpp Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/DriverUtils.cpp Sun Apr 16 16:35:48 2017 (r317031) @@ -44,31 +44,33 @@ namespace { class Executor { public: explicit Executor(StringRef S) : Saver(Alloc), Prog(Saver.save(S)) {} - void add(StringRef S) { Args.push_back(Saver.save(S).data()); } - void add(std::string &S) { Args.push_back(Saver.save(S).data()); } - void add(Twine S) { Args.push_back(Saver.save(S).data()); } - void add(const char *S) { Args.push_back(Saver.save(S).data()); } + void add(StringRef S) { Args.push_back(Saver.save(S)); } + void add(std::string &S) { Args.push_back(Saver.save(S)); } + void add(Twine S) { Args.push_back(Saver.save(S)); } + void add(const char *S) { Args.push_back(Saver.save(S)); } void run() { ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog); if (auto EC = ExeOrErr.getError()) fatal(EC, "unable to find " + Prog + " in PATH: "); - const char *Exe = Saver.save(*ExeOrErr).data(); + StringRef Exe = Saver.save(*ExeOrErr); Args.insert(Args.begin(), Exe); - Args.push_back(nullptr); - if (sys::ExecuteAndWait(Args[0], Args.data()) != 0) { - for (const char *S : Args) - if (S) - errs() << S << " "; - fatal("ExecuteAndWait failed"); - } + + std::vector<const char *> Vec; + for (StringRef S : Args) + Vec.push_back(S.data()); + Vec.push_back(nullptr); + + if (sys::ExecuteAndWait(Args[0], Vec.data()) != 0) + fatal("ExecuteAndWait failed: " + + llvm::join(Args.begin(), Args.end(), " ")); } private: BumpPtrAllocator Alloc; StringSaver Saver; StringRef Prog; - std::vector<const char *> Args; + std::vector<StringRef> Args; }; } // anonymous namespace @@ -167,8 +169,7 @@ void parseMerge(StringRef S) { if (!Inserted) { StringRef Existing = Pair.first->second; if (Existing != To) - errs() << "warning: " << S << ": already merged into " << Existing - << "\n"; + warn(S + ": already merged into " + Existing); } } @@ -282,11 +283,19 @@ static void quoteAndPrint(raw_ostream &O namespace { class TemporaryFile { public: - TemporaryFile(StringRef Prefix, StringRef Extn) { + TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") { SmallString<128> S; if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S)) fatal(EC, "cannot create a temporary file"); Path = S.str(); + + if (!Contents.empty()) { + std::error_code EC; + raw_fd_ostream OS(Path, EC, sys::fs::F_None); + if (EC) + fatal(EC, "failed to open " + Path); + OS << Contents; + } } TemporaryFile(TemporaryFile &&Obj) { @@ -542,7 +551,7 @@ void fixupExports() { Export *Existing = Pair.first->second; if (E == *Existing || E.Name != Existing->Name) continue; - errs() << "warning: duplicate /export option: " << E.Name << "\n"; + warn("duplicate /export option: " + E.Name); } Config->Exports = std::move(V); @@ -617,6 +626,26 @@ convertResToCOFF(const std::vector<Memor return File.getMemoryBuffer(); } +// Run MSVC link.exe for given in-memory object files. +// Command line options are copied from those given to LLD. +// This is for the /msvclto option. +void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) { + // Write the in-memory object files to disk. + std::vector<TemporaryFile> Temps; + for (StringRef S : Objects) { + Temps.emplace_back("lto", "obj", S); + Rsp += quote(Temps.back().Path) + " "; + } + + log("link.exe " + Rsp); + + // Run MSVC link.exe. + Temps.emplace_back("lto", "rsp", Rsp); + Executor E("link.exe"); + E.add(Twine("@" + Temps.back().Path)); + E.run(); +} + // Create OptTable // Create prefix string literals used in Options.td @@ -653,16 +682,16 @@ opt::InputArgList ArgParser::parse(Array // Print the real command line if response files are expanded. if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) { - outs() << "Command line:"; + std::string Msg = "Command line:"; for (const char *S : Argv) - outs() << " " << S; - outs() << "\n"; + Msg += " " + std::string(S); + message(Msg); } if (MissingCount) fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); for (auto *Arg : Args.filtered(OPT_UNKNOWN)) - errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; + warn("ignoring unknown argument: " + Arg->getSpelling()); return Args; } Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.cpp ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.cpp Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.cpp Sun Apr 16 16:35:48 2017 (r317031) @@ -8,11 +8,14 @@ //===----------------------------------------------------------------------===// #include "Error.h" +#include "Config.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" +#include <mutex> #if !defined(_MSC_VER) && !defined(__MINGW32__) #include <unistd.h> @@ -21,10 +24,68 @@ using namespace llvm; namespace lld { +// The functions defined in this file can be called from multiple threads, +// but outs() or errs() are not thread-safe. We protect them using a mutex. +static std::mutex Mu; + namespace coff { +StringRef Argv0; +uint64_t ErrorCount; +raw_ostream *ErrorOS; + +static LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) { + // Dealloc/destroy ManagedStatic variables before calling + // _exit(). In a non-LTO build, this is a nop. In an LTO + // build allows us to get the output of -time-passes. + llvm_shutdown(); + + outs().flush(); + errs().flush(); + _exit(Val); +} + +static void print(StringRef S, raw_ostream::Colors C) { + *ErrorOS << Argv0 + ": "; + if (Config->ColorDiagnostics) { + ErrorOS->changeColor(C, true); + *ErrorOS << S; + ErrorOS->resetColor(); + } else { + *ErrorOS << S; + } +} + +void log(const Twine &Msg) { + if (Config->Verbose) { + std::lock_guard<std::mutex> Lock(Mu); + outs() << Argv0 << ": " << Msg << "\n"; + } +} + +void message(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + outs() << Msg << "\n"; + outs().flush(); +} + +void error(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + + if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << Msg << "\n"; + } else if (ErrorCount == Config->ErrorLimit) { + print("error: ", raw_ostream::RED); + *ErrorOS << "too many errors emitted, stopping now" + << " (use /ERRORLIMIT:0 to see all errors)\n"; + exitLld(1); + } + + ++ErrorCount; +} void fatal(const Twine &Msg) { - if (sys::Process::StandardErrHasColors()) { + if (Config->ColorDiagnostics) { errs().changeColor(raw_ostream::RED, /*bold=*/true); errs() << "error: "; errs().resetColor(); @@ -32,10 +93,7 @@ void fatal(const Twine &Msg) { errs() << "error: "; } errs() << Msg << "\n"; - - outs().flush(); - errs().flush(); - _exit(1); + exitLld(1); } void fatal(std::error_code EC, const Twine &Msg) { @@ -46,5 +104,11 @@ void fatal(llvm::Error &Err, const Twine fatal(errorToErrorCode(std::move(Err)), Msg); } +void warn(const Twine &Msg) { + std::lock_guard<std::mutex> Lock(Mu); + print("warning: ", raw_ostream::MAGENTA); + *ErrorOS << Msg << "\n"; +} + } // namespace coff } // namespace lld Modified: projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.h ============================================================================== --- projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.h Sun Apr 16 16:31:20 2017 (r317030) +++ projects/clang500-import/contrib/llvm/tools/lld/COFF/Error.h Sun Apr 16 16:35:48 2017 (r317031) @@ -16,11 +16,19 @@ namespace lld { namespace coff { +extern uint64_t ErrorCount; +extern llvm::raw_ostream *ErrorOS; +extern llvm::StringRef Argv0; + +void log(const Twine &Msg); +void message(const Twine &Msg); +void warn(const Twine &Msg); +void error(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg); LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix); LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix); -template <class T> T check(ErrorOr<T> &&V, const Twine &Prefix) { +template <class T> T check(ErrorOr<T> V, const Twine &Prefix) { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704161635.v3GGZmcI010003>