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 
253ff0cc061SDimitry Andric const void *LTOCodeGenerator::compileOptimized(size_t *length,
254f785676fSDimitry Andric                                                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   }
26739d628a0SDimitry Andric   NativeObjectFile = std::move(*BufferOrErr);
268f785676fSDimitry Andric 
269f785676fSDimitry Andric   // remove temp files
270f785676fSDimitry Andric   sys::fs::remove(NativeObjectPath);
271f785676fSDimitry Andric 
272f785676fSDimitry Andric   // return buffer, unless error
27391bc56edSDimitry Andric   if (!NativeObjectFile)
27491bc56edSDimitry Andric     return nullptr;
275f785676fSDimitry Andric   *length = NativeObjectFile->getBufferSize();
276f785676fSDimitry Andric   return NativeObjectFile->getBufferStart();
277f785676fSDimitry Andric }
278f785676fSDimitry Andric 
279ff0cc061SDimitry Andric 
280ff0cc061SDimitry Andric bool LTOCodeGenerator::compile_to_file(const char **name,
281ff0cc061SDimitry Andric                                        bool disableInline,
282ff0cc061SDimitry Andric                                        bool disableGVNLoadPRE,
283ff0cc061SDimitry Andric                                        bool disableVectorization,
284ff0cc061SDimitry Andric                                        std::string &errMsg) {
285ff0cc061SDimitry Andric   if (!optimize(disableInline, disableGVNLoadPRE,
286ff0cc061SDimitry Andric                 disableVectorization, errMsg))
287ff0cc061SDimitry Andric     return false;
288ff0cc061SDimitry Andric 
289ff0cc061SDimitry Andric   return compileOptimizedToFile(name, errMsg);
290ff0cc061SDimitry Andric }
291ff0cc061SDimitry Andric 
292ff0cc061SDimitry Andric const void* LTOCodeGenerator::compile(size_t *length,
293ff0cc061SDimitry Andric                                       bool disableInline,
294ff0cc061SDimitry Andric                                       bool disableGVNLoadPRE,
295ff0cc061SDimitry Andric                                       bool disableVectorization,
296ff0cc061SDimitry Andric                                       std::string &errMsg) {
297ff0cc061SDimitry Andric   if (!optimize(disableInline, disableGVNLoadPRE,
298ff0cc061SDimitry Andric                 disableVectorization, errMsg))
299ff0cc061SDimitry Andric     return nullptr;
300ff0cc061SDimitry Andric 
301ff0cc061SDimitry Andric   return compileOptimized(length, errMsg);
302ff0cc061SDimitry Andric }
303ff0cc061SDimitry Andric 
304f785676fSDimitry Andric bool LTOCodeGenerator::determineTarget(std::string &errMsg) {
30591bc56edSDimitry Andric   if (TargetMach)
306f785676fSDimitry Andric     return true;
307f785676fSDimitry Andric 
30891bc56edSDimitry Andric   std::string TripleStr = IRLinker.getModule()->getTargetTriple();
309f785676fSDimitry Andric   if (TripleStr.empty())
310f785676fSDimitry Andric     TripleStr = sys::getDefaultTargetTriple();
311f785676fSDimitry Andric   llvm::Triple Triple(TripleStr);
312f785676fSDimitry Andric 
313f785676fSDimitry Andric   // create target machine from info for merged modules
314f785676fSDimitry Andric   const Target *march = TargetRegistry::lookupTarget(TripleStr, errMsg);
31591bc56edSDimitry Andric   if (!march)
316f785676fSDimitry Andric     return false;
317f785676fSDimitry Andric 
318f785676fSDimitry Andric   // The relocation model is actually a static member of TargetMachine and
319f785676fSDimitry Andric   // needs to be set before the TargetMachine is instantiated.
320f785676fSDimitry Andric   Reloc::Model RelocModel = Reloc::Default;
321f785676fSDimitry Andric   switch (CodeModel) {
322f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_STATIC:
323f785676fSDimitry Andric     RelocModel = Reloc::Static;
324f785676fSDimitry Andric     break;
325f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC:
326f785676fSDimitry Andric     RelocModel = Reloc::PIC_;
327f785676fSDimitry Andric     break;
328f785676fSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC:
329f785676fSDimitry Andric     RelocModel = Reloc::DynamicNoPIC;
330f785676fSDimitry Andric     break;
33191bc56edSDimitry Andric   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
33291bc56edSDimitry Andric     // RelocModel is already the default, so leave it that way.
33391bc56edSDimitry Andric     break;
334f785676fSDimitry Andric   }
335f785676fSDimitry Andric 
33691bc56edSDimitry Andric   // Construct LTOModule, hand over ownership of module and target. Use MAttr as
33791bc56edSDimitry Andric   // the default set of features.
33891bc56edSDimitry Andric   SubtargetFeatures Features(MAttr);
339f785676fSDimitry Andric   Features.getDefaultSubtargetFeatures(Triple);
340f785676fSDimitry Andric   std::string FeatureStr = Features.getString();
341f785676fSDimitry Andric   // Set a default CPU for Darwin triples.
342f785676fSDimitry Andric   if (MCpu.empty() && Triple.isOSDarwin()) {
343f785676fSDimitry Andric     if (Triple.getArch() == llvm::Triple::x86_64)
344f785676fSDimitry Andric       MCpu = "core2";
345f785676fSDimitry Andric     else if (Triple.getArch() == llvm::Triple::x86)
346f785676fSDimitry Andric       MCpu = "yonah";
34739d628a0SDimitry Andric     else if (Triple.getArch() == llvm::Triple::aarch64)
34891bc56edSDimitry Andric       MCpu = "cyclone";
349f785676fSDimitry Andric   }
350f785676fSDimitry Andric 
351ff0cc061SDimitry Andric   CodeGenOpt::Level CGOptLevel;
352ff0cc061SDimitry Andric   switch (OptLevel) {
353ff0cc061SDimitry Andric   case 0:
354ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::None;
355ff0cc061SDimitry Andric     break;
356ff0cc061SDimitry Andric   case 1:
357ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Less;
358ff0cc061SDimitry Andric     break;
359ff0cc061SDimitry Andric   case 2:
360ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Default;
361ff0cc061SDimitry Andric     break;
362ff0cc061SDimitry Andric   case 3:
363ff0cc061SDimitry Andric     CGOptLevel = CodeGenOpt::Aggressive;
364ff0cc061SDimitry Andric     break;
365ff0cc061SDimitry Andric   }
366ff0cc061SDimitry Andric 
367f785676fSDimitry Andric   TargetMach = march->createTargetMachine(TripleStr, MCpu, FeatureStr, Options,
368f785676fSDimitry Andric                                           RelocModel, CodeModel::Default,
369ff0cc061SDimitry Andric                                           CGOptLevel);
370f785676fSDimitry Andric   return true;
371f785676fSDimitry Andric }
372f785676fSDimitry Andric 
373f785676fSDimitry Andric void LTOCodeGenerator::
374f785676fSDimitry Andric applyRestriction(GlobalValue &GV,
37539d628a0SDimitry Andric                  ArrayRef<StringRef> Libcalls,
376f785676fSDimitry Andric                  std::vector<const char*> &MustPreserveList,
37739d628a0SDimitry Andric                  SmallPtrSetImpl<GlobalValue*> &AsmUsed,
378f785676fSDimitry Andric                  Mangler &Mangler) {
37991bc56edSDimitry Andric   // There are no restrictions to apply to declarations.
380f785676fSDimitry Andric   if (GV.isDeclaration())
381f785676fSDimitry Andric     return;
38291bc56edSDimitry Andric 
38391bc56edSDimitry Andric   // There is nothing more restrictive than private linkage.
38491bc56edSDimitry Andric   if (GV.hasPrivateLinkage())
38591bc56edSDimitry Andric     return;
38691bc56edSDimitry Andric 
38791bc56edSDimitry Andric   SmallString<64> Buffer;
38891bc56edSDimitry Andric   TargetMach->getNameWithPrefix(Buffer, &GV, Mangler);
38991bc56edSDimitry Andric 
390f785676fSDimitry Andric   if (MustPreserveSymbols.count(Buffer))
391f785676fSDimitry Andric     MustPreserveList.push_back(GV.getName().data());
392f785676fSDimitry Andric   if (AsmUndefinedRefs.count(Buffer))
393f785676fSDimitry Andric     AsmUsed.insert(&GV);
394f785676fSDimitry Andric 
395f785676fSDimitry Andric   // Conservatively append user-supplied runtime library functions to
396f785676fSDimitry Andric   // llvm.compiler.used.  These could be internalized and deleted by
397f785676fSDimitry Andric   // optimizations like -globalopt, causing problems when later optimizations
398f785676fSDimitry Andric   // add new library calls (e.g., llvm.memset => memset and printf => puts).
399f785676fSDimitry Andric   // Leave it to the linker to remove any dead code (e.g. with -dead_strip).
400f785676fSDimitry Andric   if (isa<Function>(GV) &&
401f785676fSDimitry Andric       std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName()))
402f785676fSDimitry Andric     AsmUsed.insert(&GV);
403f785676fSDimitry Andric }
404f785676fSDimitry Andric 
405f785676fSDimitry Andric static void findUsedValues(GlobalVariable *LLVMUsed,
40639d628a0SDimitry Andric                            SmallPtrSetImpl<GlobalValue*> &UsedValues) {
40791bc56edSDimitry Andric   if (!LLVMUsed) return;
408f785676fSDimitry Andric 
409f785676fSDimitry Andric   ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
410f785676fSDimitry Andric   for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
411f785676fSDimitry Andric     if (GlobalValue *GV =
412f785676fSDimitry Andric         dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
413f785676fSDimitry Andric       UsedValues.insert(GV);
414f785676fSDimitry Andric }
415f785676fSDimitry Andric 
416ff0cc061SDimitry Andric // Collect names of runtime library functions. User-defined functions with the
417ff0cc061SDimitry Andric // same names are added to llvm.compiler.used to prevent them from being
418ff0cc061SDimitry Andric // deleted by optimizations.
419f785676fSDimitry Andric static void accumulateAndSortLibcalls(std::vector<StringRef> &Libcalls,
420f785676fSDimitry Andric                                       const TargetLibraryInfo& TLI,
421ff0cc061SDimitry Andric                                       const Module &Mod,
422ff0cc061SDimitry Andric                                       const TargetMachine &TM) {
423f785676fSDimitry Andric   // TargetLibraryInfo has info on C runtime library calls on the current
424f785676fSDimitry Andric   // target.
425f785676fSDimitry Andric   for (unsigned I = 0, E = static_cast<unsigned>(LibFunc::NumLibFuncs);
426f785676fSDimitry Andric        I != E; ++I) {
427f785676fSDimitry Andric     LibFunc::Func F = static_cast<LibFunc::Func>(I);
428f785676fSDimitry Andric     if (TLI.has(F))
429f785676fSDimitry Andric       Libcalls.push_back(TLI.getName(F));
430f785676fSDimitry Andric   }
431f785676fSDimitry Andric 
432ff0cc061SDimitry Andric   SmallPtrSet<const TargetLowering *, 1> TLSet;
433ff0cc061SDimitry Andric 
434ff0cc061SDimitry Andric   for (const Function &F : Mod) {
435ff0cc061SDimitry Andric     const TargetLowering *Lowering =
436ff0cc061SDimitry Andric         TM.getSubtargetImpl(F)->getTargetLowering();
437ff0cc061SDimitry Andric 
438ff0cc061SDimitry Andric     if (Lowering && TLSet.insert(Lowering).second)
439f785676fSDimitry Andric       // TargetLowering has info on library calls that CodeGen expects to be
440f785676fSDimitry Andric       // available, both from the C runtime and compiler-rt.
441f785676fSDimitry Andric       for (unsigned I = 0, E = static_cast<unsigned>(RTLIB::UNKNOWN_LIBCALL);
442f785676fSDimitry Andric            I != E; ++I)
443ff0cc061SDimitry Andric         if (const char *Name =
444ff0cc061SDimitry Andric                 Lowering->getLibcallName(static_cast<RTLIB::Libcall>(I)))
445f785676fSDimitry Andric           Libcalls.push_back(Name);
446ff0cc061SDimitry Andric   }
447f785676fSDimitry Andric 
448f785676fSDimitry Andric   array_pod_sort(Libcalls.begin(), Libcalls.end());
449f785676fSDimitry Andric   Libcalls.erase(std::unique(Libcalls.begin(), Libcalls.end()),
450f785676fSDimitry Andric                  Libcalls.end());
451f785676fSDimitry Andric }
452f785676fSDimitry Andric 
453f785676fSDimitry Andric void LTOCodeGenerator::applyScopeRestrictions() {
454ff0cc061SDimitry Andric   if (ScopeRestrictionsDone || !ShouldInternalize)
455f785676fSDimitry Andric     return;
45691bc56edSDimitry Andric   Module *mergedModule = IRLinker.getModule();
457f785676fSDimitry Andric 
458f785676fSDimitry Andric   // Start off with a verification pass.
459ff0cc061SDimitry Andric   legacy::PassManager passes;
460f785676fSDimitry Andric   passes.add(createVerifierPass());
461f785676fSDimitry Andric 
462f785676fSDimitry Andric   // mark which symbols can not be internalized
463ff0cc061SDimitry Andric   Mangler Mangler(TargetMach->getDataLayout());
464f785676fSDimitry Andric   std::vector<const char*> MustPreserveList;
465f785676fSDimitry Andric   SmallPtrSet<GlobalValue*, 8> AsmUsed;
466f785676fSDimitry Andric   std::vector<StringRef> Libcalls;
467ff0cc061SDimitry Andric   TargetLibraryInfoImpl TLII(Triple(TargetMach->getTargetTriple()));
468ff0cc061SDimitry Andric   TargetLibraryInfo TLI(TLII);
469ff0cc061SDimitry Andric 
470ff0cc061SDimitry Andric   accumulateAndSortLibcalls(Libcalls, TLI, *mergedModule, *TargetMach);
471f785676fSDimitry Andric 
472f785676fSDimitry Andric   for (Module::iterator f = mergedModule->begin(),
473f785676fSDimitry Andric          e = mergedModule->end(); f != e; ++f)
474f785676fSDimitry Andric     applyRestriction(*f, Libcalls, MustPreserveList, AsmUsed, Mangler);
475f785676fSDimitry Andric   for (Module::global_iterator v = mergedModule->global_begin(),
476f785676fSDimitry Andric          e = mergedModule->global_end(); v !=  e; ++v)
477f785676fSDimitry Andric     applyRestriction(*v, Libcalls, MustPreserveList, AsmUsed, Mangler);
478f785676fSDimitry Andric   for (Module::alias_iterator a = mergedModule->alias_begin(),
479f785676fSDimitry Andric          e = mergedModule->alias_end(); a != e; ++a)
480f785676fSDimitry Andric     applyRestriction(*a, Libcalls, MustPreserveList, AsmUsed, Mangler);
481f785676fSDimitry Andric 
482f785676fSDimitry Andric   GlobalVariable *LLVMCompilerUsed =
483f785676fSDimitry Andric     mergedModule->getGlobalVariable("llvm.compiler.used");
484f785676fSDimitry Andric   findUsedValues(LLVMCompilerUsed, AsmUsed);
485f785676fSDimitry Andric   if (LLVMCompilerUsed)
486f785676fSDimitry Andric     LLVMCompilerUsed->eraseFromParent();
487f785676fSDimitry Andric 
488f785676fSDimitry Andric   if (!AsmUsed.empty()) {
489f785676fSDimitry Andric     llvm::Type *i8PTy = llvm::Type::getInt8PtrTy(Context);
490f785676fSDimitry Andric     std::vector<Constant*> asmUsed2;
49191bc56edSDimitry Andric     for (auto *GV : AsmUsed) {
492f785676fSDimitry Andric       Constant *c = ConstantExpr::getBitCast(GV, i8PTy);
493f785676fSDimitry Andric       asmUsed2.push_back(c);
494f785676fSDimitry Andric     }
495f785676fSDimitry Andric 
496f785676fSDimitry Andric     llvm::ArrayType *ATy = llvm::ArrayType::get(i8PTy, asmUsed2.size());
497f785676fSDimitry Andric     LLVMCompilerUsed =
498f785676fSDimitry Andric       new llvm::GlobalVariable(*mergedModule, ATy, false,
499f785676fSDimitry Andric                                llvm::GlobalValue::AppendingLinkage,
500f785676fSDimitry Andric                                llvm::ConstantArray::get(ATy, asmUsed2),
501f785676fSDimitry Andric                                "llvm.compiler.used");
502f785676fSDimitry Andric 
503f785676fSDimitry Andric     LLVMCompilerUsed->setSection("llvm.metadata");
504f785676fSDimitry Andric   }
505f785676fSDimitry Andric 
506f785676fSDimitry Andric   passes.add(createInternalizePass(MustPreserveList));
507f785676fSDimitry Andric 
508f785676fSDimitry Andric   // apply scope restrictions
509f785676fSDimitry Andric   passes.run(*mergedModule);
510f785676fSDimitry Andric 
511f785676fSDimitry Andric   ScopeRestrictionsDone = true;
512f785676fSDimitry Andric }
513f785676fSDimitry Andric 
514f785676fSDimitry Andric /// Optimize merged modules using various IPO passes
515ff0cc061SDimitry Andric bool LTOCodeGenerator::optimize(bool DisableInline,
516f785676fSDimitry Andric                                 bool DisableGVNLoadPRE,
51739d628a0SDimitry Andric                                 bool DisableVectorization,
518f785676fSDimitry Andric                                 std::string &errMsg) {
519f785676fSDimitry Andric   if (!this->determineTarget(errMsg))
520f785676fSDimitry Andric     return false;
521f785676fSDimitry Andric 
52291bc56edSDimitry Andric   Module *mergedModule = IRLinker.getModule();
523f785676fSDimitry Andric 
524f785676fSDimitry Andric   // Mark which symbols can not be internalized
525f785676fSDimitry Andric   this->applyScopeRestrictions();
526f785676fSDimitry Andric 
527f785676fSDimitry Andric   // Instantiate the pass manager to organize the passes.
528ff0cc061SDimitry Andric   legacy::PassManager passes;
529f785676fSDimitry Andric 
530f785676fSDimitry Andric   // Add an appropriate DataLayout instance for this module...
531ff0cc061SDimitry Andric   mergedModule->setDataLayout(*TargetMach->getDataLayout());
532ff0cc061SDimitry Andric 
533ff0cc061SDimitry Andric   passes.add(
534ff0cc061SDimitry Andric       createTargetTransformInfoWrapperPass(TargetMach->getTargetIRAnalysis()));
53591bc56edSDimitry Andric 
53639d628a0SDimitry Andric   Triple TargetTriple(TargetMach->getTargetTriple());
53739d628a0SDimitry Andric   PassManagerBuilder PMB;
53839d628a0SDimitry Andric   PMB.DisableGVNLoadPRE = DisableGVNLoadPRE;
53939d628a0SDimitry Andric   PMB.LoopVectorize = !DisableVectorization;
54039d628a0SDimitry Andric   PMB.SLPVectorize = !DisableVectorization;
54139d628a0SDimitry Andric   if (!DisableInline)
54239d628a0SDimitry Andric     PMB.Inliner = createFunctionInliningPass();
543ff0cc061SDimitry Andric   PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple);
544ff0cc061SDimitry Andric   PMB.OptLevel = OptLevel;
54539d628a0SDimitry Andric   PMB.VerifyInput = true;
54639d628a0SDimitry Andric   PMB.VerifyOutput = true;
54791bc56edSDimitry Andric 
548ff0cc061SDimitry Andric   PMB.populateLTOPassManager(passes);
549f785676fSDimitry Andric 
550ff0cc061SDimitry Andric   // Run our queue of passes all at once now, efficiently.
551ff0cc061SDimitry Andric   passes.run(*mergedModule);
552f785676fSDimitry Andric 
553ff0cc061SDimitry Andric   return true;
554ff0cc061SDimitry Andric }
555f785676fSDimitry Andric 
556ff0cc061SDimitry Andric bool LTOCodeGenerator::compileOptimized(raw_pwrite_stream &out,
557ff0cc061SDimitry Andric                                         std::string &errMsg) {
558ff0cc061SDimitry Andric   if (!this->determineTarget(errMsg))
559ff0cc061SDimitry Andric     return false;
560ff0cc061SDimitry Andric 
561ff0cc061SDimitry Andric   Module *mergedModule = IRLinker.getModule();
562ff0cc061SDimitry Andric 
563ff0cc061SDimitry Andric   legacy::PassManager codeGenPasses;
564f785676fSDimitry Andric 
565f785676fSDimitry Andric   // If the bitcode files contain ARC code and were compiled with optimization,
566f785676fSDimitry Andric   // the ObjCARCContractPass must be run, so do it unconditionally here.
567f785676fSDimitry Andric   codeGenPasses.add(createObjCARCContractPass());
568f785676fSDimitry Andric 
569ff0cc061SDimitry Andric   if (TargetMach->addPassesToEmitFile(codeGenPasses, out,
570f785676fSDimitry Andric                                       TargetMachine::CGFT_ObjectFile)) {
571f785676fSDimitry Andric     errMsg = "target file type not supported";
572f785676fSDimitry Andric     return false;
573f785676fSDimitry Andric   }
574f785676fSDimitry Andric 
575f785676fSDimitry Andric   // Run the code generator, and write assembly file
576f785676fSDimitry Andric   codeGenPasses.run(*mergedModule);
577f785676fSDimitry Andric 
578f785676fSDimitry Andric   return true;
579f785676fSDimitry Andric }
580f785676fSDimitry Andric 
581f785676fSDimitry Andric /// setCodeGenDebugOptions - Set codegen debugging options to aid in debugging
582f785676fSDimitry Andric /// LTO problems.
583f785676fSDimitry Andric void LTOCodeGenerator::setCodeGenDebugOptions(const char *options) {
584f785676fSDimitry Andric   for (std::pair<StringRef, StringRef> o = getToken(options);
585f785676fSDimitry Andric        !o.first.empty(); o = getToken(o.second)) {
586f785676fSDimitry Andric     // ParseCommandLineOptions() expects argv[0] to be program name. Lazily add
587f785676fSDimitry Andric     // that.
588f785676fSDimitry Andric     if (CodegenOptions.empty())
589f785676fSDimitry Andric       CodegenOptions.push_back(strdup("libLLVMLTO"));
590f785676fSDimitry Andric     CodegenOptions.push_back(strdup(o.first.str().c_str()));
591f785676fSDimitry Andric   }
592f785676fSDimitry Andric }
593f785676fSDimitry Andric 
594f785676fSDimitry Andric void LTOCodeGenerator::parseCodeGenDebugOptions() {
595f785676fSDimitry Andric   // if options were requested, set them
596f785676fSDimitry Andric   if (!CodegenOptions.empty())
597f785676fSDimitry Andric     cl::ParseCommandLineOptions(CodegenOptions.size(),
598f785676fSDimitry Andric                                 const_cast<char **>(&CodegenOptions[0]));
599f785676fSDimitry Andric }
60091bc56edSDimitry Andric 
60191bc56edSDimitry Andric void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI,
60291bc56edSDimitry Andric                                          void *Context) {
60391bc56edSDimitry Andric   ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI);
60491bc56edSDimitry Andric }
60591bc56edSDimitry Andric 
60691bc56edSDimitry Andric void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) {
60791bc56edSDimitry Andric   // Map the LLVM internal diagnostic severity to the LTO diagnostic severity.
60891bc56edSDimitry Andric   lto_codegen_diagnostic_severity_t Severity;
60991bc56edSDimitry Andric   switch (DI.getSeverity()) {
61091bc56edSDimitry Andric   case DS_Error:
61191bc56edSDimitry Andric     Severity = LTO_DS_ERROR;
61291bc56edSDimitry Andric     break;
61391bc56edSDimitry Andric   case DS_Warning:
61491bc56edSDimitry Andric     Severity = LTO_DS_WARNING;
61591bc56edSDimitry Andric     break;
61691bc56edSDimitry Andric   case DS_Remark:
61791bc56edSDimitry Andric     Severity = LTO_DS_REMARK;
61891bc56edSDimitry Andric     break;
61991bc56edSDimitry Andric   case DS_Note:
62091bc56edSDimitry Andric     Severity = LTO_DS_NOTE;
62191bc56edSDimitry Andric     break;
62291bc56edSDimitry Andric   }
62391bc56edSDimitry Andric   // Create the string that will be reported to the external diagnostic handler.
62491bc56edSDimitry Andric   std::string MsgStorage;
62591bc56edSDimitry Andric   raw_string_ostream Stream(MsgStorage);
62691bc56edSDimitry Andric   DiagnosticPrinterRawOStream DP(Stream);
62791bc56edSDimitry Andric   DI.print(DP);
62891bc56edSDimitry Andric   Stream.flush();
62991bc56edSDimitry Andric 
63091bc56edSDimitry Andric   // If this method has been called it means someone has set up an external
63191bc56edSDimitry Andric   // diagnostic handler. Assert on that.
63291bc56edSDimitry Andric   assert(DiagHandler && "Invalid diagnostic handler");
63391bc56edSDimitry Andric   (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext);
63491bc56edSDimitry Andric }
63591bc56edSDimitry Andric 
63691bc56edSDimitry Andric void
63791bc56edSDimitry Andric LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler,
63891bc56edSDimitry Andric                                        void *Ctxt) {
63991bc56edSDimitry Andric   this->DiagHandler = DiagHandler;
64091bc56edSDimitry Andric   this->DiagContext = Ctxt;
64191bc56edSDimitry Andric   if (!DiagHandler)
64291bc56edSDimitry Andric     return Context.setDiagnosticHandler(nullptr, nullptr);
64391bc56edSDimitry Andric   // Register the LTOCodeGenerator stub in the LLVMContext to forward the
64491bc56edSDimitry Andric   // diagnostic to the external DiagHandler.
64539d628a0SDimitry Andric   Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this,
64639d628a0SDimitry Andric                                /* RespectFilters */ true);
64791bc56edSDimitry Andric }
648