xref: /aosp_15_r20/external/llvm/tools/llvm-lto/llvm-lto.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- llvm-lto: a simple command-line program to link modules with LTO --===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This program takes in a list of bitcode files, links them, performs link-time
11*9880d681SAndroid Build Coastguard Worker // optimization, and outputs an object file.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSet.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Bitcode/ReaderWriter.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CommandFlags.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DiagnosticPrinter.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Verifier.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IRReader/IRReader.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/LTO/legacy/LTOCodeGenerator.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/LTO/legacy/LTOModule.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Object/ModuleSummaryIndexObjectFile.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FileSystem.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ManagedStatic.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/PrettyStackTrace.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Signals.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetSelect.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ToolOutputFile.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
36*9880d681SAndroid Build Coastguard Worker #include <list>
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker using namespace llvm;
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker static cl::opt<char>
41*9880d681SAndroid Build Coastguard Worker     OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
42*9880d681SAndroid Build Coastguard Worker                            "(default = '-O2')"),
43*9880d681SAndroid Build Coastguard Worker              cl::Prefix, cl::ZeroOrMore, cl::init('2'));
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableVerify(
46*9880d681SAndroid Build Coastguard Worker     "disable-verify", cl::init(false),
47*9880d681SAndroid Build Coastguard Worker     cl::desc("Do not run the verifier during the optimization pipeline"));
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
50*9880d681SAndroid Build Coastguard Worker                                    cl::desc("Do not run the inliner pass"));
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
53*9880d681SAndroid Build Coastguard Worker     DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
54*9880d681SAndroid Build Coastguard Worker                       cl::desc("Do not run the GVN load PRE pass"));
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableLTOVectorization(
57*9880d681SAndroid Build Coastguard Worker     "disable-lto-vectorization", cl::init(false),
58*9880d681SAndroid Build Coastguard Worker     cl::desc("Do not run loop or slp vectorization during LTO"));
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> UseDiagnosticHandler(
61*9880d681SAndroid Build Coastguard Worker     "use-diagnostic-handler", cl::init(false),
62*9880d681SAndroid Build Coastguard Worker     cl::desc("Use a diagnostic handler to test the handler interface"));
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
65*9880d681SAndroid Build Coastguard Worker     ThinLTO("thinlto", cl::init(false),
66*9880d681SAndroid Build Coastguard Worker             cl::desc("Only write combined global index for ThinLTO backends"));
67*9880d681SAndroid Build Coastguard Worker 
68*9880d681SAndroid Build Coastguard Worker enum ThinLTOModes {
69*9880d681SAndroid Build Coastguard Worker   THINLINK,
70*9880d681SAndroid Build Coastguard Worker   THINDISTRIBUTE,
71*9880d681SAndroid Build Coastguard Worker   THINEMITIMPORTS,
72*9880d681SAndroid Build Coastguard Worker   THINPROMOTE,
73*9880d681SAndroid Build Coastguard Worker   THINIMPORT,
74*9880d681SAndroid Build Coastguard Worker   THININTERNALIZE,
75*9880d681SAndroid Build Coastguard Worker   THINOPT,
76*9880d681SAndroid Build Coastguard Worker   THINCODEGEN,
77*9880d681SAndroid Build Coastguard Worker   THINALL
78*9880d681SAndroid Build Coastguard Worker };
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker cl::opt<ThinLTOModes> ThinLTOMode(
81*9880d681SAndroid Build Coastguard Worker     "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
82*9880d681SAndroid Build Coastguard Worker     cl::values(
83*9880d681SAndroid Build Coastguard Worker         clEnumValN(
84*9880d681SAndroid Build Coastguard Worker             THINLINK, "thinlink",
85*9880d681SAndroid Build Coastguard Worker             "ThinLink: produces the index by linking only the summaries."),
86*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINDISTRIBUTE, "distributedindexes",
87*9880d681SAndroid Build Coastguard Worker                    "Produces individual indexes for distributed backends."),
88*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINEMITIMPORTS, "emitimports",
89*9880d681SAndroid Build Coastguard Worker                    "Emit imports files for distributed backends."),
90*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINPROMOTE, "promote",
91*9880d681SAndroid Build Coastguard Worker                    "Perform pre-import promotion (requires -thinlto-index)."),
92*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINIMPORT, "import", "Perform both promotion and "
93*9880d681SAndroid Build Coastguard Worker                                          "cross-module importing (requires "
94*9880d681SAndroid Build Coastguard Worker                                          "-thinlto-index)."),
95*9880d681SAndroid Build Coastguard Worker         clEnumValN(THININTERNALIZE, "internalize",
96*9880d681SAndroid Build Coastguard Worker                    "Perform internalization driven by -exported-symbol "
97*9880d681SAndroid Build Coastguard Worker                    "(requires -thinlto-index)."),
98*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
99*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
100*9880d681SAndroid Build Coastguard Worker         clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end"),
101*9880d681SAndroid Build Coastguard Worker         clEnumValEnd));
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
104*9880d681SAndroid Build Coastguard Worker     ThinLTOIndex("thinlto-index",
105*9880d681SAndroid Build Coastguard Worker                  cl::desc("Provide the index produced by a ThinLink, required "
106*9880d681SAndroid Build Coastguard Worker                           "to perform the promotion and/or importing."));
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> ThinLTOPrefixReplace(
109*9880d681SAndroid Build Coastguard Worker     "thinlto-prefix-replace",
110*9880d681SAndroid Build Coastguard Worker     cl::desc("Control where files for distributed backends are "
111*9880d681SAndroid Build Coastguard Worker              "created. Expects 'oldprefix;newprefix' and if path "
112*9880d681SAndroid Build Coastguard Worker              "prefix of output file is oldprefix it will be "
113*9880d681SAndroid Build Coastguard Worker              "replaced with newprefix."));
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> ThinLTOModuleId(
116*9880d681SAndroid Build Coastguard Worker     "thinlto-module-id",
117*9880d681SAndroid Build Coastguard Worker     cl::desc("For the module ID for the file to process, useful to "
118*9880d681SAndroid Build Coastguard Worker              "match what is in the index."));
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string>
121*9880d681SAndroid Build Coastguard Worker     ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
122*9880d681SAndroid Build Coastguard Worker 
123*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
124*9880d681SAndroid Build Coastguard Worker     SaveModuleFile("save-merged-module", cl::init(false),
125*9880d681SAndroid Build Coastguard Worker                    cl::desc("Write merged LTO module to file before CodeGen"));
126*9880d681SAndroid Build Coastguard Worker 
127*9880d681SAndroid Build Coastguard Worker static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
128*9880d681SAndroid Build Coastguard Worker                                             cl::desc("<input bitcode files>"));
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker static cl::opt<std::string> OutputFilename("o", cl::init(""),
131*9880d681SAndroid Build Coastguard Worker                                            cl::desc("Override output filename"),
132*9880d681SAndroid Build Coastguard Worker                                            cl::value_desc("filename"));
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker static cl::list<std::string> ExportedSymbols(
135*9880d681SAndroid Build Coastguard Worker     "exported-symbol",
136*9880d681SAndroid Build Coastguard Worker     cl::desc("List of symbols to export from the resulting object file"),
137*9880d681SAndroid Build Coastguard Worker     cl::ZeroOrMore);
138*9880d681SAndroid Build Coastguard Worker 
139*9880d681SAndroid Build Coastguard Worker static cl::list<std::string>
140*9880d681SAndroid Build Coastguard Worker     DSOSymbols("dso-symbol",
141*9880d681SAndroid Build Coastguard Worker                cl::desc("Symbol to put in the symtab in the resulting dso"),
142*9880d681SAndroid Build Coastguard Worker                cl::ZeroOrMore);
143*9880d681SAndroid Build Coastguard Worker 
144*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> ListSymbolsOnly(
145*9880d681SAndroid Build Coastguard Worker     "list-symbols-only", cl::init(false),
146*9880d681SAndroid Build Coastguard Worker     cl::desc("Instead of running LTO, list the symbols in each IR file"));
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> SetMergedModule(
149*9880d681SAndroid Build Coastguard Worker     "set-merged-module", cl::init(false),
150*9880d681SAndroid Build Coastguard Worker     cl::desc("Use the first input module as the merged module"));
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
153*9880d681SAndroid Build Coastguard Worker                                      cl::desc("Number of backend threads"));
154*9880d681SAndroid Build Coastguard Worker 
155*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> RestoreGlobalsLinkage(
156*9880d681SAndroid Build Coastguard Worker     "restore-linkage", cl::init(false),
157*9880d681SAndroid Build Coastguard Worker     cl::desc("Restore original linkage of globals prior to CodeGen"));
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> CheckHasObjC(
160*9880d681SAndroid Build Coastguard Worker     "check-for-objc", cl::init(false),
161*9880d681SAndroid Build Coastguard Worker     cl::desc("Only check if the module has objective-C defined in it"));
162*9880d681SAndroid Build Coastguard Worker 
163*9880d681SAndroid Build Coastguard Worker namespace {
164*9880d681SAndroid Build Coastguard Worker struct ModuleInfo {
165*9880d681SAndroid Build Coastguard Worker   std::vector<bool> CanBeHidden;
166*9880d681SAndroid Build Coastguard Worker };
167*9880d681SAndroid Build Coastguard Worker }
168*9880d681SAndroid Build Coastguard Worker 
handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,const char * Msg,void *)169*9880d681SAndroid Build Coastguard Worker static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
170*9880d681SAndroid Build Coastguard Worker                               const char *Msg, void *) {
171*9880d681SAndroid Build Coastguard Worker   errs() << "llvm-lto: ";
172*9880d681SAndroid Build Coastguard Worker   switch (Severity) {
173*9880d681SAndroid Build Coastguard Worker   case LTO_DS_NOTE:
174*9880d681SAndroid Build Coastguard Worker     errs() << "note: ";
175*9880d681SAndroid Build Coastguard Worker     break;
176*9880d681SAndroid Build Coastguard Worker   case LTO_DS_REMARK:
177*9880d681SAndroid Build Coastguard Worker     errs() << "remark: ";
178*9880d681SAndroid Build Coastguard Worker     break;
179*9880d681SAndroid Build Coastguard Worker   case LTO_DS_ERROR:
180*9880d681SAndroid Build Coastguard Worker     errs() << "error: ";
181*9880d681SAndroid Build Coastguard Worker     break;
182*9880d681SAndroid Build Coastguard Worker   case LTO_DS_WARNING:
183*9880d681SAndroid Build Coastguard Worker     errs() << "warning: ";
184*9880d681SAndroid Build Coastguard Worker     break;
185*9880d681SAndroid Build Coastguard Worker   }
186*9880d681SAndroid Build Coastguard Worker   errs() << Msg << "\n";
187*9880d681SAndroid Build Coastguard Worker }
188*9880d681SAndroid Build Coastguard Worker 
189*9880d681SAndroid Build Coastguard Worker static std::string CurrentActivity;
diagnosticHandler(const DiagnosticInfo & DI)190*9880d681SAndroid Build Coastguard Worker static void diagnosticHandler(const DiagnosticInfo &DI) {
191*9880d681SAndroid Build Coastguard Worker   raw_ostream &OS = errs();
192*9880d681SAndroid Build Coastguard Worker   OS << "llvm-lto: ";
193*9880d681SAndroid Build Coastguard Worker   switch (DI.getSeverity()) {
194*9880d681SAndroid Build Coastguard Worker   case DS_Error:
195*9880d681SAndroid Build Coastguard Worker     OS << "error";
196*9880d681SAndroid Build Coastguard Worker     break;
197*9880d681SAndroid Build Coastguard Worker   case DS_Warning:
198*9880d681SAndroid Build Coastguard Worker     OS << "warning";
199*9880d681SAndroid Build Coastguard Worker     break;
200*9880d681SAndroid Build Coastguard Worker   case DS_Remark:
201*9880d681SAndroid Build Coastguard Worker     OS << "remark";
202*9880d681SAndroid Build Coastguard Worker     break;
203*9880d681SAndroid Build Coastguard Worker   case DS_Note:
204*9880d681SAndroid Build Coastguard Worker     OS << "note";
205*9880d681SAndroid Build Coastguard Worker     break;
206*9880d681SAndroid Build Coastguard Worker   }
207*9880d681SAndroid Build Coastguard Worker   if (!CurrentActivity.empty())
208*9880d681SAndroid Build Coastguard Worker     OS << ' ' << CurrentActivity;
209*9880d681SAndroid Build Coastguard Worker   OS << ": ";
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker   DiagnosticPrinterRawOStream DP(OS);
212*9880d681SAndroid Build Coastguard Worker   DI.print(DP);
213*9880d681SAndroid Build Coastguard Worker   OS << '\n';
214*9880d681SAndroid Build Coastguard Worker 
215*9880d681SAndroid Build Coastguard Worker   if (DI.getSeverity() == DS_Error)
216*9880d681SAndroid Build Coastguard Worker     exit(1);
217*9880d681SAndroid Build Coastguard Worker }
218*9880d681SAndroid Build Coastguard Worker 
diagnosticHandlerWithContext(const DiagnosticInfo & DI,void * Context)219*9880d681SAndroid Build Coastguard Worker static void diagnosticHandlerWithContext(const DiagnosticInfo &DI,
220*9880d681SAndroid Build Coastguard Worker                                          void *Context) {
221*9880d681SAndroid Build Coastguard Worker   diagnosticHandler(DI);
222*9880d681SAndroid Build Coastguard Worker }
223*9880d681SAndroid Build Coastguard Worker 
error(const Twine & Msg)224*9880d681SAndroid Build Coastguard Worker static void error(const Twine &Msg) {
225*9880d681SAndroid Build Coastguard Worker   errs() << "llvm-lto: " << Msg << '\n';
226*9880d681SAndroid Build Coastguard Worker   exit(1);
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker 
error(std::error_code EC,const Twine & Prefix)229*9880d681SAndroid Build Coastguard Worker static void error(std::error_code EC, const Twine &Prefix) {
230*9880d681SAndroid Build Coastguard Worker   if (EC)
231*9880d681SAndroid Build Coastguard Worker     error(Prefix + ": " + EC.message());
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker 
234*9880d681SAndroid Build Coastguard Worker template <typename T>
error(const ErrorOr<T> & V,const Twine & Prefix)235*9880d681SAndroid Build Coastguard Worker static void error(const ErrorOr<T> &V, const Twine &Prefix) {
236*9880d681SAndroid Build Coastguard Worker   error(V.getError(), Prefix);
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker 
maybeVerifyModule(const Module & Mod)239*9880d681SAndroid Build Coastguard Worker static void maybeVerifyModule(const Module &Mod) {
240*9880d681SAndroid Build Coastguard Worker   if (!DisableVerify && verifyModule(Mod))
241*9880d681SAndroid Build Coastguard Worker     error("Broken Module");
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker 
244*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<LTOModule>
getLocalLTOModule(StringRef Path,std::unique_ptr<MemoryBuffer> & Buffer,const TargetOptions & Options)245*9880d681SAndroid Build Coastguard Worker getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
246*9880d681SAndroid Build Coastguard Worker                   const TargetOptions &Options) {
247*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
248*9880d681SAndroid Build Coastguard Worker       MemoryBuffer::getFile(Path);
249*9880d681SAndroid Build Coastguard Worker   error(BufferOrErr, "error loading file '" + Path + "'");
250*9880d681SAndroid Build Coastguard Worker   Buffer = std::move(BufferOrErr.get());
251*9880d681SAndroid Build Coastguard Worker   CurrentActivity = ("loading file '" + Path + "'").str();
252*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
253*9880d681SAndroid Build Coastguard Worker   Context->setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);
254*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
255*9880d681SAndroid Build Coastguard Worker       std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
256*9880d681SAndroid Build Coastguard Worker       Options, Path);
257*9880d681SAndroid Build Coastguard Worker   CurrentActivity = "";
258*9880d681SAndroid Build Coastguard Worker   maybeVerifyModule((*Ret)->getModule());
259*9880d681SAndroid Build Coastguard Worker   return std::move(*Ret);
260*9880d681SAndroid Build Coastguard Worker }
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker /// \brief List symbols in each IR file.
263*9880d681SAndroid Build Coastguard Worker ///
264*9880d681SAndroid Build Coastguard Worker /// The main point here is to provide lit-testable coverage for the LTOModule
265*9880d681SAndroid Build Coastguard Worker /// functionality that's exposed by the C API to list symbols.  Moreover, this
266*9880d681SAndroid Build Coastguard Worker /// provides testing coverage for modules that have been created in their own
267*9880d681SAndroid Build Coastguard Worker /// contexts.
listSymbols(const TargetOptions & Options)268*9880d681SAndroid Build Coastguard Worker static void listSymbols(const TargetOptions &Options) {
269*9880d681SAndroid Build Coastguard Worker   for (auto &Filename : InputFilenames) {
270*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<MemoryBuffer> Buffer;
271*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<LTOModule> Module =
272*9880d681SAndroid Build Coastguard Worker         getLocalLTOModule(Filename, Buffer, Options);
273*9880d681SAndroid Build Coastguard Worker 
274*9880d681SAndroid Build Coastguard Worker     // List the symbols.
275*9880d681SAndroid Build Coastguard Worker     outs() << Filename << ":\n";
276*9880d681SAndroid Build Coastguard Worker     for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
277*9880d681SAndroid Build Coastguard Worker       outs() << Module->getSymbolName(I) << "\n";
278*9880d681SAndroid Build Coastguard Worker   }
279*9880d681SAndroid Build Coastguard Worker }
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker /// Create a combined index file from the input IR files and write it.
282*9880d681SAndroid Build Coastguard Worker ///
283*9880d681SAndroid Build Coastguard Worker /// This is meant to enable testing of ThinLTO combined index generation,
284*9880d681SAndroid Build Coastguard Worker /// currently available via the gold plugin via -thinlto.
createCombinedModuleSummaryIndex()285*9880d681SAndroid Build Coastguard Worker static void createCombinedModuleSummaryIndex() {
286*9880d681SAndroid Build Coastguard Worker   ModuleSummaryIndex CombinedIndex;
287*9880d681SAndroid Build Coastguard Worker   uint64_t NextModuleId = 0;
288*9880d681SAndroid Build Coastguard Worker   for (auto &Filename : InputFilenames) {
289*9880d681SAndroid Build Coastguard Worker     CurrentActivity = "loading file '" + Filename + "'";
290*9880d681SAndroid Build Coastguard Worker     ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
291*9880d681SAndroid Build Coastguard Worker         llvm::getModuleSummaryIndexForFile(Filename, diagnosticHandler);
292*9880d681SAndroid Build Coastguard Worker     error(IndexOrErr, "error " + CurrentActivity);
293*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<ModuleSummaryIndex> Index = std::move(IndexOrErr.get());
294*9880d681SAndroid Build Coastguard Worker     CurrentActivity = "";
295*9880d681SAndroid Build Coastguard Worker     // Skip files without a module summary.
296*9880d681SAndroid Build Coastguard Worker     if (!Index)
297*9880d681SAndroid Build Coastguard Worker       continue;
298*9880d681SAndroid Build Coastguard Worker     CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
299*9880d681SAndroid Build Coastguard Worker   }
300*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
301*9880d681SAndroid Build Coastguard Worker   assert(!OutputFilename.empty());
302*9880d681SAndroid Build Coastguard Worker   raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
303*9880d681SAndroid Build Coastguard Worker                     sys::fs::OpenFlags::F_None);
304*9880d681SAndroid Build Coastguard Worker   error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
305*9880d681SAndroid Build Coastguard Worker   WriteIndexToFile(CombinedIndex, OS);
306*9880d681SAndroid Build Coastguard Worker   OS.close();
307*9880d681SAndroid Build Coastguard Worker }
308*9880d681SAndroid Build Coastguard Worker 
309*9880d681SAndroid Build Coastguard Worker /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
310*9880d681SAndroid Build Coastguard Worker /// \p NewPrefix strings, if it was specified.
getThinLTOOldAndNewPrefix(std::string & OldPrefix,std::string & NewPrefix)311*9880d681SAndroid Build Coastguard Worker static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
312*9880d681SAndroid Build Coastguard Worker                                       std::string &NewPrefix) {
313*9880d681SAndroid Build Coastguard Worker   assert(ThinLTOPrefixReplace.empty() ||
314*9880d681SAndroid Build Coastguard Worker          ThinLTOPrefixReplace.find(";") != StringRef::npos);
315*9880d681SAndroid Build Coastguard Worker   StringRef PrefixReplace = ThinLTOPrefixReplace;
316*9880d681SAndroid Build Coastguard Worker   std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
317*9880d681SAndroid Build Coastguard Worker   OldPrefix = Split.first.str();
318*9880d681SAndroid Build Coastguard Worker   NewPrefix = Split.second.str();
319*9880d681SAndroid Build Coastguard Worker }
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker /// Given the original \p Path to an output file, replace any path
322*9880d681SAndroid Build Coastguard Worker /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
323*9880d681SAndroid Build Coastguard Worker /// resulting directory if it does not yet exist.
getThinLTOOutputFile(const std::string & Path,const std::string & OldPrefix,const std::string & NewPrefix)324*9880d681SAndroid Build Coastguard Worker static std::string getThinLTOOutputFile(const std::string &Path,
325*9880d681SAndroid Build Coastguard Worker                                         const std::string &OldPrefix,
326*9880d681SAndroid Build Coastguard Worker                                         const std::string &NewPrefix) {
327*9880d681SAndroid Build Coastguard Worker   if (OldPrefix.empty() && NewPrefix.empty())
328*9880d681SAndroid Build Coastguard Worker     return Path;
329*9880d681SAndroid Build Coastguard Worker   SmallString<128> NewPath(Path);
330*9880d681SAndroid Build Coastguard Worker   llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
331*9880d681SAndroid Build Coastguard Worker   StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
332*9880d681SAndroid Build Coastguard Worker   if (!ParentPath.empty()) {
333*9880d681SAndroid Build Coastguard Worker     // Make sure the new directory exists, creating it if necessary.
334*9880d681SAndroid Build Coastguard Worker     if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
335*9880d681SAndroid Build Coastguard Worker       error(EC, "error creating the directory '" + ParentPath + "'");
336*9880d681SAndroid Build Coastguard Worker   }
337*9880d681SAndroid Build Coastguard Worker   return NewPath.str();
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker namespace thinlto {
341*9880d681SAndroid Build Coastguard Worker 
342*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<MemoryBuffer>>
loadAllFilesForIndex(const ModuleSummaryIndex & Index)343*9880d681SAndroid Build Coastguard Worker loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
344*9880d681SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
345*9880d681SAndroid Build Coastguard Worker 
346*9880d681SAndroid Build Coastguard Worker   for (auto &ModPath : Index.modulePaths()) {
347*9880d681SAndroid Build Coastguard Worker     const auto &Filename = ModPath.first();
348*9880d681SAndroid Build Coastguard Worker     auto CurrentActivity = "loading file '" + Filename + "'";
349*9880d681SAndroid Build Coastguard Worker     auto InputOrErr = MemoryBuffer::getFile(Filename);
350*9880d681SAndroid Build Coastguard Worker     error(InputOrErr, "error " + CurrentActivity);
351*9880d681SAndroid Build Coastguard Worker     InputBuffers.push_back(std::move(*InputOrErr));
352*9880d681SAndroid Build Coastguard Worker   }
353*9880d681SAndroid Build Coastguard Worker   return InputBuffers;
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker 
loadCombinedIndex()356*9880d681SAndroid Build Coastguard Worker std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
357*9880d681SAndroid Build Coastguard Worker   if (ThinLTOIndex.empty())
358*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
359*9880d681SAndroid Build Coastguard Worker   auto CurrentActivity = "loading file '" + ThinLTOIndex + "'";
360*9880d681SAndroid Build Coastguard Worker   ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IndexOrErr =
361*9880d681SAndroid Build Coastguard Worker       llvm::getModuleSummaryIndexForFile(ThinLTOIndex, diagnosticHandler);
362*9880d681SAndroid Build Coastguard Worker   error(IndexOrErr, "error " + CurrentActivity);
363*9880d681SAndroid Build Coastguard Worker   return std::move(IndexOrErr.get());
364*9880d681SAndroid Build Coastguard Worker }
365*9880d681SAndroid Build Coastguard Worker 
loadModule(StringRef Filename,LLVMContext & Ctx)366*9880d681SAndroid Build Coastguard Worker static std::unique_ptr<Module> loadModule(StringRef Filename,
367*9880d681SAndroid Build Coastguard Worker                                           LLVMContext &Ctx) {
368*9880d681SAndroid Build Coastguard Worker   SMDiagnostic Err;
369*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
370*9880d681SAndroid Build Coastguard Worker   if (!M) {
371*9880d681SAndroid Build Coastguard Worker     Err.print("llvm-lto", errs());
372*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Can't load module for file " + Filename);
373*9880d681SAndroid Build Coastguard Worker   }
374*9880d681SAndroid Build Coastguard Worker   maybeVerifyModule(*M);
375*9880d681SAndroid Build Coastguard Worker 
376*9880d681SAndroid Build Coastguard Worker   if (ThinLTOModuleId.getNumOccurrences()) {
377*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1)
378*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't override the module id for multiple files");
379*9880d681SAndroid Build Coastguard Worker     M->setModuleIdentifier(ThinLTOModuleId);
380*9880d681SAndroid Build Coastguard Worker   }
381*9880d681SAndroid Build Coastguard Worker   return M;
382*9880d681SAndroid Build Coastguard Worker }
383*9880d681SAndroid Build Coastguard Worker 
writeModuleToFile(Module & TheModule,StringRef Filename)384*9880d681SAndroid Build Coastguard Worker static void writeModuleToFile(Module &TheModule, StringRef Filename) {
385*9880d681SAndroid Build Coastguard Worker   std::error_code EC;
386*9880d681SAndroid Build Coastguard Worker   raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
387*9880d681SAndroid Build Coastguard Worker   error(EC, "error opening the file '" + Filename + "'");
388*9880d681SAndroid Build Coastguard Worker   maybeVerifyModule(TheModule);
389*9880d681SAndroid Build Coastguard Worker   WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker 
392*9880d681SAndroid Build Coastguard Worker class ThinLTOProcessing {
393*9880d681SAndroid Build Coastguard Worker public:
394*9880d681SAndroid Build Coastguard Worker   ThinLTOCodeGenerator ThinGenerator;
395*9880d681SAndroid Build Coastguard Worker 
ThinLTOProcessing(const TargetOptions & Options)396*9880d681SAndroid Build Coastguard Worker   ThinLTOProcessing(const TargetOptions &Options) {
397*9880d681SAndroid Build Coastguard Worker     ThinGenerator.setCodePICModel(getRelocModel());
398*9880d681SAndroid Build Coastguard Worker     ThinGenerator.setTargetOptions(Options);
399*9880d681SAndroid Build Coastguard Worker     ThinGenerator.setCacheDir(ThinLTOCacheDir);
400*9880d681SAndroid Build Coastguard Worker 
401*9880d681SAndroid Build Coastguard Worker     // Add all the exported symbols to the table of symbols to preserve.
402*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
403*9880d681SAndroid Build Coastguard Worker       ThinGenerator.preserveSymbol(ExportedSymbols[i]);
404*9880d681SAndroid Build Coastguard Worker   }
405*9880d681SAndroid Build Coastguard Worker 
run()406*9880d681SAndroid Build Coastguard Worker   void run() {
407*9880d681SAndroid Build Coastguard Worker     switch (ThinLTOMode) {
408*9880d681SAndroid Build Coastguard Worker     case THINLINK:
409*9880d681SAndroid Build Coastguard Worker       return thinLink();
410*9880d681SAndroid Build Coastguard Worker     case THINDISTRIBUTE:
411*9880d681SAndroid Build Coastguard Worker       return distributedIndexes();
412*9880d681SAndroid Build Coastguard Worker     case THINEMITIMPORTS:
413*9880d681SAndroid Build Coastguard Worker       return emitImports();
414*9880d681SAndroid Build Coastguard Worker     case THINPROMOTE:
415*9880d681SAndroid Build Coastguard Worker       return promote();
416*9880d681SAndroid Build Coastguard Worker     case THINIMPORT:
417*9880d681SAndroid Build Coastguard Worker       return import();
418*9880d681SAndroid Build Coastguard Worker     case THININTERNALIZE:
419*9880d681SAndroid Build Coastguard Worker       return internalize();
420*9880d681SAndroid Build Coastguard Worker     case THINOPT:
421*9880d681SAndroid Build Coastguard Worker       return optimize();
422*9880d681SAndroid Build Coastguard Worker     case THINCODEGEN:
423*9880d681SAndroid Build Coastguard Worker       return codegen();
424*9880d681SAndroid Build Coastguard Worker     case THINALL:
425*9880d681SAndroid Build Coastguard Worker       return runAll();
426*9880d681SAndroid Build Coastguard Worker     }
427*9880d681SAndroid Build Coastguard Worker   }
428*9880d681SAndroid Build Coastguard Worker 
429*9880d681SAndroid Build Coastguard Worker private:
430*9880d681SAndroid Build Coastguard Worker   /// Load the input files, create the combined index, and write it out.
thinLink()431*9880d681SAndroid Build Coastguard Worker   void thinLink() {
432*9880d681SAndroid Build Coastguard Worker     // Perform "ThinLink": just produce the index
433*9880d681SAndroid Build Coastguard Worker     if (OutputFilename.empty())
434*9880d681SAndroid Build Coastguard Worker       report_fatal_error(
435*9880d681SAndroid Build Coastguard Worker           "OutputFilename is necessary to store the combined index.\n");
436*9880d681SAndroid Build Coastguard Worker 
437*9880d681SAndroid Build Coastguard Worker     LLVMContext Ctx;
438*9880d681SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
439*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
440*9880d681SAndroid Build Coastguard Worker       auto &Filename = InputFilenames[i];
441*9880d681SAndroid Build Coastguard Worker       StringRef CurrentActivity = "loading file '" + Filename + "'";
442*9880d681SAndroid Build Coastguard Worker       auto InputOrErr = MemoryBuffer::getFile(Filename);
443*9880d681SAndroid Build Coastguard Worker       error(InputOrErr, "error " + CurrentActivity);
444*9880d681SAndroid Build Coastguard Worker       InputBuffers.push_back(std::move(*InputOrErr));
445*9880d681SAndroid Build Coastguard Worker       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
446*9880d681SAndroid Build Coastguard Worker     }
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker     auto CombinedIndex = ThinGenerator.linkCombinedIndex();
449*9880d681SAndroid Build Coastguard Worker     std::error_code EC;
450*9880d681SAndroid Build Coastguard Worker     raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
451*9880d681SAndroid Build Coastguard Worker     error(EC, "error opening the file '" + OutputFilename + "'");
452*9880d681SAndroid Build Coastguard Worker     WriteIndexToFile(*CombinedIndex, OS);
453*9880d681SAndroid Build Coastguard Worker     return;
454*9880d681SAndroid Build Coastguard Worker   }
455*9880d681SAndroid Build Coastguard Worker 
456*9880d681SAndroid Build Coastguard Worker   /// Load the combined index from disk, then compute and generate
457*9880d681SAndroid Build Coastguard Worker   /// individual index files suitable for ThinLTO distributed backend builds
458*9880d681SAndroid Build Coastguard Worker   /// on the files mentioned on the command line (these must match the index
459*9880d681SAndroid Build Coastguard Worker   /// content).
distributedIndexes()460*9880d681SAndroid Build Coastguard Worker   void distributedIndexes() {
461*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
462*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
463*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
464*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
465*9880d681SAndroid Build Coastguard Worker                          "ones.");
466*9880d681SAndroid Build Coastguard Worker 
467*9880d681SAndroid Build Coastguard Worker     std::string OldPrefix, NewPrefix;
468*9880d681SAndroid Build Coastguard Worker     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
469*9880d681SAndroid Build Coastguard Worker 
470*9880d681SAndroid Build Coastguard Worker     auto Index = loadCombinedIndex();
471*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
472*9880d681SAndroid Build Coastguard Worker       // Build a map of module to the GUIDs and summary objects that should
473*9880d681SAndroid Build Coastguard Worker       // be written to its index.
474*9880d681SAndroid Build Coastguard Worker       std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
475*9880d681SAndroid Build Coastguard Worker       ThinLTOCodeGenerator::gatherImportedSummariesForModule(
476*9880d681SAndroid Build Coastguard Worker           Filename, *Index, ModuleToSummariesForIndex);
477*9880d681SAndroid Build Coastguard Worker 
478*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
479*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
480*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.bc";
481*9880d681SAndroid Build Coastguard Worker       }
482*9880d681SAndroid Build Coastguard Worker       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
483*9880d681SAndroid Build Coastguard Worker       std::error_code EC;
484*9880d681SAndroid Build Coastguard Worker       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
485*9880d681SAndroid Build Coastguard Worker       error(EC, "error opening the file '" + OutputName + "'");
486*9880d681SAndroid Build Coastguard Worker       WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
487*9880d681SAndroid Build Coastguard Worker     }
488*9880d681SAndroid Build Coastguard Worker   }
489*9880d681SAndroid Build Coastguard Worker 
490*9880d681SAndroid Build Coastguard Worker   /// Load the combined index from disk, compute the imports, and emit
491*9880d681SAndroid Build Coastguard Worker   /// the import file lists for each module to disk.
emitImports()492*9880d681SAndroid Build Coastguard Worker   void emitImports() {
493*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
494*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
495*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
496*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
497*9880d681SAndroid Build Coastguard Worker                          "ones.");
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker     std::string OldPrefix, NewPrefix;
500*9880d681SAndroid Build Coastguard Worker     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
501*9880d681SAndroid Build Coastguard Worker 
502*9880d681SAndroid Build Coastguard Worker     auto Index = loadCombinedIndex();
503*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
504*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
505*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
506*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".imports";
507*9880d681SAndroid Build Coastguard Worker       }
508*9880d681SAndroid Build Coastguard Worker       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
509*9880d681SAndroid Build Coastguard Worker       ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
510*9880d681SAndroid Build Coastguard Worker     }
511*9880d681SAndroid Build Coastguard Worker   }
512*9880d681SAndroid Build Coastguard Worker 
513*9880d681SAndroid Build Coastguard Worker   /// Load the combined index from disk, then load every file referenced by
514*9880d681SAndroid Build Coastguard Worker   /// the index and add them to the generator, finally perform the promotion
515*9880d681SAndroid Build Coastguard Worker   /// on the files mentioned on the command line (these must match the index
516*9880d681SAndroid Build Coastguard Worker   /// content).
promote()517*9880d681SAndroid Build Coastguard Worker   void promote() {
518*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
519*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
520*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
521*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
522*9880d681SAndroid Build Coastguard Worker                          "ones.");
523*9880d681SAndroid Build Coastguard Worker 
524*9880d681SAndroid Build Coastguard Worker     auto Index = loadCombinedIndex();
525*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
526*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
527*9880d681SAndroid Build Coastguard Worker       auto TheModule = loadModule(Filename, Ctx);
528*9880d681SAndroid Build Coastguard Worker 
529*9880d681SAndroid Build Coastguard Worker       ThinGenerator.promote(*TheModule, *Index);
530*9880d681SAndroid Build Coastguard Worker 
531*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
532*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
533*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.promoted.bc";
534*9880d681SAndroid Build Coastguard Worker       }
535*9880d681SAndroid Build Coastguard Worker       writeModuleToFile(*TheModule, OutputName);
536*9880d681SAndroid Build Coastguard Worker     }
537*9880d681SAndroid Build Coastguard Worker   }
538*9880d681SAndroid Build Coastguard Worker 
539*9880d681SAndroid Build Coastguard Worker   /// Load the combined index from disk, then load every file referenced by
540*9880d681SAndroid Build Coastguard Worker   /// the index and add them to the generator, then performs the promotion and
541*9880d681SAndroid Build Coastguard Worker   /// cross module importing on the files mentioned on the command line
542*9880d681SAndroid Build Coastguard Worker   /// (these must match the index content).
import()543*9880d681SAndroid Build Coastguard Worker   void import() {
544*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
545*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
546*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
547*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
548*9880d681SAndroid Build Coastguard Worker                          "ones.");
549*9880d681SAndroid Build Coastguard Worker 
550*9880d681SAndroid Build Coastguard Worker     auto Index = loadCombinedIndex();
551*9880d681SAndroid Build Coastguard Worker     auto InputBuffers = loadAllFilesForIndex(*Index);
552*9880d681SAndroid Build Coastguard Worker     for (auto &MemBuffer : InputBuffers)
553*9880d681SAndroid Build Coastguard Worker       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
554*9880d681SAndroid Build Coastguard Worker                               MemBuffer->getBuffer());
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
557*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
558*9880d681SAndroid Build Coastguard Worker       auto TheModule = loadModule(Filename, Ctx);
559*9880d681SAndroid Build Coastguard Worker 
560*9880d681SAndroid Build Coastguard Worker       ThinGenerator.crossModuleImport(*TheModule, *Index);
561*9880d681SAndroid Build Coastguard Worker 
562*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
563*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
564*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.imported.bc";
565*9880d681SAndroid Build Coastguard Worker       }
566*9880d681SAndroid Build Coastguard Worker       writeModuleToFile(*TheModule, OutputName);
567*9880d681SAndroid Build Coastguard Worker     }
568*9880d681SAndroid Build Coastguard Worker   }
569*9880d681SAndroid Build Coastguard Worker 
internalize()570*9880d681SAndroid Build Coastguard Worker   void internalize() {
571*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
572*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
573*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
574*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
575*9880d681SAndroid Build Coastguard Worker                          "ones.");
576*9880d681SAndroid Build Coastguard Worker 
577*9880d681SAndroid Build Coastguard Worker     if (ExportedSymbols.empty())
578*9880d681SAndroid Build Coastguard Worker       errs() << "Warning: -internalize will not perform without "
579*9880d681SAndroid Build Coastguard Worker                 "-exported-symbol\n";
580*9880d681SAndroid Build Coastguard Worker 
581*9880d681SAndroid Build Coastguard Worker     auto Index = loadCombinedIndex();
582*9880d681SAndroid Build Coastguard Worker     auto InputBuffers = loadAllFilesForIndex(*Index);
583*9880d681SAndroid Build Coastguard Worker     for (auto &MemBuffer : InputBuffers)
584*9880d681SAndroid Build Coastguard Worker       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
585*9880d681SAndroid Build Coastguard Worker                               MemBuffer->getBuffer());
586*9880d681SAndroid Build Coastguard Worker 
587*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
588*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
589*9880d681SAndroid Build Coastguard Worker       auto TheModule = loadModule(Filename, Ctx);
590*9880d681SAndroid Build Coastguard Worker 
591*9880d681SAndroid Build Coastguard Worker       ThinGenerator.internalize(*TheModule, *Index);
592*9880d681SAndroid Build Coastguard Worker 
593*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
594*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
595*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.internalized.bc";
596*9880d681SAndroid Build Coastguard Worker       }
597*9880d681SAndroid Build Coastguard Worker       writeModuleToFile(*TheModule, OutputName);
598*9880d681SAndroid Build Coastguard Worker     }
599*9880d681SAndroid Build Coastguard Worker   }
600*9880d681SAndroid Build Coastguard Worker 
optimize()601*9880d681SAndroid Build Coastguard Worker   void optimize() {
602*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
603*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
604*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
605*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
606*9880d681SAndroid Build Coastguard Worker                          "ones.");
607*9880d681SAndroid Build Coastguard Worker     if (!ThinLTOIndex.empty())
608*9880d681SAndroid Build Coastguard Worker       errs() << "Warning: -thinlto-index ignored for optimize stage";
609*9880d681SAndroid Build Coastguard Worker 
610*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
611*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
612*9880d681SAndroid Build Coastguard Worker       auto TheModule = loadModule(Filename, Ctx);
613*9880d681SAndroid Build Coastguard Worker 
614*9880d681SAndroid Build Coastguard Worker       ThinGenerator.optimize(*TheModule);
615*9880d681SAndroid Build Coastguard Worker 
616*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
617*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
618*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.imported.bc";
619*9880d681SAndroid Build Coastguard Worker       }
620*9880d681SAndroid Build Coastguard Worker       writeModuleToFile(*TheModule, OutputName);
621*9880d681SAndroid Build Coastguard Worker     }
622*9880d681SAndroid Build Coastguard Worker   }
623*9880d681SAndroid Build Coastguard Worker 
codegen()624*9880d681SAndroid Build Coastguard Worker   void codegen() {
625*9880d681SAndroid Build Coastguard Worker     if (InputFilenames.size() != 1 && !OutputFilename.empty())
626*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Can't handle a single output filename and multiple "
627*9880d681SAndroid Build Coastguard Worker                          "input files, do not provide an output filename and "
628*9880d681SAndroid Build Coastguard Worker                          "the output files will be suffixed from the input "
629*9880d681SAndroid Build Coastguard Worker                          "ones.");
630*9880d681SAndroid Build Coastguard Worker     if (!ThinLTOIndex.empty())
631*9880d681SAndroid Build Coastguard Worker       errs() << "Warning: -thinlto-index ignored for codegen stage";
632*9880d681SAndroid Build Coastguard Worker 
633*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
634*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
635*9880d681SAndroid Build Coastguard Worker       auto TheModule = loadModule(Filename, Ctx);
636*9880d681SAndroid Build Coastguard Worker 
637*9880d681SAndroid Build Coastguard Worker       auto Buffer = ThinGenerator.codegen(*TheModule);
638*9880d681SAndroid Build Coastguard Worker       std::string OutputName = OutputFilename;
639*9880d681SAndroid Build Coastguard Worker       if (OutputName.empty()) {
640*9880d681SAndroid Build Coastguard Worker         OutputName = Filename + ".thinlto.o";
641*9880d681SAndroid Build Coastguard Worker       }
642*9880d681SAndroid Build Coastguard Worker       if (OutputName == "-") {
643*9880d681SAndroid Build Coastguard Worker         outs() << Buffer->getBuffer();
644*9880d681SAndroid Build Coastguard Worker         return;
645*9880d681SAndroid Build Coastguard Worker       }
646*9880d681SAndroid Build Coastguard Worker 
647*9880d681SAndroid Build Coastguard Worker       std::error_code EC;
648*9880d681SAndroid Build Coastguard Worker       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
649*9880d681SAndroid Build Coastguard Worker       error(EC, "error opening the file '" + OutputName + "'");
650*9880d681SAndroid Build Coastguard Worker       OS << Buffer->getBuffer();
651*9880d681SAndroid Build Coastguard Worker     }
652*9880d681SAndroid Build Coastguard Worker   }
653*9880d681SAndroid Build Coastguard Worker 
654*9880d681SAndroid Build Coastguard Worker   /// Full ThinLTO process
runAll()655*9880d681SAndroid Build Coastguard Worker   void runAll() {
656*9880d681SAndroid Build Coastguard Worker     if (!OutputFilename.empty())
657*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Do not provide an output filename for ThinLTO "
658*9880d681SAndroid Build Coastguard Worker                          " processing, the output files will be suffixed from "
659*9880d681SAndroid Build Coastguard Worker                          "the input ones.");
660*9880d681SAndroid Build Coastguard Worker 
661*9880d681SAndroid Build Coastguard Worker     if (!ThinLTOIndex.empty())
662*9880d681SAndroid Build Coastguard Worker       errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
663*9880d681SAndroid Build Coastguard Worker 
664*9880d681SAndroid Build Coastguard Worker     LLVMContext Ctx;
665*9880d681SAndroid Build Coastguard Worker     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
666*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
667*9880d681SAndroid Build Coastguard Worker       auto &Filename = InputFilenames[i];
668*9880d681SAndroid Build Coastguard Worker       StringRef CurrentActivity = "loading file '" + Filename + "'";
669*9880d681SAndroid Build Coastguard Worker       auto InputOrErr = MemoryBuffer::getFile(Filename);
670*9880d681SAndroid Build Coastguard Worker       error(InputOrErr, "error " + CurrentActivity);
671*9880d681SAndroid Build Coastguard Worker       InputBuffers.push_back(std::move(*InputOrErr));
672*9880d681SAndroid Build Coastguard Worker       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
673*9880d681SAndroid Build Coastguard Worker     }
674*9880d681SAndroid Build Coastguard Worker 
675*9880d681SAndroid Build Coastguard Worker     ThinGenerator.run();
676*9880d681SAndroid Build Coastguard Worker 
677*9880d681SAndroid Build Coastguard Worker     auto &Binaries = ThinGenerator.getProducedBinaries();
678*9880d681SAndroid Build Coastguard Worker     if (Binaries.size() != InputFilenames.size())
679*9880d681SAndroid Build Coastguard Worker       report_fatal_error("Number of output objects does not match the number "
680*9880d681SAndroid Build Coastguard Worker                          "of inputs");
681*9880d681SAndroid Build Coastguard Worker 
682*9880d681SAndroid Build Coastguard Worker     for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
683*9880d681SAndroid Build Coastguard Worker       auto OutputName = InputFilenames[BufID] + ".thinlto.o";
684*9880d681SAndroid Build Coastguard Worker       std::error_code EC;
685*9880d681SAndroid Build Coastguard Worker       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
686*9880d681SAndroid Build Coastguard Worker       error(EC, "error opening the file '" + OutputName + "'");
687*9880d681SAndroid Build Coastguard Worker       OS << Binaries[BufID]->getBuffer();
688*9880d681SAndroid Build Coastguard Worker     }
689*9880d681SAndroid Build Coastguard Worker   }
690*9880d681SAndroid Build Coastguard Worker 
691*9880d681SAndroid Build Coastguard Worker   /// Load the combined index from disk, then load every file referenced by
692*9880d681SAndroid Build Coastguard Worker };
693*9880d681SAndroid Build Coastguard Worker 
694*9880d681SAndroid Build Coastguard Worker } // namespace thinlto
695*9880d681SAndroid Build Coastguard Worker 
main(int argc,char ** argv)696*9880d681SAndroid Build Coastguard Worker int main(int argc, char **argv) {
697*9880d681SAndroid Build Coastguard Worker   // Print a stack trace if we signal out.
698*9880d681SAndroid Build Coastguard Worker   sys::PrintStackTraceOnErrorSignal(argv[0]);
699*9880d681SAndroid Build Coastguard Worker   PrettyStackTraceProgram X(argc, argv);
700*9880d681SAndroid Build Coastguard Worker 
701*9880d681SAndroid Build Coastguard Worker   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
702*9880d681SAndroid Build Coastguard Worker   cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
703*9880d681SAndroid Build Coastguard Worker 
704*9880d681SAndroid Build Coastguard Worker   if (OptLevel < '0' || OptLevel > '3')
705*9880d681SAndroid Build Coastguard Worker     error("optimization level must be between 0 and 3");
706*9880d681SAndroid Build Coastguard Worker 
707*9880d681SAndroid Build Coastguard Worker   // Initialize the configured targets.
708*9880d681SAndroid Build Coastguard Worker   InitializeAllTargets();
709*9880d681SAndroid Build Coastguard Worker   InitializeAllTargetMCs();
710*9880d681SAndroid Build Coastguard Worker   InitializeAllAsmPrinters();
711*9880d681SAndroid Build Coastguard Worker   InitializeAllAsmParsers();
712*9880d681SAndroid Build Coastguard Worker 
713*9880d681SAndroid Build Coastguard Worker   // set up the TargetOptions for the machine
714*9880d681SAndroid Build Coastguard Worker   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
715*9880d681SAndroid Build Coastguard Worker 
716*9880d681SAndroid Build Coastguard Worker   if (ListSymbolsOnly) {
717*9880d681SAndroid Build Coastguard Worker     listSymbols(Options);
718*9880d681SAndroid Build Coastguard Worker     return 0;
719*9880d681SAndroid Build Coastguard Worker   }
720*9880d681SAndroid Build Coastguard Worker 
721*9880d681SAndroid Build Coastguard Worker   if (CheckHasObjC) {
722*9880d681SAndroid Build Coastguard Worker     for (auto &Filename : InputFilenames) {
723*9880d681SAndroid Build Coastguard Worker       ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
724*9880d681SAndroid Build Coastguard Worker           MemoryBuffer::getFile(Filename);
725*9880d681SAndroid Build Coastguard Worker       error(BufferOrErr, "error loading file '" + Filename + "'");
726*9880d681SAndroid Build Coastguard Worker       auto Buffer = std::move(BufferOrErr.get());
727*9880d681SAndroid Build Coastguard Worker       LLVMContext Ctx;
728*9880d681SAndroid Build Coastguard Worker       if (llvm::isBitcodeContainingObjCCategory(*Buffer, Ctx))
729*9880d681SAndroid Build Coastguard Worker         outs() << "Bitcode " << Filename << " contains ObjC\n";
730*9880d681SAndroid Build Coastguard Worker       else
731*9880d681SAndroid Build Coastguard Worker         outs() << "Bitcode " << Filename << " does not contain ObjC\n";
732*9880d681SAndroid Build Coastguard Worker     }
733*9880d681SAndroid Build Coastguard Worker     return 0;
734*9880d681SAndroid Build Coastguard Worker   }
735*9880d681SAndroid Build Coastguard Worker 
736*9880d681SAndroid Build Coastguard Worker   if (ThinLTOMode.getNumOccurrences()) {
737*9880d681SAndroid Build Coastguard Worker     if (ThinLTOMode.getNumOccurrences() > 1)
738*9880d681SAndroid Build Coastguard Worker       report_fatal_error("You can't specify more than one -thinlto-action");
739*9880d681SAndroid Build Coastguard Worker     thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
740*9880d681SAndroid Build Coastguard Worker     ThinLTOProcessor.run();
741*9880d681SAndroid Build Coastguard Worker     return 0;
742*9880d681SAndroid Build Coastguard Worker   }
743*9880d681SAndroid Build Coastguard Worker 
744*9880d681SAndroid Build Coastguard Worker   if (ThinLTO) {
745*9880d681SAndroid Build Coastguard Worker     createCombinedModuleSummaryIndex();
746*9880d681SAndroid Build Coastguard Worker     return 0;
747*9880d681SAndroid Build Coastguard Worker   }
748*9880d681SAndroid Build Coastguard Worker 
749*9880d681SAndroid Build Coastguard Worker   unsigned BaseArg = 0;
750*9880d681SAndroid Build Coastguard Worker 
751*9880d681SAndroid Build Coastguard Worker   LLVMContext Context;
752*9880d681SAndroid Build Coastguard Worker   Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);
753*9880d681SAndroid Build Coastguard Worker 
754*9880d681SAndroid Build Coastguard Worker   LTOCodeGenerator CodeGen(Context);
755*9880d681SAndroid Build Coastguard Worker 
756*9880d681SAndroid Build Coastguard Worker   if (UseDiagnosticHandler)
757*9880d681SAndroid Build Coastguard Worker     CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
758*9880d681SAndroid Build Coastguard Worker 
759*9880d681SAndroid Build Coastguard Worker   CodeGen.setCodePICModel(getRelocModel());
760*9880d681SAndroid Build Coastguard Worker 
761*9880d681SAndroid Build Coastguard Worker   CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
762*9880d681SAndroid Build Coastguard Worker   CodeGen.setTargetOptions(Options);
763*9880d681SAndroid Build Coastguard Worker   CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
764*9880d681SAndroid Build Coastguard Worker 
765*9880d681SAndroid Build Coastguard Worker   llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
766*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < DSOSymbols.size(); ++i)
767*9880d681SAndroid Build Coastguard Worker     DSOSymbolsSet.insert(DSOSymbols[i]);
768*9880d681SAndroid Build Coastguard Worker 
769*9880d681SAndroid Build Coastguard Worker   std::vector<std::string> KeptDSOSyms;
770*9880d681SAndroid Build Coastguard Worker 
771*9880d681SAndroid Build Coastguard Worker   for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
772*9880d681SAndroid Build Coastguard Worker     CurrentActivity = "loading file '" + InputFilenames[i] + "'";
773*9880d681SAndroid Build Coastguard Worker     ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
774*9880d681SAndroid Build Coastguard Worker         LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options);
775*9880d681SAndroid Build Coastguard Worker     std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
776*9880d681SAndroid Build Coastguard Worker     CurrentActivity = "";
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker     unsigned NumSyms = Module->getSymbolCount();
779*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I < NumSyms; ++I) {
780*9880d681SAndroid Build Coastguard Worker       StringRef Name = Module->getSymbolName(I);
781*9880d681SAndroid Build Coastguard Worker       if (!DSOSymbolsSet.count(Name))
782*9880d681SAndroid Build Coastguard Worker         continue;
783*9880d681SAndroid Build Coastguard Worker       lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
784*9880d681SAndroid Build Coastguard Worker       unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
785*9880d681SAndroid Build Coastguard Worker       if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
786*9880d681SAndroid Build Coastguard Worker         KeptDSOSyms.push_back(Name);
787*9880d681SAndroid Build Coastguard Worker     }
788*9880d681SAndroid Build Coastguard Worker 
789*9880d681SAndroid Build Coastguard Worker     // We use the first input module as the destination module when
790*9880d681SAndroid Build Coastguard Worker     // SetMergedModule is true.
791*9880d681SAndroid Build Coastguard Worker     if (SetMergedModule && i == BaseArg) {
792*9880d681SAndroid Build Coastguard Worker       // Transfer ownership to the code generator.
793*9880d681SAndroid Build Coastguard Worker       CodeGen.setModule(std::move(Module));
794*9880d681SAndroid Build Coastguard Worker     } else if (!CodeGen.addModule(Module.get())) {
795*9880d681SAndroid Build Coastguard Worker       // Print a message here so that we know addModule() did not abort.
796*9880d681SAndroid Build Coastguard Worker       error("error adding file '" + InputFilenames[i] + "'");
797*9880d681SAndroid Build Coastguard Worker     }
798*9880d681SAndroid Build Coastguard Worker   }
799*9880d681SAndroid Build Coastguard Worker 
800*9880d681SAndroid Build Coastguard Worker   // Add all the exported symbols to the table of symbols to preserve.
801*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
802*9880d681SAndroid Build Coastguard Worker     CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
803*9880d681SAndroid Build Coastguard Worker 
804*9880d681SAndroid Build Coastguard Worker   // Add all the dso symbols to the table of symbols to expose.
805*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
806*9880d681SAndroid Build Coastguard Worker     CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str());
807*9880d681SAndroid Build Coastguard Worker 
808*9880d681SAndroid Build Coastguard Worker   // Set cpu and attrs strings for the default target/subtarget.
809*9880d681SAndroid Build Coastguard Worker   CodeGen.setCpu(MCPU.c_str());
810*9880d681SAndroid Build Coastguard Worker 
811*9880d681SAndroid Build Coastguard Worker   CodeGen.setOptLevel(OptLevel - '0');
812*9880d681SAndroid Build Coastguard Worker 
813*9880d681SAndroid Build Coastguard Worker   std::string attrs;
814*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i < MAttrs.size(); ++i) {
815*9880d681SAndroid Build Coastguard Worker     if (i > 0)
816*9880d681SAndroid Build Coastguard Worker       attrs.append(",");
817*9880d681SAndroid Build Coastguard Worker     attrs.append(MAttrs[i]);
818*9880d681SAndroid Build Coastguard Worker   }
819*9880d681SAndroid Build Coastguard Worker 
820*9880d681SAndroid Build Coastguard Worker   if (!attrs.empty())
821*9880d681SAndroid Build Coastguard Worker     CodeGen.setAttr(attrs.c_str());
822*9880d681SAndroid Build Coastguard Worker 
823*9880d681SAndroid Build Coastguard Worker   if (FileType.getNumOccurrences())
824*9880d681SAndroid Build Coastguard Worker     CodeGen.setFileType(FileType);
825*9880d681SAndroid Build Coastguard Worker 
826*9880d681SAndroid Build Coastguard Worker   if (!OutputFilename.empty()) {
827*9880d681SAndroid Build Coastguard Worker     if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
828*9880d681SAndroid Build Coastguard Worker                           DisableLTOVectorization)) {
829*9880d681SAndroid Build Coastguard Worker       // Diagnostic messages should have been printed by the handler.
830*9880d681SAndroid Build Coastguard Worker       error("error optimizing the code");
831*9880d681SAndroid Build Coastguard Worker     }
832*9880d681SAndroid Build Coastguard Worker 
833*9880d681SAndroid Build Coastguard Worker     if (SaveModuleFile) {
834*9880d681SAndroid Build Coastguard Worker       std::string ModuleFilename = OutputFilename;
835*9880d681SAndroid Build Coastguard Worker       ModuleFilename += ".merged.bc";
836*9880d681SAndroid Build Coastguard Worker       std::string ErrMsg;
837*9880d681SAndroid Build Coastguard Worker 
838*9880d681SAndroid Build Coastguard Worker       if (!CodeGen.writeMergedModules(ModuleFilename.c_str()))
839*9880d681SAndroid Build Coastguard Worker         error("writing merged module failed.");
840*9880d681SAndroid Build Coastguard Worker     }
841*9880d681SAndroid Build Coastguard Worker 
842*9880d681SAndroid Build Coastguard Worker     std::list<tool_output_file> OSs;
843*9880d681SAndroid Build Coastguard Worker     std::vector<raw_pwrite_stream *> OSPtrs;
844*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I != Parallelism; ++I) {
845*9880d681SAndroid Build Coastguard Worker       std::string PartFilename = OutputFilename;
846*9880d681SAndroid Build Coastguard Worker       if (Parallelism != 1)
847*9880d681SAndroid Build Coastguard Worker         PartFilename += "." + utostr(I);
848*9880d681SAndroid Build Coastguard Worker       std::error_code EC;
849*9880d681SAndroid Build Coastguard Worker       OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
850*9880d681SAndroid Build Coastguard Worker       if (EC)
851*9880d681SAndroid Build Coastguard Worker         error("error opening the file '" + PartFilename + "': " + EC.message());
852*9880d681SAndroid Build Coastguard Worker       OSPtrs.push_back(&OSs.back().os());
853*9880d681SAndroid Build Coastguard Worker     }
854*9880d681SAndroid Build Coastguard Worker 
855*9880d681SAndroid Build Coastguard Worker     if (!CodeGen.compileOptimized(OSPtrs))
856*9880d681SAndroid Build Coastguard Worker       // Diagnostic messages should have been printed by the handler.
857*9880d681SAndroid Build Coastguard Worker       error("error compiling the code");
858*9880d681SAndroid Build Coastguard Worker 
859*9880d681SAndroid Build Coastguard Worker     for (tool_output_file &OS : OSs)
860*9880d681SAndroid Build Coastguard Worker       OS.keep();
861*9880d681SAndroid Build Coastguard Worker   } else {
862*9880d681SAndroid Build Coastguard Worker     if (Parallelism != 1)
863*9880d681SAndroid Build Coastguard Worker       error("-j must be specified together with -o");
864*9880d681SAndroid Build Coastguard Worker 
865*9880d681SAndroid Build Coastguard Worker     if (SaveModuleFile)
866*9880d681SAndroid Build Coastguard Worker       error(": -save-merged-module must be specified with -o");
867*9880d681SAndroid Build Coastguard Worker 
868*9880d681SAndroid Build Coastguard Worker     const char *OutputName = nullptr;
869*9880d681SAndroid Build Coastguard Worker     if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
870*9880d681SAndroid Build Coastguard Worker                                  DisableGVNLoadPRE, DisableLTOVectorization))
871*9880d681SAndroid Build Coastguard Worker       error("error compiling the code");
872*9880d681SAndroid Build Coastguard Worker       // Diagnostic messages should have been printed by the handler.
873*9880d681SAndroid Build Coastguard Worker 
874*9880d681SAndroid Build Coastguard Worker     outs() << "Wrote native object file '" << OutputName << "'\n";
875*9880d681SAndroid Build Coastguard Worker   }
876*9880d681SAndroid Build Coastguard Worker 
877*9880d681SAndroid Build Coastguard Worker   return 0;
878*9880d681SAndroid Build Coastguard Worker }
879