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 //===----------------------------------------------------------------------===//
11 #include "InputFiles.h"
13 #include "lld/Common/Args.h"
14 #include "lld/Common/CommonLinkerContext.h"
15 #include "lld/Common/ErrorHandler.h"
16 #include "lld/Common/Filesystem.h"
17 #include "lld/Common/Strings.h"
18 #include "lld/Common/TargetOptionsCommandFlags.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Bitcode/BitcodeWriter.h"
24 #include "llvm/IR/DiagnosticPrinter.h"
25 #include "llvm/LTO/Config.h"
26 #include "llvm/LTO/LTO.h"
27 #include "llvm/Object/SymbolicFile.h"
28 #include "llvm/Support/Caching.h"
29 #include "llvm/Support/CodeGen.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/FileSystem.h"
32 #include "llvm/Support/MemoryBuffer.h"
33 #include "llvm/Support/Path.h"
34 #include "llvm/Support/raw_ostream.h"
39 #include <system_error>
43 using namespace lld::wasm
;
46 static std::string
getThinLTOOutputFile(StringRef modulePath
) {
47 return lto::getThinLTOOutputFile(modulePath
, config
->thinLTOPrefixReplaceOld
,
48 config
->thinLTOPrefixReplaceNew
);
51 static lto::Config
createConfig() {
53 c
.Options
= initTargetOptionsFromCodeGenFlags();
55 // Always emit a section per function/data with LTO.
56 c
.Options
.FunctionSections
= true;
57 c
.Options
.DataSections
= true;
59 c
.DisableVerify
= config
->disableVerify
;
60 c
.DiagHandler
= diagnosticHandler
;
61 c
.OptLevel
= config
->ltoo
;
62 c
.MAttrs
= getMAttrs();
63 c
.CGOptLevel
= config
->ltoCgo
;
64 c
.DebugPassManager
= config
->ltoDebugPassManager
;
65 c
.AlwaysEmitRegularLTOObj
= !config
->ltoObjPath
.empty();
67 if (config
->relocatable
)
68 c
.RelocModel
= std::nullopt
;
70 c
.RelocModel
= Reloc::PIC_
;
72 c
.RelocModel
= Reloc::Static
;
74 if (config
->saveTemps
)
75 checkError(c
.addSaveTemps(config
->outputFile
.str() + ".",
76 /*UseInputModulePath*/ true));
82 BitcodeCompiler::BitcodeCompiler() {
83 // Initialize indexFile.
84 if (!config
->thinLTOIndexOnlyArg
.empty())
85 indexFile
= openFile(config
->thinLTOIndexOnlyArg
);
88 lto::ThinBackend backend
;
89 auto onIndexWrite
= [&](StringRef s
) { thinIndices
.erase(s
); };
90 if (config
->thinLTOIndexOnly
) {
91 backend
= lto::createWriteIndexesThinBackend(
92 llvm::hardware_concurrency(config
->thinLTOJobs
),
93 std::string(config
->thinLTOPrefixReplaceOld
),
94 std::string(config
->thinLTOPrefixReplaceNew
),
95 std::string(config
->thinLTOPrefixReplaceNativeObject
),
96 config
->thinLTOEmitImportsFiles
, indexFile
.get(), onIndexWrite
);
98 backend
= lto::createInProcessThinBackend(
99 llvm::heavyweight_hardware_concurrency(config
->thinLTOJobs
),
100 onIndexWrite
, config
->thinLTOEmitIndexFiles
,
101 config
->thinLTOEmitImportsFiles
);
103 ltoObj
= std::make_unique
<lto::LTO
>(createConfig(), backend
,
104 config
->ltoPartitions
);
107 BitcodeCompiler::~BitcodeCompiler() = default;
109 static void undefine(Symbol
*s
) {
110 if (auto f
= dyn_cast
<DefinedFunction
>(s
))
111 replaceSymbol
<UndefinedFunction
>(f
, f
->getName(), std::nullopt
,
112 std::nullopt
, 0, f
->getFile(),
114 else if (isa
<DefinedData
>(s
))
115 replaceSymbol
<UndefinedData
>(s
, s
->getName(), 0, s
->getFile());
117 llvm_unreachable("unexpected symbol kind");
120 void BitcodeCompiler::add(BitcodeFile
&f
) {
121 lto::InputFile
&obj
= *f
.obj
;
123 ArrayRef
<Symbol
*> syms
= f
.getSymbols();
124 std::vector
<lto::SymbolResolution
> resols(syms
.size());
126 if (config
->thinLTOEmitIndexFiles
) {
127 thinIndices
.insert(obj
.getName());
130 // Provide a resolution to the LTO API for each symbol.
131 for (const lto::InputFile::Symbol
&objSym
: obj
.symbols()) {
132 Symbol
*sym
= syms
[symNum
];
133 lto::SymbolResolution
&r
= resols
[symNum
];
136 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
137 // reports two symbols for module ASM defined. Without this check, lld
138 // flags an undefined in IR with a definition in ASM as prevailing.
139 // Once IRObjectFile is fixed to report only one symbol this hack can
141 r
.Prevailing
= !objSym
.isUndefined() && sym
->getFile() == &f
;
142 r
.VisibleToRegularObj
= config
->relocatable
|| sym
->isUsedInRegularObj
||
144 (r
.Prevailing
&& sym
->isExported());
148 // We tell LTO to not apply interprocedural optimization for wrapped
149 // (with --wrap) symbols because otherwise LTO would inline them while
150 // their values are still not final.
151 r
.LinkerRedefined
= !sym
->canInline
;
153 checkError(ltoObj
->add(std::move(f
.obj
), resols
));
156 // If LazyObjFile has not been added to link, emit empty index files.
157 // This is needed because this is what GNU gold plugin does and we have a
158 // distributed build system that depends on that behavior.
159 static void thinLTOCreateEmptyIndexFiles() {
160 DenseSet
<StringRef
> linkedBitCodeFiles
;
161 for (BitcodeFile
*f
: ctx
.bitcodeFiles
)
162 linkedBitCodeFiles
.insert(f
->getName());
164 for (BitcodeFile
*f
: ctx
.lazyBitcodeFiles
) {
167 if (linkedBitCodeFiles
.contains(f
->getName()))
170 replaceThinLTOSuffix(getThinLTOOutputFile(f
->obj
->getName()));
171 std::unique_ptr
<raw_fd_ostream
> os
= openFile(path
+ ".thinlto.bc");
175 ModuleSummaryIndex
m(/*HaveGVs*/ false);
176 m
.setSkipModuleByDistributedBackend();
177 writeIndexToFile(m
, *os
);
178 if (config
->thinLTOEmitImportsFiles
)
179 openFile(path
+ ".imports");
183 // Merge all the bitcode files we have seen, codegen the result
184 // and return the resulting objects.
185 std::vector
<StringRef
> BitcodeCompiler::compile() {
186 unsigned maxTasks
= ltoObj
->getMaxTasks();
187 buf
.resize(maxTasks
);
188 files
.resize(maxTasks
);
190 // The --thinlto-cache-dir option specifies the path to a directory in which
191 // to cache native object files for ThinLTO incremental builds. If a path was
192 // specified, configure LTO to use it as the cache directory.
194 if (!config
->thinLTOCacheDir
.empty())
195 cache
= check(localCache("ThinLTO", "Thin", config
->thinLTOCacheDir
,
196 [&](size_t task
, const Twine
&moduleName
,
197 std::unique_ptr
<MemoryBuffer
> mb
) {
198 files
[task
] = std::move(mb
);
201 checkError(ltoObj
->run(
202 [&](size_t task
, const Twine
&moduleName
) {
203 buf
[task
].first
= moduleName
.str();
204 return std::make_unique
<CachedFileStream
>(
205 std::make_unique
<raw_svector_ostream
>(buf
[task
].second
));
209 // Emit empty index files for non-indexed files but not in single-module mode.
210 for (StringRef s
: thinIndices
) {
212 openFile(path
+ ".thinlto.bc");
213 if (config
->thinLTOEmitImportsFiles
)
214 openFile(path
+ ".imports");
217 if (config
->thinLTOEmitIndexFiles
)
218 thinLTOCreateEmptyIndexFiles();
220 if (config
->thinLTOIndexOnly
) {
221 if (!config
->ltoObjPath
.empty())
222 saveBuffer(buf
[0].second
, config
->ltoObjPath
);
224 // ThinLTO with index only option is required to generate only the index
225 // files. After that, we exit from linker and ThinLTO backend runs in a
226 // distributed environment.
232 if (!config
->thinLTOCacheDir
.empty())
233 pruneCache(config
->thinLTOCacheDir
, config
->thinLTOCachePolicy
, files
);
235 std::vector
<StringRef
> ret
;
236 for (unsigned i
= 0; i
!= maxTasks
; ++i
) {
237 StringRef objBuf
= buf
[i
].second
;
238 StringRef bitcodeFilePath
= buf
[i
].first
;
241 ret
.emplace_back(objBuf
.data(), objBuf
.size());
242 if (!config
->saveTemps
)
245 // If the input bitcode file is path/to/x.o and -o specifies a.out, the
246 // corresponding native relocatable file path will look like:
247 // path/to/a.out.lto.x.o.
248 StringRef ltoObjName
;
249 if (bitcodeFilePath
== "ld-temp.o") {
251 saver().save(Twine(config
->outputFile
) + ".lto" +
252 (i
== 0 ? Twine("") : Twine('.') + Twine(i
)) + ".o");
254 StringRef directory
= sys::path::parent_path(bitcodeFilePath
);
255 // For an archive member, which has an identifier like "d/a.a(coll.o at
256 // 8)" (see BitcodeFile::BitcodeFile), use the filename; otherwise, use
257 // the stem (d/a.o => a).
258 StringRef baseName
= bitcodeFilePath
.ends_with(")")
259 ? sys::path::filename(bitcodeFilePath
)
260 : sys::path::stem(bitcodeFilePath
);
261 StringRef outputFileBaseName
= sys::path::filename(config
->outputFile
);
262 SmallString
<256> path
;
263 sys::path::append(path
, directory
,
264 outputFileBaseName
+ ".lto." + baseName
+ ".o");
265 sys::path::remove_dots(path
, true);
266 ltoObjName
= saver().save(path
.str());
268 saveBuffer(objBuf
, ltoObjName
);
271 if (!config
->ltoObjPath
.empty()) {
272 saveBuffer(buf
[0].second
, config
->ltoObjPath
);
273 for (unsigned i
= 1; i
!= maxTasks
; ++i
)
274 saveBuffer(buf
[i
].second
, config
->ltoObjPath
+ Twine(i
));
277 for (std::unique_ptr
<MemoryBuffer
> &file
: files
)
279 ret
.push_back(file
->getBuffer());
284 } // namespace lld::wasm