diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -45,6 +45,7 @@ uint32_t headerPad; llvm::StringRef installName; llvm::StringRef outputFile; + llvm::StringRef ltoObjPath; bool demangle = false; llvm::MachO::Architecture arch; PlatformInfo platform; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -703,6 +703,7 @@ config->printEachFile = args.hasArg(OPT_t); config->printWhyLoad = args.hasArg(OPT_why_load); config->outputType = getOutputType(args); + config->ltoObjPath = args.getLastArgValue(OPT_object_path_lto); config->runtimePaths = args::getStrings(args, OPT_rpath); config->allLoad = args.hasArg(OPT_all_load); config->forceLoadObjC = args.hasArg(OPT_ObjC); diff --git a/lld/MachO/LTO.cpp b/lld/MachO/LTO.cpp --- a/lld/MachO/LTO.cpp +++ b/lld/MachO/LTO.cpp @@ -8,17 +8,21 @@ #include "LTO.h" #include "Config.h" +#include "Driver.h" #include "InputFiles.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Strings.h" #include "lld/Common/TargetOptionsCommandFlags.h" #include "llvm/LTO/LTO.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" using namespace lld; using namespace lld::macho; using namespace llvm; +using namespace llvm::sys; static lto::Config createConfig() { lto::Config c; @@ -73,12 +77,26 @@ saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o"); } - // TODO: set modTime properly + if (!config->ltoObjPath.empty()) + fs::create_directories(config->ltoObjPath); + std::vector ret; - for (unsigned i = 0; i != maxTasks; ++i) - if (!buf[i].empty()) - ret.push_back( - make(MemoryBufferRef(buf[i], "lto.tmp"), /*modTime=*/0, "")); + for (unsigned i = 0; i != maxTasks; ++i) { + if (buf[i].empty()) { + continue; + } + SmallString<261> filePath("/tmp/lto.tmp"); + uint32_t modTime = 0; + if (!config->ltoObjPath.empty()) { + filePath = config->ltoObjPath; + path::append(filePath, Twine(i) + "." + + getArchitectureName(config->arch) + ".lto.o"); + saveBuffer(buf[i], filePath); + modTime = getModTime(filePath); + } + ret.push_back(make( + MemoryBufferRef(buf[i], saver.save(filePath.str())), modTime, "")); + } return ret; } diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -840,7 +840,6 @@ def object_path_lto : Separate<["-"], "object_path_lto">, MetaVarName<"">, HelpText<"Retain any temporary mach-o file in that would otherwise be deleted during LTO">, - Flags<[HelpHidden]>, Group; def lto_library : Separate<["-"], "lto_library">, MetaVarName<"">, diff --git a/lld/test/MachO/lto-object-path.ll b/lld/test/MachO/lto-object-path.ll new file mode 100644 --- /dev/null +++ b/lld/test/MachO/lto-object-path.ll @@ -0,0 +1,37 @@ +; REQUIRES: x86 + +; RUN: rm -rf %t; mkdir %t +; RUN: llvm-as %s -o %t/test.o + +; RUN: %lld %t/test.o -o %t/test +; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,NOOBJPATH + +; RUN: %lld %t/test.o -o %t/test -object_path_lto %t/lto-temps +; RUN: llvm-nm -pa %t/test | FileCheck %s --check-prefixes CHECK,OBJPATH -DDIR=%t/lto-temps + +; CHECK: 0000000000000000 - 00 0000 SO /tmp/test.cpp +; NOOBJPATH-NEXT: 0000000000000000 - 03 0001 OSO /tmp/lto.tmp +;; check that modTime is nonzero when `-object_path_lto` is provided +; OBJPATH-NEXT: {{[0-9a-f]*[1-9a-f]+[0-9a-f]*}} - 03 0001 OSO [[DIR]]/0.x86_64.lto.o +; CHECK-NEXT: {{[0-9a-f]+}} - 01 0000 FUN _main +; CHECK-NEXT: 0000000000000001 - 00 0000 FUN +; CHECK-NEXT: 0000000000000000 - 01 0000 SO +; CHECK-NEXT: {{[0-9a-f]+}} T _main + +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define void @main() #0 !dbg !4 { + ret void +} + +!llvm.module.flags = !{ !0, !1 } +!llvm.dbg.cu = !{!2} + +!0 = !{i32 7, !"Dwarf Version", i32 4} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, emissionKind: FullDebug) +!3 = !DIFile(filename: "test.cpp", directory: "/tmp") +!4 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 1, type: !5, scopeLine: 1, unit: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{}