mirror of
https://github.com/intel/llvm.git
synced 2026-01-13 19:08:21 +08:00
[lld] Support separate native object file path in --thinlto-prefix-replace
Currently, the --thinlto-prefix-replace="oldpath;newpath" option is used during
distributed ThinLTO thin links to specify the mapping of the input bitcode object
files' directory tree (oldpath) to the directory tree (newpath) used for both:
1) the output files of the thin link itself (the .thinlto.bc index files and the
optional .imports files)
2) the specified object file paths written to the response file given in the
--thinlto-index-only=${response} option, which is used by the final native
link and must match the paths of the native object files that will be
produced by ThinLTO backend compiles.
This patch expands the --thinlto-prefix-replace option to allow a separate directory
tree mapping to be specified for the object file paths written to the response file
(number 2 above). This is important to support builds and build systems where the
same output directory may not be written by multiple build actions (e.g. the thin link
and the ThinLTO backend compiles).
The new format is: --thinlto-prefix-replace="origpath;outpath[;objpath]"
This replaces the origpath directory tree of the thin link input files with
outpath when writing the thin link index and imports outputs (number 1
above). If objpath is specified it replaces origpath of the input files with
objpath when writing the response file (number 2 above), otherwise it
falls back to the old behavior of using outpath for this as well.
Reviewed By: tejohnson, MaskRay
Differential Revision: https://reviews.llvm.org/D144596
This commit is contained in:
committed by
Teresa Johnson
parent
a401e10f12
commit
73fd9d310f
@@ -218,8 +218,16 @@ struct Configuration {
|
||||
// Used for /thinlto-index-only:
|
||||
llvm::StringRef thinLTOIndexOnlyArg;
|
||||
|
||||
// Used for /thinlto-object-prefix-replace:
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
|
||||
// Used for /thinlto-prefix-replace:
|
||||
// Replace the prefix in paths generated for ThinLTO, replacing
|
||||
// thinLTOPrefixReplaceOld with thinLTOPrefixReplaceNew. If
|
||||
// thinLTOPrefixReplaceNativeObject is defined, replace the prefix of object
|
||||
// file paths written to the response file given in the
|
||||
// --thinlto-index-only=${response} option with
|
||||
// thinLTOPrefixReplaceNativeObject, instead of thinLTOPrefixReplaceNew.
|
||||
llvm::StringRef thinLTOPrefixReplaceOld;
|
||||
llvm::StringRef thinLTOPrefixReplaceNew;
|
||||
llvm::StringRef thinLTOPrefixReplaceNativeObject;
|
||||
|
||||
// Used for /thinlto-object-suffix-replace:
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
@@ -90,6 +91,14 @@ static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Parse options of the form "old;new[;extra]".
|
||||
static std::tuple<StringRef, StringRef, StringRef>
|
||||
getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {
|
||||
auto [oldDir, second] = getOldNewOptions(args, id);
|
||||
auto [newDir, extraDir] = second.split(';');
|
||||
return {oldDir, newDir, extraDir};
|
||||
}
|
||||
|
||||
// Drop directory components and replace extension with
|
||||
// ".exe", ".dll" or ".sys".
|
||||
static std::string getOutputPath(StringRef path, bool isDll, bool isDriver) {
|
||||
@@ -1884,8 +1893,9 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
args.hasArg(OPT_thinlto_index_only_arg);
|
||||
config->thinLTOIndexOnlyArg =
|
||||
args.getLastArgValue(OPT_thinlto_index_only_arg);
|
||||
config->thinLTOPrefixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_prefix_replace);
|
||||
std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,
|
||||
config->thinLTOPrefixReplaceNativeObject) =
|
||||
getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace);
|
||||
config->thinLTOObjectSuffixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_object_suffix_replace);
|
||||
config->ltoObjPath = args.getLastArgValue(OPT_lto_obj_path);
|
||||
|
||||
@@ -56,8 +56,8 @@ static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
|
||||
|
||||
std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) {
|
||||
return lto::getThinLTOOutputFile(
|
||||
std::string(path), std::string(ctx.config.thinLTOPrefixReplace.first),
|
||||
std::string(ctx.config.thinLTOPrefixReplace.second));
|
||||
std::string(path), std::string(ctx.config.thinLTOPrefixReplaceOld),
|
||||
std::string(ctx.config.thinLTOPrefixReplaceNew));
|
||||
}
|
||||
|
||||
lto::Config BitcodeCompiler::createConfig() {
|
||||
@@ -114,8 +114,9 @@ BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {
|
||||
if (ctx.config.thinLTOIndexOnly) {
|
||||
auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
|
||||
backend = lto::createWriteIndexesThinBackend(
|
||||
std::string(ctx.config.thinLTOPrefixReplace.first),
|
||||
std::string(ctx.config.thinLTOPrefixReplace.second),
|
||||
std::string(ctx.config.thinLTOPrefixReplaceOld),
|
||||
std::string(ctx.config.thinLTOPrefixReplaceNew),
|
||||
std::string(ctx.config.thinLTOPrefixReplaceNativeObject),
|
||||
ctx.config.thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);
|
||||
} else {
|
||||
backend = lto::createInProcessThinBackend(
|
||||
|
||||
@@ -177,7 +177,9 @@ struct Config {
|
||||
StringRef zCetReport = "none";
|
||||
llvm::StringRef ltoBasicBlockSections;
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
|
||||
llvm::StringRef thinLTOPrefixReplaceOld;
|
||||
llvm::StringRef thinLTOPrefixReplaceNew;
|
||||
llvm::StringRef thinLTOPrefixReplaceNativeObject;
|
||||
std::string rpath;
|
||||
llvm::SmallVector<VersionDefinition, 0> versionDefinitions;
|
||||
llvm::SmallVector<llvm::StringRef, 0> auxiliaryList;
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "llvm/Support/TimeProfiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cstdlib>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
using namespace llvm;
|
||||
@@ -1023,6 +1024,14 @@ static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Parse options of the form "old;new[;extra]".
|
||||
static std::tuple<StringRef, StringRef, StringRef>
|
||||
getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {
|
||||
auto [oldDir, second] = getOldNewOptions(args, id);
|
||||
auto [newDir, extraDir] = second.split(';');
|
||||
return {oldDir, newDir, extraDir};
|
||||
}
|
||||
|
||||
// Parse the symbol ordering file and warn for any duplicate entries.
|
||||
static SmallVector<StringRef, 0> getSymbolOrderingFile(MemoryBufferRef mb) {
|
||||
SetVector<StringRef, SmallVector<StringRef, 0>> names;
|
||||
@@ -1249,8 +1258,9 @@ static void readConfigs(opt::InputArgList &args) {
|
||||
config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);
|
||||
config->thinLTOObjectSuffixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq);
|
||||
config->thinLTOPrefixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_prefix_replace_eq);
|
||||
std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,
|
||||
config->thinLTOPrefixReplaceNativeObject) =
|
||||
getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq);
|
||||
if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) {
|
||||
if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))
|
||||
error("--thinlto-object-suffix-replace is not supported with "
|
||||
@@ -1259,6 +1269,11 @@ static void readConfigs(opt::InputArgList &args) {
|
||||
error("--thinlto-prefix-replace is not supported with "
|
||||
"--thinlto-emit-index-files");
|
||||
}
|
||||
if (!config->thinLTOPrefixReplaceNativeObject.empty() &&
|
||||
config->thinLTOIndexOnlyArg.empty()) {
|
||||
error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
|
||||
"--thinlto-index-only=");
|
||||
}
|
||||
config->thinLTOModulesToCompile =
|
||||
args::getStrings(args, OPT_thinlto_single_module_eq);
|
||||
config->timeTraceEnabled = args.hasArg(OPT_time_trace_eq);
|
||||
|
||||
@@ -68,8 +68,8 @@ static std::unique_ptr<raw_fd_ostream> openLTOOutputFile(StringRef file) {
|
||||
|
||||
static std::string getThinLTOOutputFile(StringRef modulePath) {
|
||||
return lto::getThinLTOOutputFile(
|
||||
std::string(modulePath), std::string(config->thinLTOPrefixReplace.first),
|
||||
std::string(config->thinLTOPrefixReplace.second));
|
||||
std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld),
|
||||
std::string(config->thinLTOPrefixReplaceNew));
|
||||
}
|
||||
|
||||
static lto::Config createConfig() {
|
||||
@@ -196,8 +196,9 @@ BitcodeCompiler::BitcodeCompiler() {
|
||||
auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
|
||||
if (config->thinLTOIndexOnly) {
|
||||
backend = lto::createWriteIndexesThinBackend(
|
||||
std::string(config->thinLTOPrefixReplace.first),
|
||||
std::string(config->thinLTOPrefixReplace.second),
|
||||
std::string(config->thinLTOPrefixReplaceOld),
|
||||
std::string(config->thinLTOPrefixReplaceNew),
|
||||
std::string(config->thinLTOPrefixReplaceNativeObject),
|
||||
config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
|
||||
} else {
|
||||
backend = lto::createInProcessThinBackend(
|
||||
|
||||
@@ -173,7 +173,9 @@ struct Configuration {
|
||||
llvm::StringRef thinLTOCacheDir;
|
||||
llvm::StringRef thinLTOIndexOnlyArg;
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
|
||||
std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
|
||||
llvm::StringRef thinLTOPrefixReplaceOld;
|
||||
llvm::StringRef thinLTOPrefixReplaceNew;
|
||||
llvm::StringRef thinLTOPrefixReplaceNativeObject;
|
||||
bool deadStripDylibs = false;
|
||||
bool demangle = false;
|
||||
bool deadStrip = false;
|
||||
|
||||
@@ -868,6 +868,14 @@ static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Parse options of the form "old;new[;extra]".
|
||||
static std::tuple<StringRef, StringRef, StringRef>
|
||||
getOldNewOptionsExtra(opt::InputArgList &args, unsigned id) {
|
||||
auto [oldDir, second] = getOldNewOptions(args, id);
|
||||
auto [newDir, extraDir] = second.split(';');
|
||||
return {oldDir, newDir, extraDir};
|
||||
}
|
||||
|
||||
static void parseClangOption(StringRef opt, const Twine &msg) {
|
||||
std::string err;
|
||||
raw_string_ostream os(err);
|
||||
@@ -1578,8 +1586,9 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
|
||||
config->thinLTOIndexOnlyArg = args.getLastArgValue(OPT_thinlto_index_only_eq);
|
||||
config->thinLTOObjectSuffixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_object_suffix_replace_eq);
|
||||
config->thinLTOPrefixReplace =
|
||||
getOldNewOptions(args, OPT_thinlto_prefix_replace_eq);
|
||||
std::tie(config->thinLTOPrefixReplaceOld, config->thinLTOPrefixReplaceNew,
|
||||
config->thinLTOPrefixReplaceNativeObject) =
|
||||
getOldNewOptionsExtra(args, OPT_thinlto_prefix_replace_eq);
|
||||
if (config->thinLTOEmitIndexFiles && !config->thinLTOIndexOnly) {
|
||||
if (args.hasArg(OPT_thinlto_object_suffix_replace_eq))
|
||||
error("--thinlto-object-suffix-replace is not supported with "
|
||||
@@ -1588,6 +1597,11 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
|
||||
error("--thinlto-prefix-replace is not supported with "
|
||||
"--thinlto-emit-index-files");
|
||||
}
|
||||
if (!config->thinLTOPrefixReplaceNativeObject.empty() &&
|
||||
config->thinLTOIndexOnlyArg.empty()) {
|
||||
error("--thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with "
|
||||
"--thinlto-index-only=");
|
||||
}
|
||||
config->runtimePaths = args::getStrings(args, OPT_rpath);
|
||||
config->allLoad = args.hasFlag(OPT_all_load, OPT_noall_load, false);
|
||||
config->archMultiple = args.hasArg(OPT_arch_multiple);
|
||||
|
||||
@@ -47,8 +47,8 @@ static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
|
||||
|
||||
static std::string getThinLTOOutputFile(StringRef modulePath) {
|
||||
return lto::getThinLTOOutputFile(
|
||||
std::string(modulePath), std::string(config->thinLTOPrefixReplace.first),
|
||||
std::string(config->thinLTOPrefixReplace.second));
|
||||
std::string(modulePath), std::string(config->thinLTOPrefixReplaceOld),
|
||||
std::string(config->thinLTOPrefixReplaceNew));
|
||||
}
|
||||
|
||||
static lto::Config createConfig() {
|
||||
@@ -99,8 +99,9 @@ BitcodeCompiler::BitcodeCompiler() {
|
||||
auto onIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
|
||||
if (config->thinLTOIndexOnly) {
|
||||
backend = lto::createWriteIndexesThinBackend(
|
||||
std::string(config->thinLTOPrefixReplace.first),
|
||||
std::string(config->thinLTOPrefixReplace.second),
|
||||
std::string(config->thinLTOPrefixReplaceOld),
|
||||
std::string(config->thinLTOPrefixReplaceNew),
|
||||
std::string(config->thinLTOPrefixReplaceNativeObject),
|
||||
config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
|
||||
} else {
|
||||
backend = lto::createInProcessThinBackend(
|
||||
|
||||
46
lld/test/COFF/thinlto-index-file-object-prefix-replace.ll
Normal file
46
lld/test/COFF/thinlto-index-file-object-prefix-replace.ll
Normal file
@@ -0,0 +1,46 @@
|
||||
; REQUIRES: x86
|
||||
; RUN: rm -rf %t && mkdir %t
|
||||
; RUN: mkdir -p %t/old/subdir
|
||||
; RUN: opt -module-summary %s -o %t/old/subdir/1.obj
|
||||
; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t/old/subdir/2.obj
|
||||
; RUN: opt -module-summary %p/Inputs/thinlto-empty.ll -o %t/old/3.obj
|
||||
|
||||
;; Ensure lld writes linked files to linked objects file.
|
||||
; RUN: lld-link -entry:main -thinlto-index-only:%t/1.txt %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe
|
||||
; RUN: ls %t/old/subdir/1.obj.thinlto.bc
|
||||
; RUN: ls %t/old/subdir/2.obj.thinlto.bc
|
||||
; RUN: ls %t/old/3.obj.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-NO-REPLACE %s < %t/1.txt
|
||||
; CHECK-NO-REPLACE: old/subdir/1.obj
|
||||
; CHECK-NO-REPLACE-NEXT: old/subdir/2.obj
|
||||
; CHECK-NO-REPLACE-NEXT: old/3.obj
|
||||
|
||||
;; Check that this also works with thinlto-prefix-replace.
|
||||
; RUN: lld-link -entry:main -thinlto-index-only:%t/2.txt -thinlto-prefix-replace:"%t/old/;%t/new/" %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe
|
||||
; RUN: ls %t/new/subdir/1.obj.thinlto.bc
|
||||
; RUN: ls %t/new/subdir/2.obj.thinlto.bc
|
||||
; RUN: ls %t/new/3.obj.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-REPLACE-PREFIX %s < %t/2.txt
|
||||
; CHECK-REPLACE-PREFIX: new/subdir/1.obj
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.obj
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/3.obj
|
||||
|
||||
;; Check that this also works with replacing the prefix of linked objects.
|
||||
; RUN: lld-link -entry:main -thinlto-index-only:%t/3.txt -thinlto-prefix-replace:"%t/old/;%t/new/;%t/obj/" %t/old/subdir/1.obj %t/old/subdir/2.obj %t/old/3.obj -out:%t/t.exe
|
||||
; RUN: ls %t/new/subdir/1.obj.thinlto.bc
|
||||
; RUN: ls %t/new/subdir/2.obj.thinlto.bc
|
||||
; RUN: ls %t/new/3.obj.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < %t/3.txt
|
||||
; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.obj
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.obj
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.obj
|
||||
|
||||
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-windows-msvc19.0.24215"
|
||||
|
||||
declare void @g(...)
|
||||
|
||||
define void @main() {
|
||||
call void (...) @g()
|
||||
ret void
|
||||
}
|
||||
51
lld/test/ELF/lto/thinlto-index-file-object-prefix-replace.ll
Normal file
51
lld/test/ELF/lto/thinlto-index-file-object-prefix-replace.ll
Normal file
@@ -0,0 +1,51 @@
|
||||
; REQUIRES: x86
|
||||
; RUN: rm -rf %t && mkdir %t && cd %t
|
||||
; RUN: mkdir -p old/subdir
|
||||
; RUN: opt -module-summary %s -o old/subdir/1.o
|
||||
; RUN: opt -module-summary %p/Inputs/thinlto.ll -o old/subdir/2.o
|
||||
; RUN: opt -module-summary %p/Inputs/thinlto_empty.ll -o old/3.o
|
||||
|
||||
;; Ensure lld writes linked files to linked objects file.
|
||||
; RUN: ld.lld --thinlto-index-only=1.txt -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null
|
||||
; RUN: ls old/subdir/1.o.thinlto.bc
|
||||
; RUN: ls old/subdir/2.o.thinlto.bc
|
||||
; RUN: ls old/3.o.thinlto.bc
|
||||
; RUN: FileCheck --match-full-lines --check-prefix=CHECK-NO-REPLACE %s < 1.txt
|
||||
; CHECK-NO-REPLACE: old/subdir/1.o
|
||||
; CHECK-NO-REPLACE-NEXT: old/subdir/2.o
|
||||
; CHECK-NO-REPLACE-NEXT: old/3.o
|
||||
|
||||
;; Check that this also works with thinlto-prefix-replace.
|
||||
; RUN: ld.lld --thinlto-index-only=2.txt --thinlto-prefix-replace="old/;new/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null
|
||||
; RUN: ls new/subdir/1.o.thinlto.bc
|
||||
; RUN: ls new/subdir/2.o.thinlto.bc
|
||||
; RUN: ls new/3.o.thinlto.bc
|
||||
; RUN: FileCheck --match-full-lines --check-prefix=CHECK-REPLACE-PREFIX %s < 2.txt
|
||||
; CHECK-REPLACE-PREFIX: new/subdir/1.o
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.o
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/3.o
|
||||
|
||||
;; Check that this also works with replacing the prefix of linked objects.
|
||||
; RUN: ld.lld --thinlto-index-only=3.txt --thinlto-prefix-replace="old/;new/;obj/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null
|
||||
; RUN: ls new/subdir/1.o.thinlto.bc
|
||||
; RUN: ls new/subdir/2.o.thinlto.bc
|
||||
; RUN: ls new/3.o.thinlto.bc
|
||||
; RUN: FileCheck --match-full-lines --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < 3.txt
|
||||
; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.o
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.o
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.o
|
||||
|
||||
; Create an error if prefix replace option have 'old;new;obj' format but index file is not set. Ensure that the error is about thinlto-prefix-replace.
|
||||
; RUN: not ld.lld --thinlto-prefix-replace="old/;new/;obj/" -shared old/subdir/1.o old/subdir/2.o old/3.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERROR
|
||||
; ERROR: error: --thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with --thinlto-index-only=
|
||||
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @g(...)
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
call void (...) @g()
|
||||
ret void
|
||||
}
|
||||
67
lld/test/MachO/thinlto-index-file-object-prefix-replace.ll
Normal file
67
lld/test/MachO/thinlto-index-file-object-prefix-replace.ll
Normal file
@@ -0,0 +1,67 @@
|
||||
; REQUIRES: x86
|
||||
; RUN: rm -rf %t && split-file %s %t
|
||||
; RUN: mkdir -p %t/old/subdir
|
||||
|
||||
; RUN: opt -module-summary %t/f.ll -o %t/old/subdir/1.o
|
||||
; RUN: opt -module-summary %t/g.ll -o %t/old/subdir/2.o
|
||||
; RUN: opt -module-summary %t/empty.ll -o %t/old/3.o
|
||||
|
||||
;; Ensure lld writes linked files to linked objects file.
|
||||
; RUN: %lld --thinlto-index-only=%t/1.txt -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null
|
||||
; RUN: ls %t/old/subdir/1.o.thinlto.bc
|
||||
; RUN: ls %t/old/subdir/2.o.thinlto.bc
|
||||
; RUN: ls %t/old/3.o.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-NO-REPLACE %s < %t/1.txt
|
||||
; CHECK-NO-REPLACE: old/subdir/1.o
|
||||
; CHECK-NO-REPLACE-NEXT: old/subdir/2.o
|
||||
; CHECK-NO-REPLACE-NEXT: old/3.o
|
||||
|
||||
;; Check that this also works with thinlto-prefix-replace.
|
||||
; RUN: %lld --thinlto-index-only=%t/2.txt --thinlto-prefix-replace="%t/old/;%t/new/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null
|
||||
; RUN: ls %t/new/subdir/1.o.thinlto.bc
|
||||
; RUN: ls %t/new/subdir/2.o.thinlto.bc
|
||||
; RUN: ls %t/new/3.o.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-REPLACE-PREFIX %s < %t/2.txt
|
||||
; CHECK-REPLACE-PREFIX: new/subdir/1.o
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/subdir/2.o
|
||||
; CHECK-REPLACE-PREFIX-NEXT: new/3.o
|
||||
|
||||
|
||||
;; Check that this also works with replacing the prefix of linked objects.
|
||||
; RUN: %lld --thinlto-index-only=%t/3.txt --thinlto-prefix-replace="%t/old/;%t/new/;%t/obj/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null
|
||||
; RUN: ls %t/new/subdir/1.o.thinlto.bc
|
||||
; RUN: ls %t/new/subdir/2.o.thinlto.bc
|
||||
; RUN: ls %t/new/3.o.thinlto.bc
|
||||
; RUN: FileCheck --check-prefix=CHECK-REPLACE-OBJECT-PREFIX %s < %t/3.txt
|
||||
; CHECK-REPLACE-OBJECT-PREFIX: obj/subdir/1.o
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/subdir/2.o
|
||||
; CHECK-REPLACE-OBJECT-PREFIX-NEXT: obj/3.o
|
||||
|
||||
; Create an error if prefix replace option have 'old;new;obj' format but index file is not set. Ensure that the error is about thinlto-prefix-replace.
|
||||
; RUN: not %lld --thinlto-prefix-replace="%t/old/;%t/new/;%t/obj/" -dylib %t/old/subdir/1.o %t/old/subdir/2.o %t/old/3.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERROR
|
||||
; ERROR: error: --thinlto-prefix-replace=old_dir;new_dir;obj_dir must be used with --thinlto-index-only=
|
||||
|
||||
;--- f.ll
|
||||
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-darwin"
|
||||
|
||||
declare void @g(...)
|
||||
|
||||
define void @f() {
|
||||
entry:
|
||||
call void (...) @g()
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- g.ll
|
||||
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-darwin"
|
||||
|
||||
define void @g() {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
;--- empty.ll
|
||||
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-apple-darwin"
|
||||
@@ -219,11 +219,14 @@ ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism,
|
||||
/// ShouldEmitImportsFiles is true it also writes a list of imported files to a
|
||||
/// similar path with ".imports" appended instead.
|
||||
/// LinkedObjectsFile is an output stream to write the list of object files for
|
||||
/// the final ThinLTO linking. Can be nullptr.
|
||||
/// OnWrite is callback which receives module identifier and notifies LTO user
|
||||
/// that index file for the module (and optionally imports file) was created.
|
||||
/// the final ThinLTO linking. Can be nullptr. If LinkedObjectsFile is not
|
||||
/// nullptr and NativeObjectPrefix is not empty then it replaces the prefix of
|
||||
/// the objects with NativeObjectPrefix instead of NewPrefix. OnWrite is
|
||||
/// callback which receives module identifier and notifies LTO user that index
|
||||
/// file for the module (and optionally imports file) was created.
|
||||
ThinBackend createWriteIndexesThinBackend(std::string OldPrefix,
|
||||
std::string NewPrefix,
|
||||
std::string NativeObjectPrefix,
|
||||
bool ShouldEmitImportsFiles,
|
||||
raw_fd_ostream *LinkedObjectsFile,
|
||||
IndexWriteCallback OnWrite);
|
||||
|
||||
@@ -1422,18 +1422,20 @@ std::string lto::getThinLTOOutputFile(const std::string &Path,
|
||||
|
||||
namespace {
|
||||
class WriteIndexesThinBackend : public ThinBackendProc {
|
||||
std::string OldPrefix, NewPrefix;
|
||||
std::string OldPrefix, NewPrefix, NativeObjectPrefix;
|
||||
raw_fd_ostream *LinkedObjectsFile;
|
||||
|
||||
public:
|
||||
WriteIndexesThinBackend(
|
||||
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
|
||||
const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
|
||||
std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles,
|
||||
std::string OldPrefix, std::string NewPrefix,
|
||||
std::string NativeObjectPrefix, bool ShouldEmitImportsFiles,
|
||||
raw_fd_ostream *LinkedObjectsFile, lto::IndexWriteCallback OnWrite)
|
||||
: ThinBackendProc(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
|
||||
OnWrite, ShouldEmitImportsFiles),
|
||||
OldPrefix(OldPrefix), NewPrefix(NewPrefix),
|
||||
NativeObjectPrefix(NativeObjectPrefix),
|
||||
LinkedObjectsFile(LinkedObjectsFile) {}
|
||||
|
||||
Error start(
|
||||
@@ -1446,8 +1448,13 @@ public:
|
||||
std::string NewModulePath =
|
||||
getThinLTOOutputFile(std::string(ModulePath), OldPrefix, NewPrefix);
|
||||
|
||||
if (LinkedObjectsFile)
|
||||
*LinkedObjectsFile << NewModulePath << '\n';
|
||||
if (LinkedObjectsFile) {
|
||||
std::string ObjectPrefix =
|
||||
NativeObjectPrefix.empty() ? NewPrefix : NativeObjectPrefix;
|
||||
std::string LinkedObjectsFilePath = getThinLTOOutputFile(
|
||||
std::string(ModulePath), OldPrefix, ObjectPrefix);
|
||||
*LinkedObjectsFile << LinkedObjectsFilePath << '\n';
|
||||
}
|
||||
|
||||
if (auto E = emitFiles(ImportList, ModulePath, NewModulePath))
|
||||
return E;
|
||||
@@ -1466,14 +1473,15 @@ public:
|
||||
} // end anonymous namespace
|
||||
|
||||
ThinBackend lto::createWriteIndexesThinBackend(
|
||||
std::string OldPrefix, std::string NewPrefix, bool ShouldEmitImportsFiles,
|
||||
std::string OldPrefix, std::string NewPrefix,
|
||||
std::string NativeObjectPrefix, bool ShouldEmitImportsFiles,
|
||||
raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite) {
|
||||
return [=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
|
||||
const StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
|
||||
AddStreamFn AddStream, FileCache Cache) {
|
||||
return std::make_unique<WriteIndexesThinBackend>(
|
||||
Conf, CombinedIndex, ModuleToDefinedGVSummaries, OldPrefix, NewPrefix,
|
||||
ShouldEmitImportsFiles, LinkedObjectsFile, OnWrite);
|
||||
NativeObjectPrefix, ShouldEmitImportsFiles, LinkedObjectsFile, OnWrite);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -891,9 +891,12 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
|
||||
if (options::thinlto_index_only) {
|
||||
std::string OldPrefix, NewPrefix;
|
||||
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
|
||||
Backend = createWriteIndexesThinBackend(OldPrefix, NewPrefix,
|
||||
options::thinlto_emit_imports_files,
|
||||
LinkedObjectsFile, OnIndexWrite);
|
||||
Backend = createWriteIndexesThinBackend(
|
||||
OldPrefix, NewPrefix,
|
||||
// TODO: Add support for optional native object path in
|
||||
// thinlto_prefix_replace option to match lld.
|
||||
/*NativeObjectPrefix=*/"", options::thinlto_emit_imports_files,
|
||||
LinkedObjectsFile, OnIndexWrite);
|
||||
} else {
|
||||
Backend = createInProcessThinBackend(
|
||||
llvm::heavyweight_hardware_concurrency(options::Parallelism));
|
||||
|
||||
@@ -320,11 +320,12 @@ static int run(int argc, char **argv) {
|
||||
|
||||
ThinBackend Backend;
|
||||
if (ThinLTODistributedIndexes)
|
||||
Backend =
|
||||
createWriteIndexesThinBackend(/* OldPrefix */ "",
|
||||
/* NewPrefix */ "", ThinLTOEmitImports,
|
||||
/* LinkedObjectsFile */ nullptr,
|
||||
/* OnWrite */ {});
|
||||
Backend = createWriteIndexesThinBackend(/*OldPrefix=*/"",
|
||||
/*NewPrefix=*/"",
|
||||
/*NativeObjectPrefix=*/"",
|
||||
ThinLTOEmitImports,
|
||||
/*LinkedObjectsFile=*/nullptr,
|
||||
/*OnWrite=*/{});
|
||||
else
|
||||
Backend = createInProcessThinBackend(
|
||||
llvm::heavyweight_hardware_concurrency(Threads),
|
||||
|
||||
Reference in New Issue
Block a user