1f785676fSDimitry Andric //===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===//
2f785676fSDimitry Andric //
3f785676fSDimitry Andric //                     The LLVM Compiler Infrastructure
4f785676fSDimitry Andric //
5f785676fSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f785676fSDimitry Andric // License. See LICENSE.TXT for details.
7f785676fSDimitry Andric //
8f785676fSDimitry Andric //===----------------------------------------------------------------------===//
9f785676fSDimitry Andric //
10f785676fSDimitry Andric // This file implements the Link Time Optimization library. This library is
11f785676fSDimitry Andric // intended to be used by linker to optimize code at link time.
12f785676fSDimitry Andric //
13f785676fSDimitry Andric //===----------------------------------------------------------------------===//
14f785676fSDimitry Andric 
15f785676fSDimitry Andric #include "llvm/LTO/LTOCodeGenerator.h"
16f785676fSDimitry Andric #include "llvm/ADT/StringExtras.h"
17f785676fSDimitry Andric #include "llvm/Analysis/Passes.h"
18ff0cc061SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
19ff0cc061SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
20f785676fSDimitry Andric #include "llvm/Bitcode/ReaderWriter.h"
21f785676fSDimitry Andric #include "llvm/CodeGen/RuntimeLibcalls.h"
22f785676fSDimitry Andric #include "llvm/Config/config.h"
23f785676fSDimitry Andric #include "llvm/IR/Constants.h"
24f785676fSDimitry Andric #include "llvm/IR/DataLayout.h"
25f785676fSDimitry Andric #include "llvm/IR/DerivedTypes.h"
2691bc56edSDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
2791bc56edSDimitry Andric #include "llvm/IR/DiagnosticPrinter.h"
28f785676fSDimitry Andric #include "llvm/IR/LLVMContext.h"
29ff0cc061SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
3091bc56edSDimitry Andric #include "llvm/IR/Mangler.h"
31f785676fSDimitry Andric #include "llvm/IR/Module.h"
3291bc56edSDimitry Andric #include "llvm/IR/Verifier.h"
33f785676fSDimitry Andric #include "llvm/InitializePasses.h"
3491bc56edSDimitry Andric #include "llvm/LTO/LTOModule.h"
3591bc56edSDimitry Andric #include "llvm/Linker/Linker.h"
36f785676fSDimitry Andric #include "llvm/MC/MCAsmInfo.h"
37f785676fSDimitry Andric #include "llvm/MC/MCContext.h"
38f785676fSDimitry Andric #include "llvm/MC/SubtargetFeature.h"
39f785676fSDimitry Andric #include "llvm/Support/CommandLine.h"
40f785676fSDimitry Andric #include "llvm/Support/FileSystem.h"
41f785676fSDimitry Andric #include "llvm/Support/Host.h"
42f785676fSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
43f785676fSDimitry Andric #include "llvm/Support/Signals.h"
44f785676fSDimitry Andric #include "llvm/Support/TargetRegistry.h"
45f785676fSDimitry Andric #include "llvm/Support/TargetSelect.h"
46f785676fSDimitry Andric #include "llvm/Support/ToolOutputFile.h"
4791bc56edSDimitry Andric #include "llvm/Support/raw_ostream.h"
48f785676fSDimitry Andric #include "llvm/Target/TargetLowering.h"
49f785676fSDimitry Andric #include "llvm/Target/TargetOptions.h"
50f785676fSDimitry Andric #include "llvm/Target/TargetRegisterInfo.h"
5139d628a0SDimitry Andric #include "llvm/Target/TargetSubtargetInfo.h"
52f785676fSDimitry Andric #include "llvm/Transforms/IPO.h"
53f785676fSDimitry Andric #include "llvm/Transforms/IPO/PassManagerBuilder.h"
54f785676fSDimitry Andric #include "llvm/Transforms/ObjCARC.h"
5591bc56edSDimitry Andric #include <system_error>
56f785676fSDimitry Andric using namespace llvm;
57f785676fSDimitry Andric 
58f785676fSDimitry Andric const char* LTOCodeGenerator::getVersionString() {
59f785676fSDimitry Andric #ifdef LLVM_VERSION_INFO
60f785676fSDimitry Andric   return PACKAGE_NAME " version " PACKAGE_VERSION ", " LLVM_VERSION_INFO;
61f785676fSDimitry Andric #else
62f785676fSDimitry Andric   return PACKAGE_NAME " version " PACKAGE_VERSION;
63f785676fSDimitry Andric #endif
64f785676fSDimitry Andric }
65f785676fSDimitry Andric 
66f785676fSDimitry Andric LTOCodeGenerator::LTOCodeGenerator()
6739d628a0SDimitry Andric     : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)) {
68ff0cc061SDimitry Andric   initializeLTOPasses();
6939d628a0SDimitry Andric }
7039d628a0SDimitry Andric 
7139d628a0SDimitry Andric LTOCodeGenerator::LTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
7239d628a0SDimitry Andric     : OwnedContext(std::move(Context)), Context(*OwnedContext),
7339d628a0SDimitry Andric       IRLinker(new Module("ld-temp.o", *OwnedContext)) {
74f785676fSDimitry Andric   initializeLTOPasses();
75f785676fSDimitry Andric }
76f785676fSDimitry Andric 
77ff0cc061SDimitry Andric void LTOCodeGenerator::destroyMergedModule() {
78ff0cc061SDimitry Andric   if (OwnedModule) {
79ff0cc061SDimitry Andric     assert(IRLinker.getModule() == &OwnedModule->getModule() &&
80ff0cc061SDimitry Andric            "The linker's module should be the same as the owned module");
81ff0cc061SDimitry Andric     delete OwnedModule;
82ff0cc061SDimitry Andric     OwnedModule = nullptr;
83ff0cc061SDimitry Andric   } else if (IRLinker.getModule())
84ff0cc061SDimitry Andric     IRLinker.deleteModule();
85ff0cc061SDimitry Andric }
86ff0cc061SDimitry Andric 
87f785676fSDimitry Andric LTOCodeGenerator::~LTOCodeGenerator() {
88ff0cc061SDimitry Andric   destroyMergedModule();
89ff0cc061SDimitry Andric 
90f785676fSDimitry Andric   delete TargetMach;
9191bc56edSDimitry Andric   TargetMach = nullptr;
92f785676fSDimitry Andric 
93f785676fSDimitry Andric   for (std::vector<char *>::iterator I = CodegenOptions.begin(),
94f785676fSDimitry Andric                                      E = CodegenOptions.end();
95f785676fSDimitry Andric        I != E; ++I)
96f785676fSDimitry Andric     free(*I);
97f785676fSDimitry Andric }
98f785676fSDimitry Andric 
99f785676fSDimitry Andric // Initialize LTO passes. Please keep this funciton in sync with
100f785676fSDimitry Andric // PassManagerBuilder::populateLTOPassManager(), and make sure all LTO
101f785676fSDimitry Andric // passes are initialized.
102f785676fSDimitry Andric void LTOCodeGenerator::initializeLTOPasses() {
103f785676fSDimitry Andric   PassRegistry &R = *PassRegistry::getPassRegistry();
104f785676fSDimitry Andric 
105f785676fSDimitry Andric   initializeInternalizePassPass(R);
106f785676fSDimitry Andric   initializeIPSCCPPass(R);
107f785676fSDimitry Andric   initializeGlobalOptPass(R);
108f785676fSDimitry Andric   initializeConstantMergePass(R);
109f785676fSDimitry Andric   initializeDAHPass(R);
110ff0cc061SDimitry Andric   initializeInstructionCombiningPassPass(R);
111f785676fSDimitry Andric   initializeSimpleInlinerPass(R);
112f785676fSDimitry Andric   initializePruneEHPass(R);
113f785676fSDimitry Andric   initializeGlobalDCEPass(R);
114f785676fSDimitry Andric   initializeArgPromotionPass(R);
115f785676fSDimitry Andric   initializeJumpThreadingPass(R);
116f785676fSDimitry Andric   initializeSROAPass(R);
117f785676fSDimitry Andric   initializeSROA_DTPass(R);
118f785676fSDimitry Andric   initializeSROA_SSAUpPass(R);
119f785676fSDimitry Andric   initializeFunctionAttrsPass(R);
120f785676fSDimitry Andric   initializeGlobalsModRefPass(R);
121f785676fSDimitry Andric   initializeLICMPass(R);
12291bc56edSDimitry Andric   initializeMergedLoadStoreMotionPass(R);
123f785676fSDimitry Andric   initializeGVNPass(R);
124f785676fSDimitry Andric   initializeMemCpyOptPass(R);
125f785676fSDimitry Andric   initializeDCEPass(R);
126f785676fSDimitry Andric   initializeCFGSimplifyPassPass(R);
127f785676fSDimitry Andric }
128f785676fSDimitry Andric 
12939d628a0SDimitry Andric bool LTOCodeGenerator::addModule(LTOModule *mod) {
13039d628a0SDimitry Andric   assert(&mod->getModule().getContext() == &Context &&
13139d628a0SDimitry Andric          "Expected module in same context");
13239d628a0SDimitry Andric 
13339d628a0SDimitry Andric   bool ret = IRLinker.linkInModule(&mod->getModule());
134f785676fSDimitry Andric 
135f785676fSDimitry Andric   const std::vector<const char*> &undefs = mod->getAsmUndefinedRefs();
136f785676fSDimitry Andric   for (int i = 0, e = undefs.size(); i != e; ++i)
137f785676fSDimitry Andric     AsmUndefinedRefs[undefs[i]] = 1;
138f785676fSDimitry Andric 
139f785676fSDimitry Andric   return !ret;
140f785676fSDimitry Andric }
141f785676fSDimitry Andric 
142ff0cc061SDimitry Andric void LTOCodeGenerator::setModule(LTOModule *Mod) {
143ff0cc061SDimitry Andric   assert(&Mod->getModule().getContext() == &Context &&
144ff0cc061SDimitry Andric          "Expected module in same context");
145ff0cc061SDimitry Andric 
146ff0cc061SDimitry Andric   // Delete the old merged module.
147ff0cc061SDimitry Andric   destroyMergedModule();
148ff0cc061SDimitry Andric   AsmUndefinedRefs.clear();
149ff0cc061SDimitry Andric 
150ff0cc061SDimitry Andric   OwnedModule = Mod;
151ff0cc061SDimitry Andric   IRLinker.setModule(&Mod->getModule());
152ff0cc061SDimitry Andric 
153ff0cc061SDimitry Andric   const std::vector<const char*> &Undefs = Mod->getAsmUndefinedRefs();
154ff0cc061SDimitry Andric   for (int I = 0, E = Undefs.size(); I != E; ++I)
155ff0cc061SDimitry Andric     AsmUndefinedRefs[Undefs[I]] = 1;
156ff0cc061SDimitry Andric }
157ff0cc061SDimitry Andric 
158f785676fSDimitry Andric void LTOCodeGenerator::setTargetOptions(TargetOptions options) {
15991bc56edSDimitry Andric   Options = options;
160f785676fSDimitry Andric }
161f785676fSDimitry Andric 
162f785676fSDimitry Andric void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) {
163f785676fSDimitry Andric   switch (debug) {
164f785676fSDimitry Andric   case LTO_DEBUG_MODEL_NONE:
165f785676fSDimitry Andric     EmitDwarfDebugInfo = false;
166f785676fSDimitry Andric     return;
167f785676fSDimitry Andric 
168f785676fSDimitry Andric   case LTO_DEBUG_MODEL_DWARF:
169f785676fSDimitry Andric     EmitDwarfDebugInfo = true;
170f785676fSDimitry Andric     return;
171f785676fSDimitry Andric   }
172f785676fSDimitry Andric   llvm_unreachable("Unknown debug format!");
173f785676fSDimitry Andric }
174f785676fSDimitry Andric 
175f785676fSDimitry Andric void LTOCodeGenerator::setCodePICModel(lto_codegen_model model) {
176f785676fSDimitry Andric   switch (model) {
177f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_STATIC:
178f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
179f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
18091bc56edSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
181f785676fSDimitry Andric     CodeModel = model;
182f785676fSDimitry Andric     return;
183f785676fSDimitry Andric   }
184f785676fSDimitry Andric   llvm_unreachable("Unknown PIC model!");
185f785676fSDimitry Andric }
186f785676fSDimitry Andric 
187f785676fSDimitry Andric bool LTOCodeGenerator::writeMergedModules(const char *path,
188f785676fSDimitry Andric                                           std::string &errMsg) {
189f785676fSDimitry Andric   if (!determineTarget(errMsg))
190f785676fSDimitry Andric     return false;
191f785676fSDimitry Andric 
192f785676fSDimitry Andric   // mark which symbols can not be internalized
193f785676fSDimitry Andric   applyScopeRestrictions();
194f785676fSDimitry Andric 
195f785676fSDimitry Andric   // create output file
19639d628a0SDimitry Andric   std::error_code EC;
19739d628a0SDimitry Andric   tool_output_file Out(path, EC, sys::fs::F_None);
19839d628a0SDimitry Andric   if (EC) {
199f785676fSDimitry Andric     errMsg = "could not open bitcode file for writing: ";
200f785676fSDimitry Andric     errMsg += path;
201f785676fSDimitry Andric     return false;
202f785676fSDimitry Andric   }
203f785676fSDimitry Andric 
204f785676fSDimitry Andric   // write bitcode to it
205ff0cc061SDimitry Andric   WriteBitcodeToFile(IRLinker.getModule(), Out.os(), ShouldEmbedUselists);
206f785676fSDimitry Andric   Out.os().close();
207f785676fSDimitry Andric 
208f785676fSDimitry Andric   if (Out.os().has_error()) {
209f785676fSDimitry Andric     errMsg = "could not write bitcode file: ";
210f785676fSDimitry Andric     errMsg += path;
211f785676fSDimitry Andric     Out.os().clear_error();
212f785676fSDimitry Andric     return false;
213f785676fSDimitry Andric   }
214f785676fSDimitry Andric 
215f785676fSDimitry Andric   Out.keep();
216f785676fSDimitry Andric   return true;
217f785676fSDimitry Andric }
218f785676fSDimitry Andric 
219ff0cc061SDimitry Andric bool LTOCodeGenerator::compileOptimizedToFile(const char **name,
220f785676fSDimitry Andric                                               std::string &errMsg) {
221f785676fSDimitry Andric   // make unique temp .o file to put generated object file
222f785676fSDimitry Andric   SmallString<128> Filename;
223f785676fSDimitry Andric   int FD;
22491bc56edSDimitry Andric   std::error_code EC =
22591bc56edSDimitry Andric       sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename);
226f785676fSDimitry Andric   if (EC) {
227f785676fSDimitry Andric     errMsg = EC.message();
228f785676fSDimitry Andric     return false;
229f785676fSDimitry Andric   }
230f785676fSDimitry Andric 
231f785676fSDimitry Andric   // generate object file
232f785676fSDimitry Andric   tool_output_file objFile(Filename.c_str(), FD);
233f785676fSDimitry Andric 
234ff0cc061SDimitry Andric   bool genResult = compileOptimized(objFile.os(), errMsg);
235f785676fSDimitry Andric   objFile.os().close();
236f785676fSDimitry Andric   if (objFile.os().has_error()) {
237f785676fSDimitry Andric     objFile.os().clear_error();
238f785676fSDimitry Andric     sys::fs::remove(Twine(Filename));
239f785676fSDimitry Andric     return false;
240f785676fSDimitry Andric   }
241f785676fSDimitry Andric 
242f785676fSDimitry Andric   objFile.keep();
243f785676fSDimitry Andric   if (!genResult) {
244f785676fSDimitry Andric     sys::fs::remove(Twine(Filename));
245f785676fSDimitry Andric     return false;
246f785676fSDimitry Andric   }
247f785676fSDimitry Andric 
248f785676fSDimitry Andric   NativeObjectPath = Filename.c_str();
249f785676fSDimitry Andric   *name = NativeObjectPath.c_str();
250f785676fSDimitry Andric   return true;
251f785676fSDimitry Andric }
252f785676fSDimitry Andric 
25397bc6c73SDimitry Andric std::unique_ptr<MemoryBuffer>
25497bc6c73SDimitry Andric LTOCodeGenerator::compileOptimized(std::string &errMsg) {
255f785676fSDimitry Andric   const char *name;
256ff0cc061SDimitry Andric   if (!compileOptimizedToFile(&name, errMsg))
25791bc56edSDimitry Andric     return nullptr;
258f785676fSDimitry Andric 
259f785676fSDimitry Andric   // read .o file into memory buffer
26091bc56edSDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
26191bc56edSDimitry Andric       MemoryBuffer::getFile(name, -1, false);
26291bc56edSDimitry Andric   if (std::error_code EC = BufferOrErr.getError()) {
26391bc56edSDimitry Andric     errMsg = EC.message();
264f785676fSDimitry Andric     sys::fs::remove(NativeObjectPath);
26591bc56edSDimitry Andric     return nullptr;
266f785676fSDimitry Andric   }
267f785676fSDimitry Andric 
268f785676fSDimitry Andric   // remove temp files
269f785676fSDimitry Andric   sys::fs::remove(NativeObjectPath);
270f785676fSDimitry Andric 
27197bc6c73SDimitry Andric   return std::move(*BufferOrErr);
272f785676fSDimitry Andric }
273f785676fSDimitry Andric 
274ff0cc061SDimitry Andric 
275ff0cc061SDimitry Andric bool LTOCodeGenerator::compile_to_file(const char **name,
276ff0cc061SDimitry Andric                                        bool disableInline,
277ff0cc061SDimitry Andric                                        bool disableGVNLoadPRE,
278ff0cc061SDimitry Andric                                        bool disableVectorization,
279ff0cc061SDimitry Andric                                        std::string &errMsg) {
280ff0cc061SDimitry Andric   if (!optimize(disableInline, disableGVNLoadPRE,
281ff0cc061SDimitry Andric                 disableVectorization, errMsg))
282ff0cc061SDimitry Andric     return false;
283ff0cc061SDimitry Andric 
284ff0cc061SDimitry Andric   return compileOptimizedToFile(name, errMsg);
285ff0cc061SDimitry Andric }
286ff0cc061SDimitry Andric 
28797bc6c73SDimitry Andric std::unique_ptr<MemoryBuffer>
28897bc6c73SDimitry Andric LTOCodeGenerator::compile(bool disableInline, bool disableGVNLoadPRE,
28997bc6c73SDimitry Andric                           bool disableVectorization, std::string &errMsg) {
290ff0cc061SDimitry Andric   if (!optimize(disableInline, disableGVNLoadPRE,
291ff0cc061SDimitry Andric                 disableVectorization, errMsg))
292ff0cc061SDimitry Andric     return nullptr;
293ff0cc061SDimitry Andric 
29497bc6c73SDimitry Andric   return compileOptimized(errMsg);
295ff0cc061SDimitry Andric }
296ff0cc061SDimitry Andric 
297f785676fSDimitry Andric bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
29891bc56edSDimitry Andric   if (TargetMach)
299f785676fSDimitry Andric     return true;
300f785676fSDimitry Andric 
30191bc56edSDimitry Andric   std::string TripleStr = IRLinker.getModule()->getTargetTriple();
302f785676fSDimitry Andric   if (TripleStr.empty())
303f785676fSDimitry Andric     TripleStr = sys::getDefaultTargetTriple();
304f785676fSDimitry Andric   llvm::Triple Triple(TripleStr);
305f785676fSDimitry Andric 
306f785676fSDimitry Andric   // create target machine from info for merged modules
307f785676fSDimitry Andric   const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
30891bc56edSDimitry Andric   if (!march)
309f785676fSDimitry Andric     return false;
310f785676fSDimitry Andric 
311f785676fSDimitry Andric   // The relocation model is actually a static member of TargetMachine and
312f785676fSDimitry Andric   // needs to be set before the TargetMachine is instantiated.
313f785676fSDimitry Andric   Reloc::Model RelocModel = Reloc::Default;
314f785676fSDimitry Andric   switch (CodeModel) {
315f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_STATIC:
316f785676fSDimitry Andric     RelocModel = Reloc::Static;
317f785676fSDimitry Andric     break;
318f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
319f785676fSDimitry Andric     RelocModel = Reloc::PIC_;
320f785676fSDimitry Andric     break;
321f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
322f785676fSDimitry Andric     RelocModel = Reloc::DynamicNoPIC;
323f785676fSDimitry Andric     break;
32491bc56edSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
32591bc56edSDimitry Andric     // RelocModel is already the default, so leave it that way.
32691bc56edSDimitry Andric     break;
327f785676fSDimitry Andric   }
328f785676fSDimitry Andric 
32991bc56edSDimitry Andric   // Construct LTOModule, hand over ownership of module and target. Use MAttr as
33091bc56edSDimitry Andric   // the default set of features.
33191bc56edSDimitry Andric   SubtargetFeatures Features(MAttr);
332f785676fSDimitry Andric   Features.getDefaultSubtargetFeatures(Triple);
333f785676fSDimitry Andric   std::string FeatureStr = Features.getString();
334f785676fSDimitry Andric   // Set a default CPU for Darwin triples.
335f785676fSDimitry Andric   if (MCpu.empty() && Triple.isOSDarwin()) {
336f785676fSDimitry Andric     if (Triple.getArch() == llvm::Triple::x86_64)
337f785676fSDimitry Andric       MCpu = "core2";
338f785676fSDimitry Andric     else if (Triple.getArch() == llvm::Triple::x86)
339f785676fSDimitry Andric       MCpu = "yonah";
34039d628a0SDimitry Andric     else if (Triple.getArch() == llvm::Triple::aarch64)
34191bc56edSDimitry Andric       MCpu = "cyclone";
342f785676fSDimitry Andric   }
343f785676fSDimitry Andric 
344ff0cc061SDimitry Andric   CodeGenOpt::Level CGOptLevel;
345ff0cc061SDimitry Andric   switch (OptLevel) {
346ff0cc061SDimitry Andric   case 0:
347ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::None;
348ff0cc061SDimitry Andric     break;
349ff0cc061SDimitry Andric   case 1:
350ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Less;
351ff0cc061SDimitry Andric     break;
352ff0cc061SDimitry Andric   case 2:
353ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Default;
354ff0cc061SDimitry Andric     break;
355ff0cc061SDimitry Andric   case 3:
356ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Aggressive;
357ff0cc061SDimitry Andric     break;
358ff0cc061SDimitry Andric   }
359ff0cc061SDimitry Andric 
360f785676fSDimitry Andric   TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options,
361f785676fSDimitry Andric                                           RelocModel, CodeModel::Default,
362ff0cc061SDimitry Andric                                           CGOptLevel);
363f785676fSDimitry Andric   return true;
364f785676fSDimitry Andric }
365f785676fSDimitry Andric 
366f785676fSDimitry Andric void LTOCodeGenerator::
367f785676fSDimitry Andric applyRestriction(GlobalValue &GV,
36839d628a0SDimitry Andric                  ArrayRef<StringRef> Libcalls,
369f785676fSDimitry Andric                  std::vector<const char*> &MustPreserveList,
37039d628a0SDimitry Andric                  SmallPtrSetImpl<GlobalValue*> &AsmUsed,
371f785676fSDimitry Andric                  Mangler &Mangler) {
37291bc56edSDimitry Andric   // There are no restrictions to apply to declarations.
373f785676fSDimitry Andric   if (GV.isDeclaration())
374f785676fSDimitry Andric     return;
37591bc56edSDimitry Andric 
37691bc56edSDimitry Andric   // There is nothing more restrictive than private linkage.
37791bc56edSDimitry Andric   if (GV.hasPrivateLinkage())
37891bc56edSDimitry Andric     return;
37991bc56edSDimitry Andric 
38091bc56edSDimitry Andric   SmallString<64> Buffer;
38191bc56edSDimitry Andric   TargetMach->getNameWithPrefix(Buffer, &GV, Mangler);
38291bc56edSDimitry Andric 
383f785676fSDimitry Andric   if (MustPreserveSymbols.count(Buffer))
384f785676fSDimitry Andric     MustPreserveList.push_back(GV.getName().data());
385f785676fSDimitry Andric   if (AsmUndefinedRefs.count(Buffer))
386f785676fSDimitry Andric     AsmUsed.insert(&GV);
387f785676fSDimitry Andric 
388f785676fSDimitry Andric   // Conservatively append user-supplied runtime library functions to
389f785676fSDimitry Andric   // llvm.compiler.used.  These could be internalized and deleted by
390f785676fSDimitry Andric   // optimizations like -globalopt, causing problems when later optimizations
391f785676fSDimitry Andric   // add new library calls (e.g., llvm.memset => memset and printf => puts).
392f785676fSDimitry Andric   // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
393f785676fSDimitry Andric   if (isa<Function>(GV) &&
394f785676fSDimitry Andric       std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName()))
395f785676fSDimitry Andric     AsmUsed.insert(&GV);
396f785676fSDimitry Andric }
397f785676fSDimitry Andric 
398f785676fSDimitry Andric static void findUsedValues(GlobalVariable *LLVMUsed,
39939d628a0SDimitry Andric                            SmallPtrSetImpl<GlobalValue*> &UsedValues) {
40091bc56edSDimitry Andric   if (!LLVMUsed) return;
401f785676fSDimitry Andric 
402f785676fSDimitry Andric   ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
403f785676fSDimitry Andric   for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
404f785676fSDimitry Andric     if (GlobalValue *GV =
405f785676fSDimitry Andric         dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
406f785676fSDimitry Andric       UsedValues.insert(GV);
407f785676fSDimitry Andric }
408f785676fSDimitry Andric 
409ff0cc061SDimitry Andric // Collect names of runtime library functions. User-defined functions with the
410ff0cc061SDimitry Andric // same names are added to llvm.compiler.used to prevent them from being
411ff0cc061SDimitry Andric // deleted by optimizations.
412f785676fSDimitry Andric static void accumulateAndSortLibcalls(std::vector<StringRef> &Libcalls,
413f785676fSDimitry Andric                                       const TargetLibraryInfo& TLI,
414ff0cc061SDimitry Andric                                       const Module &Mod,
415ff0cc061SDimitry Andric                                       const TargetMachine &TM) {
416f785676fSDimitry Andric   // TargetLibraryInfo has info on C runtime library calls on the current
417f785676fSDimitry Andric   // target.
418f785676fSDimitry Andric   for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
419f785676fSDimitry Andric        I != E; ++I) {
420f785676fSDimitry Andric     LibFunc::Func F = static_cast<LibFunc::Func>(I);
421f785676fSDimitry Andric     if (TLI.has(F))
422f785676fSDimitry Andric       Libcalls.push_back(TLI.getName(F));
423f785676fSDimitry Andric   }
424f785676fSDimitry Andric 
425ff0cc061SDimitry Andric   SmallPtrSet<const TargetLowering *, 1> TLSet;
426ff0cc061SDimitry Andric 
427ff0cc061SDimitry Andric   for (const Function &F : Mod) {
428ff0cc061SDimitry Andric     const TargetLowering *Lowering =
429ff0cc061SDimitry Andric         TM.getSubtargetImpl(F)->getTargetLowering();
430ff0cc061SDimitry Andric 
431ff0cc061SDimitry Andric     if (Lowering && TLSet.insert(Lowering).second)
432f785676fSDimitry Andric       // TargetLowering has info on library calls that CodeGen expects to be
433f785676fSDimitry Andric       // available, both from the C runtime and compiler-rt.
434f785676fSDimitry Andric       for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
435f785676fSDimitry Andric            I != E; ++I)
436ff0cc061SDimitry Andric         if (const char *Name =
437ff0cc061SDimitry Andric                 Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
438f785676fSDimitry Andric           Libcalls.push_back(Name);
439ff0cc061SDimitry Andric   }
440f785676fSDimitry Andric 
441f785676fSDimitry Andric   array_pod_sort(Libcalls.begin(), Libcalls.end());
442f785676fSDimitry Andric   Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()),
443f785676fSDimitry Andric                  Libcalls.end());
444f785676fSDimitry Andric }
445f785676fSDimitry Andric 
446f785676fSDimitry Andric void LTOCodeGenerator::applyScopeRestrictions() {
447ff0cc061SDimitry Andric   if (ScopeRestrictionsDone || !ShouldInternalize)
448f785676fSDimitry Andric     return;
44991bc56edSDimitry Andric   Module *mergedModule = IRLinker.getModule();
450f785676fSDimitry Andric 
451f785676fSDimitry Andric   // Start off with a verification pass.
452ff0cc061SDimitry Andric   legacy::PassManager passes;
453f785676fSDimitry Andric   passes.add(createVerifierPass());
454f785676fSDimitry Andric 
455f785676fSDimitry Andric   // mark which symbols can not be internalized
456ff0cc061SDimitry Andric   Mangler Mangler(TargetMach->getDataLayout());
457f785676fSDimitry Andric   std::vector<const char*> MustPreserveList;
458f785676fSDimitry Andric   SmallPtrSet<GlobalValue*, 8> AsmUsed;
459f785676fSDimitry Andric   std::vector<StringRef> Libcalls;
460ff0cc061SDimitry Andric   TargetLibraryInfoImpl TLII(Triple(TargetMach->getTargetTriple()));
461ff0cc061SDimitry Andric   TargetLibraryInfo TLI(TLII);
462ff0cc061SDimitry Andric 
463ff0cc061SDimitry Andric   accumulateAndSortLibcalls(Libcalls, TLI, *mergedModule, *TargetMach);
464f785676fSDimitry Andric 
465f785676fSDimitry Andric   for (Module::iterator f = mergedModule->begin(),
466f785676fSDimitry Andric          e = mergedModule->end(); f != e; ++f)
467f785676fSDimitry Andric     applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler);
468f785676fSDimitry Andric   for (Module::global_iterator v = mergedModule->global_begin(),
469f785676fSDimitry Andric          e = mergedModule->global_end(); v !=  e; ++v)
470f785676fSDimitry Andric     applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler);
471f785676fSDimitry Andric   for (Module::alias_iterator a = mergedModule->alias_begin(),
472f785676fSDimitry Andric          e = mergedModule->alias_end(); a != e; ++a)
473f785676fSDimitry Andric     applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler);
474f785676fSDimitry Andric 
475f785676fSDimitry Andric   GlobalVariable *LLVMCompilerUsed =
476f785676fSDimitry Andric     mergedModule->getGlobalVariable("llvm.compiler.used");
477f785676fSDimitry Andric   findUsedValues(LLVMCompilerUsed, AsmUsed);
478f785676fSDimitry Andric   if (LLVMCompilerUsed)
479f785676fSDimitry Andric     LLVMCompilerUsed->eraseFromParent();
480f785676fSDimitry Andric 
481f785676fSDimitry Andric   if (!AsmUsed.empty()) {
482f785676fSDimitry Andric     llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context);
483f785676fSDimitry Andric     std::vector<Constant*> asmUsed2;
48491bc56edSDimitry Andric     for (auto *GV : AsmUsed) {
485f785676fSDimitry Andric       Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
486f785676fSDimitry Andric       asmUsed2.push_back(c);
487f785676fSDimitry Andric     }
488f785676fSDimitry Andric 
489f785676fSDimitry Andric     llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
490f785676fSDimitry Andric     LLVMCompilerUsed =
491f785676fSDimitry Andric       new llvm::GlobalVariable(*mergedModule, ATy, false,
492f785676fSDimitry Andric                                llvm::GlobalValue::AppendingLinkage,
493f785676fSDimitry Andric                                llvm::ConstantArray::get(ATy, asmUsed2),
494f785676fSDimitry Andric                                "llvm.compiler.used");
495f785676fSDimitry Andric 
496f785676fSDimitry Andric     LLVMCompilerUsed->setSection("llvm.metadata");
497f785676fSDimitry Andric   }
498f785676fSDimitry Andric 
499f785676fSDimitry Andric   passes.add(createInternalizePass(MustPreserveList));
500f785676fSDimitry Andric 
501f785676fSDimitry Andric   // apply scope restrictions
502f785676fSDimitry Andric   passes.run(*mergedModule);
503f785676fSDimitry Andric 
504f785676fSDimitry Andric   ScopeRestrictionsDone = true;
505f785676fSDimitry Andric }
506f785676fSDimitry Andric 
507f785676fSDimitry Andric /// Optimize merged modules using various IPO passes
508ff0cc061SDimitry Andric bool LTOCodeGenerator::optimize(bool DisableInline,
509f785676fSDimitry Andric                                 bool DisableGVNLoadPRE,
51039d628a0SDimitry Andric                                 bool DisableVectorization,
511f785676fSDimitry Andric                                 std::string &errMsg) {
512f785676fSDimitry Andric   if (!this->determineTarget(errMsg))
513f785676fSDimitry Andric     return false;
514f785676fSDimitry Andric 
51591bc56edSDimitry Andric   Module *mergedModule = IRLinker.getModule();
516f785676fSDimitry Andric 
517f785676fSDimitry Andric   // Mark which symbols can not be internalized
518f785676fSDimitry Andric   this->applyScopeRestrictions();
519f785676fSDimitry Andric 
520f785676fSDimitry Andric   // Instantiate the pass manager to organize the passes.
521ff0cc061SDimitry Andric   legacy::PassManager passes;
522f785676fSDimitry Andric 
523f785676fSDimitry Andric   // Add an appropriate DataLayout instance for this module...
524ff0cc061SDimitry Andric   mergedModule->setDataLayout(*TargetMach->getDataLayout());
525ff0cc061SDimitry Andric 
526ff0cc061SDimitry Andric   passes.add(
527ff0cc061SDimitry Andric       createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis()));
52891bc56edSDimitry Andric 
52939d628a0SDimitry Andric   Triple TargetTriple(TargetMach->getTargetTriple());
53039d628a0SDimitry Andric   PassManagerBuilder PMB;
53139d628a0SDimitry Andric   PMB.DisableGVNLoadPRE = DisableGVNLoadPRE;
53239d628a0SDimitry Andric   PMB.LoopVectorize = !DisableVectorization;
53339d628a0SDimitry Andric   PMB.SLPVectorize = !DisableVectorization;
53439d628a0SDimitry Andric   if (!DisableInline)
53539d628a0SDimitry Andric     PMB.Inliner = createFunctionInliningPass();
536ff0cc061SDimitry Andric   PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple);
537ff0cc061SDimitry Andric   PMB.OptLevel = OptLevel;
53839d628a0SDimitry Andric   PMB.VerifyInput = true;
53939d628a0SDimitry Andric   PMB.VerifyOutput = true;
54091bc56edSDimitry Andric 
541ff0cc061SDimitry Andric   PMB.populateLTOPassManager(passes);
542f785676fSDimitry Andric 
543ff0cc061SDimitry Andric   // Run our queue of passes all at once now, efficiently.
544ff0cc061SDimitry Andric   passes.run(*mergedModule);
545f785676fSDimitry Andric 
546ff0cc061SDimitry Andric   return true;
547ff0cc061SDimitry Andric }
548f785676fSDimitry Andric 
549ff0cc061SDimitry Andric bool LTOCodeGenerator::compileOptimized(raw_pwrite_stream &out,
550ff0cc061SDimitry Andric                                         std::string &errMsg) {
551ff0cc061SDimitry Andric   if (!this->determineTarget(errMsg))
552ff0cc061SDimitry Andric     return false;
553ff0cc061SDimitry Andric 
554ff0cc061SDimitry Andric   Module *mergedModule = IRLinker.getModule();
555ff0cc061SDimitry Andric 
556ff0cc061SDimitry Andric   legacy::PassManager codeGenPasses;
557f785676fSDimitry Andric 
558f785676fSDimitry Andric   // If the bitcode files contain ARC code and were compiled with optimization,
559f785676fSDimitry Andric   // the ObjCARCContractPass must be run, so do it unconditionally here.
560f785676fSDimitry Andric   codeGenPasses.add(createObjCARCContractPass());
561f785676fSDimitry Andric 
562ff0cc061SDimitry Andric   if (TargetMach->addPassesToEmitFile(codeGenPasses, out,
563f785676fSDimitry Andric                                       TargetMachine::CGFT_ObjectFile)) {
564f785676fSDimitry Andric     errMsg = "target file type not supported";
565f785676fSDimitry Andric     return false;
566f785676fSDimitry Andric   }
567f785676fSDimitry Andric 
568f785676fSDimitry Andric   // Run the code generator, and write assembly file
569f785676fSDimitry Andric   codeGenPasses.run(*mergedModule);
570f785676fSDimitry Andric 
571f785676fSDimitry Andric   return true;
572f785676fSDimitry Andric }
573f785676fSDimitry Andric 
574f785676fSDimitry Andric /// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging
575f785676fSDimitry Andric /// LTO problems.
576f785676fSDimitry Andric void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) {
577f785676fSDimitry Andric   for (std::pair<StringRef, StringRef> o = getToken(options);
578f785676fSDimitry Andric        !o.first.empty(); o = getToken(o.second)) {
579f785676fSDimitry Andric     // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add
580f785676fSDimitry Andric     // that.
581f785676fSDimitry Andric     if (CodegenOptions.empty())
582f785676fSDimitry Andric       CodegenOptions.push_back(strdup("libLLVMLTO"));
583f785676fSDimitry Andric     CodegenOptions.push_back(strdup(o.first.str().c_str()));
584f785676fSDimitry Andric   }
585f785676fSDimitry Andric }
586f785676fSDimitry Andric 
587f785676fSDimitry Andric void LTOCodeGenerator::parseCodeGenDebugOptions() {
588f785676fSDimitry Andric   // if options were requested, set them
589f785676fSDimitry Andric   if (!CodegenOptions.empty())
590f785676fSDimitry Andric     cl::ParseCommandLineOptions(CodegenOptions.size(),
591f785676fSDimitry Andric                                 const_cast<char **>(&CodegenOptions[0]));
592f785676fSDimitry Andric }
59391bc56edSDimitry Andric 
59491bc56edSDimitry Andric void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,
59591bc56edSDimitry Andric                                          void *Context) {
59691bc56edSDimitry Andric   ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI);
59791bc56edSDimitry Andric }
59891bc56edSDimitry Andric 
59991bc56edSDimitry Andric void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
60091bc56edSDimitry Andric   // Map the LLVM internal diagnostic severity to the LTO diagnostic severity.
60191bc56edSDimitry Andric   lto_codegen_diagnostic_severity_t Severity;
60291bc56edSDimitry Andric   switch (DI.getSeverity()) {
60391bc56edSDimitry Andric   case DS_Error:
60491bc56edSDimitry Andric     Severity = LTO_DS_ERROR;
60591bc56edSDimitry Andric     break;
60691bc56edSDimitry Andric   case DS_Warning:
60791bc56edSDimitry Andric     Severity = LTO_DS_WARNING;
60891bc56edSDimitry Andric     break;
60991bc56edSDimitry Andric   case DS_Remark:
61091bc56edSDimitry Andric     Severity = LTO_DS_REMARK;
61191bc56edSDimitry Andric     break;
61291bc56edSDimitry Andric   case DS_Note:
61391bc56edSDimitry Andric     Severity = LTO_DS_NOTE;
61491bc56edSDimitry Andric     break;
61591bc56edSDimitry Andric   }
61691bc56edSDimitry Andric   // Create the string that will be reported to the external diagnostic handler.
61791bc56edSDimitry Andric   std::string MsgStorage;
61891bc56edSDimitry Andric   raw_string_ostream Stream(MsgStorage);
61991bc56edSDimitry Andric   DiagnosticPrinterRawOStream DP(Stream);
62091bc56edSDimitry Andric   DI.print(DP);
62191bc56edSDimitry Andric   Stream.flush();
62291bc56edSDimitry Andric 
62391bc56edSDimitry Andric   // If this method has been called it means someone has set up an external
62491bc56edSDimitry Andric   // diagnostic handler. Assert on that.
62591bc56edSDimitry Andric   assert(DiagHandler && "Invalid diagnostic handler");
62691bc56edSDimitry Andric   (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
62791bc56edSDimitry Andric }
62891bc56edSDimitry Andric 
62991bc56edSDimitry Andric void
63091bc56edSDimitry Andric LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
63191bc56edSDimitry Andric                                        void *Ctxt) {
63291bc56edSDimitry Andric   this->DiagHandler = DiagHandler;
63391bc56edSDimitry Andric   this->DiagContext = Ctxt;
63491bc56edSDimitry Andric   if (!DiagHandler)
63591bc56edSDimitry Andric     return Context.setDiagnosticHandler(nullptr, nullptr);
63691bc56edSDimitry Andric   // Register the LTOCodeGenerator stub in the LLVMContext to forward the
63791bc56edSDimitry Andric   // diagnostic to the external DiagHandler.
63839d628a0SDimitry Andric   Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this,
63939d628a0SDimitry Andric                                /* RespectFilters */ true);
64091bc56edSDimitry Andric }
641