1 //===- LTO.cpp ------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
12 #include "InputFiles.h"
16 #include "lld/Common/Args.h"
17 #include "lld/Common/CommonLinkerContext.h"
18 #include "lld/Common/Strings.h"
19 #include "lld/Common/TargetOptionsCommandFlags.h"
20 #include "llvm/LTO/Config.h"
21 #include "llvm/LTO/LTO.h"
22 #include "llvm/Support/Caching.h"
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/Transforms/ObjCARC.h"
29 using namespace lld::macho
;
31 using namespace llvm::MachO
;
32 using namespace llvm::sys
;
34 static lto::Config
createConfig() {
36 c
.Options
= initTargetOptionsFromCodeGenFlags();
37 c
.Options
.EmitAddrsig
= config
->icfLevel
== ICFLevel::safe
;
38 c
.CodeModel
= getCodeModelFromCMModel();
40 c
.MAttrs
= getMAttrs();
41 c
.DiagHandler
= diagnosticHandler
;
42 c
.PreCodeGenPassesHook
= [](legacy::PassManager
&pm
) {
43 pm
.add(createObjCARCContractPass());
45 c
.TimeTraceEnabled
= config
->timeTraceEnabled
;
46 c
.TimeTraceGranularity
= config
->timeTraceGranularity
;
47 c
.OptLevel
= config
->ltoo
;
48 c
.CGOptLevel
= args::getCGOptLevel(config
->ltoo
);
49 if (config
->saveTemps
)
50 checkError(c
.addSaveTemps(config
->outputFile
.str() + ".",
51 /*UseInputModulePath=*/true));
55 BitcodeCompiler::BitcodeCompiler() {
56 lto::ThinBackend backend
= lto::createInProcessThinBackend(
57 heavyweight_hardware_concurrency(config
->thinLTOJobs
));
58 ltoObj
= std::make_unique
<lto::LTO
>(createConfig(), backend
);
61 void BitcodeCompiler::add(BitcodeFile
&f
) {
62 ArrayRef
<lto::InputFile::Symbol
> objSyms
= f
.obj
->symbols();
63 std::vector
<lto::SymbolResolution
> resols
;
64 resols
.reserve(objSyms
.size());
66 // Provide a resolution to the LTO API for each symbol.
68 config
->outputType
!= MH_EXECUTE
|| config
->exportDynamic
;
69 auto symIt
= f
.symbols
.begin();
70 for (const lto::InputFile::Symbol
&objSym
: objSyms
) {
71 resols
.emplace_back();
72 lto::SymbolResolution
&r
= resols
.back();
73 Symbol
*sym
= *symIt
++;
75 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
76 // reports two symbols for module ASM defined. Without this check, lld
77 // flags an undefined in IR with a definition in ASM as prevailing.
78 // Once IRObjectFile is fixed to report only one symbol this hack can
80 r
.Prevailing
= !objSym
.isUndefined() && sym
->getFile() == &f
;
82 if (const auto *defined
= dyn_cast
<Defined
>(sym
)) {
84 defined
->isExternal() && !defined
->privateExtern
&& exportDynamic
;
85 r
.FinalDefinitionInLinkageUnit
=
86 !defined
->isExternalWeakDef() && !defined
->interposable
;
87 } else if (const auto *common
= dyn_cast
<CommonSymbol
>(sym
)) {
88 r
.ExportDynamic
= !common
->privateExtern
&& exportDynamic
;
89 r
.FinalDefinitionInLinkageUnit
= true;
92 r
.VisibleToRegularObj
=
93 sym
->isUsedInRegularObj
|| (r
.Prevailing
&& r
.ExportDynamic
);
95 // Un-define the symbol so that we don't get duplicate symbol errors when we
96 // load the ObjFile emitted by LTO compilation.
98 replaceSymbol
<Undefined
>(sym
, sym
->getName(), sym
->getFile(),
101 // TODO: set the other resolution configs properly
103 checkError(ltoObj
->add(std::move(f
.obj
), resols
));
106 // Merge all the bitcode files we have seen, codegen the result
107 // and return the resulting ObjectFile(s).
108 std::vector
<ObjFile
*> BitcodeCompiler::compile() {
109 unsigned maxTasks
= ltoObj
->getMaxTasks();
110 buf
.resize(maxTasks
);
111 files
.resize(maxTasks
);
113 // The -cache_path_lto option specifies the path to a directory in which
114 // to cache native object files for ThinLTO incremental builds. If a path was
115 // specified, configure LTO to use it as the cache directory.
117 if (!config
->thinLTOCacheDir
.empty())
119 check(localCache("ThinLTO", "Thin", config
->thinLTOCacheDir
,
120 [&](size_t task
, std::unique_ptr
<MemoryBuffer
> mb
) {
121 files
[task
] = std::move(mb
);
124 checkError(ltoObj
->run(
126 return std::make_unique
<CachedFileStream
>(
127 std::make_unique
<raw_svector_ostream
>(buf
[task
]));
131 if (!config
->thinLTOCacheDir
.empty())
132 pruneCache(config
->thinLTOCacheDir
, config
->thinLTOCachePolicy
);
134 if (config
->saveTemps
) {
136 saveBuffer(buf
[0], config
->outputFile
+ ".lto.o");
137 for (unsigned i
= 1; i
!= maxTasks
; ++i
)
138 saveBuffer(buf
[i
], config
->outputFile
+ Twine(i
) + ".lto.o");
141 // In ThinLTO mode, Clang passes a temporary directory in -object_path_lto,
142 // while the argument is a single file in FullLTO mode.
143 bool objPathIsDir
= true;
144 if (!config
->ltoObjPath
.empty()) {
145 if (std::error_code ec
= fs::create_directories(config
->ltoObjPath
))
146 fatal("cannot create LTO object path " + config
->ltoObjPath
+ ": " +
149 if (!fs::is_directory(config
->ltoObjPath
)) {
150 objPathIsDir
= false;
152 count_if(buf
, [](const SmallString
<0> &b
) { return !b
.empty(); });
154 fatal("-object_path_lto must specify a directory when using ThinLTO");
158 std::vector
<ObjFile
*> ret
;
159 for (unsigned i
= 0; i
!= maxTasks
; ++i
) {
162 SmallString
<261> filePath("/tmp/lto.tmp");
163 uint32_t modTime
= 0;
164 if (!config
->ltoObjPath
.empty()) {
165 filePath
= config
->ltoObjPath
;
167 path::append(filePath
, Twine(i
) + "." +
168 getArchitectureName(config
->arch()) +
170 saveBuffer(buf
[i
], filePath
);
171 modTime
= getModTime(filePath
);
173 ret
.push_back(make
<ObjFile
>(
174 MemoryBufferRef(buf
[i
], saver().save(filePath
.str())), modTime
, ""));
176 for (std::unique_ptr
<MemoryBuffer
> &file
: files
)
178 ret
.push_back(make
<ObjFile
>(*file
, 0, ""));