[LLD][COFF] allow saving intermediate files with /lldsavetemps (#115131)

* Parity with the `-save-temps=` flag in the `ELF` `lld` driver.
This commit is contained in:
Miguel A. Arroyo 2024-11-12 12:30:48 -08:00 committed by GitHub
parent 70d6789c7a
commit 5cd6e21bdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 89 additions and 6 deletions

View File

@ -166,7 +166,7 @@ struct Configuration {
Symbol *delayLoadHelper = nullptr;
Symbol *arm64ECIcallHelper = nullptr;
bool saveTemps = false;
llvm::DenseSet<llvm::StringRef> saveTempsArgs;
// /guard:cf
int guardCF = GuardCFLevel::Off;

View File

@ -1525,6 +1525,10 @@ getVFS(const opt::InputArgList &args) {
return nullptr;
}
constexpr const char *lldsaveTempsValues[] = {
"resolution", "preopt", "promote", "internalize", "import",
"opt", "precodegen", "prelink", "combinedindex"};
void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
ScopedTimer rootTimer(ctx.rootTimer);
Configuration *config = &ctx.config;
@ -2012,8 +2016,18 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
config->ltoDebugPassManager = ltoDebugPM;
// Handle /lldsavetemps
if (args.hasArg(OPT_lldsavetemps))
config->saveTemps = true;
if (args.hasArg(OPT_lldsavetemps)) {
for (const char *s : lldsaveTempsValues)
config->saveTempsArgs.insert(s);
} else {
for (auto *arg : args.filtered(OPT_lldsavetemps_colon)) {
StringRef s = arg->getValue();
if (llvm::is_contained(lldsaveTempsValues, s))
config->saveTempsArgs.insert(s);
else
error("unknown /lldsavetemps value: " + s);
}
}
// Handle /lldemit
if (auto *arg = args.getLastArg(OPT_lldemit)) {

View File

@ -102,9 +102,10 @@ lto::Config BitcodeCompiler::createConfig() {
c.Options.MCOptions.AsmVerbose = true;
}
if (ctx.config.saveTemps)
if (!ctx.config.saveTempsArgs.empty())
checkError(c.addSaveTemps(std::string(ctx.config.outputFile) + ".",
/*UseInputModulePath*/ true));
/*UseInputModulePath*/ true,
ctx.config.saveTempsArgs));
return c;
}
@ -255,7 +256,7 @@ std::vector<InputFile *> BitcodeCompiler::compile() {
sys::path::remove_dots(path, true);
ltoObjName = saver().save(path.str());
}
if (ctx.config.saveTemps || emitASM)
if (llvm::is_contained(ctx.config.saveTempsArgs, "prelink") || emitASM)
saveBuffer(buf[i].second, ltoObjName);
if (!emitASM)
ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));

View File

@ -79,6 +79,9 @@ def lldltocachepolicy : P<"lldltocachepolicy",
"Pruning policy for the ThinLTO cache">;
def lldsavetemps : F<"lldsavetemps">,
HelpText<"Save intermediate LTO compilation results">;
def lldsavetemps_colon : Joined<["/", "-", "/?", "-?"], "lldsavetemps:">,
HelpText<"Save select intermediate LTO compilation results">,
Values<"resolution,preopt,promote,internalize,import,opt,precodegen,prelink,combinedindex">;
def lto_sample_profile: P<"lto-sample-profile", "Sample profile file path">;
def machine : P<"machine", "Specify target platform">;
def merge : P<"merge", "Combine sections">;

View File

@ -42,6 +42,7 @@ Breaking changes
COFF Improvements
-----------------
* ``/includeglob`` has been implemented to match the behavior of ``--undefined-glob`` available for ELF.
* ``/lldsavetemps`` allows saving select intermediate LTO compilation results (e.g. resolution, preopt, promote, internalize, import, opt, precodegen, prelink, combinedindex).
MinGW Improvements
------------------

View File

@ -0,0 +1,64 @@
; REQUIRES: x86
; RUN: rm -fr %T/savetemps-colon
; RUN: mkdir %T/savetemps-colon
; RUN: opt -thinlto-bc -o %T/savetemps-colon/savetemps.obj %s
; RUN: opt -thinlto-bc -o %T/savetemps-colon/thin1.obj %S/Inputs/thinlto.ll
;; Check preopt
; RUN: lld-link /lldsavetemps:preopt /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.obj.*.preopt.bc | count 2
;; Check promote
; RUN: lld-link /lldsavetemps:promote /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.obj.*.promote.bc | count 2
;; Check internalize
; RUN: lld-link /lldsavetemps:internalize /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.obj.*.internalize.bc | count 2
;; Check import
; RUN: lld-link /lldsavetemps:import /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.obj.*.import.bc | count 2
;; Check opt
;; Not supported on Windows due to difficulty with escaping "opt" across platforms.
;; Check precodegen
; RUN: lld-link /lldsavetemps:precodegen /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.obj.*.precodegen.bc | count 2
;; Check combinedindex
; RUN: lld-link /lldsavetemps:combinedindex /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.exe.index.bc | count 1
;; Check prelink
; RUN: lld-link /lldsavetemps:prelink /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.exe.lto.*.obj | count 2
;; Check resolution
; RUN: lld-link /lldsavetemps:resolution /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj
; RUN: ls %T/savetemps-colon/*.resolution.txt | count 1
;; Check error message
; RUN: not lld-link /lldsavetemps:notastage /out:%T/savetemps-colon/savetemps.exe /entry:main \
; RUN: /subsystem:console %T/savetemps-colon/savetemps.obj %T/savetemps-colon/thin1.obj 2>&1 \
; RUN: | FileCheck %s
; CHECK: unknown /lldsavetemps value: notastage
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-msvc"
declare void @g()
define i32 @main() {
call void @g()
ret i32 0
}