1//===-LTOCodeGenerator.h - LLVM Link Time Optimizer -----------------------===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file declares the LTOCodeGenerator class. 10// 11// LTO compilation consists of three phases: Pre-IPO, IPO and Post-IPO. 12// 13// The Pre-IPO phase compiles source code into bitcode file. The resulting 14// bitcode files, along with object files and libraries, will be fed to the 15// linker to through the IPO and Post-IPO phases. By using obj-file extension, 16// the resulting bitcode file disguises itself as an object file, and therefore 17// obviates the need of writing a special set of the make-rules only for LTO 18// compilation. 19// 20// The IPO phase perform inter-procedural analyses and optimizations, and 21// the Post-IPO consists two sub-phases: intra-procedural scalar optimizations 22// (SOPT), and intra-procedural target-dependent code generator (CG). 23// 24// As of this writing, we don't separate IPO and the Post-IPO SOPT. They 25// are intermingled together, and are driven by a single pass manager (see 26// PassManagerBuilder::populateLTOPassManager()). 27// 28// The "LTOCodeGenerator" is the driver for the IPO and Post-IPO stages. 29// The "CodeGenerator" here is bit confusing. Don't confuse the "CodeGenerator" 30// with the machine specific code generator. 31// 32//===----------------------------------------------------------------------===// 33 34#ifndef LLVM_LTO_LTOCODEGENERATOR_H 35#define LLVM_LTO_LTOCODEGENERATOR_H 36 37#include "llvm-c/lto.h" 38#include "llvm/ADT/ArrayRef.h" 39#include "llvm/ADT/SmallPtrSet.h" 40#include "llvm/ADT/StringMap.h" 41#include "llvm/ADT/StringSet.h" 42#include "llvm/IR/GlobalValue.h" 43#include "llvm/IR/Module.h" 44#include "llvm/Support/CommandLine.h" 45#include "llvm/Support/Error.h" 46#include "llvm/Support/ToolOutputFile.h" 47#include "llvm/Target/TargetMachine.h" 48#include "llvm/Target/TargetOptions.h" 49#include <string> 50#include <vector> 51 52/// Enable global value internalization in LTO. 53extern llvm::cl::opt<bool> EnableLTOInternalization; 54 55namespace llvm { 56template <typename T> class ArrayRef; 57 class LLVMContext; 58 class DiagnosticInfo; 59 class Linker; 60 class Mangler; 61 class MemoryBuffer; 62 class TargetLibraryInfo; 63 class TargetMachine; 64 class raw_ostream; 65 class raw_pwrite_stream; 66 67//===----------------------------------------------------------------------===// 68/// C++ class which implements the opaque lto_code_gen_t type. 69/// 70struct LTOCodeGenerator { 71 static const char *getVersionString(); 72 73 LTOCodeGenerator(LLVMContext &Context); 74 ~LTOCodeGenerator(); 75 76 /// Merge given module. Return true on success. 77 /// 78 /// Resets \a HasVerifiedInput. 79 bool addModule(struct LTOModule *); 80 81 /// Set the destination module. 82 /// 83 /// Resets \a HasVerifiedInput. 84 void setModule(std::unique_ptr<LTOModule> M); 85 86 void setAsmUndefinedRefs(struct LTOModule *); 87 void setTargetOptions(const TargetOptions &Options); 88 void setDebugInfo(lto_debug_model); 89 void setCodePICModel(Optional<Reloc::Model> Model) { RelocModel = Model; } 90 91 /// Set the file type to be emitted (assembly or object code). 92 /// The default is CGFT_ObjectFile. 93 void setFileType(CodeGenFileType FT) { FileType = FT; } 94 95 void setCpu(StringRef MCpu) { this->MCpu = MCpu; } 96 void setAttr(StringRef MAttr) { this->MAttr = MAttr; } 97 void setOptLevel(unsigned OptLevel); 98 99 void setShouldInternalize(bool Value) { ShouldInternalize = Value; } 100 void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } 101 102 /// Restore linkage of globals 103 /// 104 /// When set, the linkage of globals will be restored prior to code 105 /// generation. That is, a global symbol that had external linkage prior to 106 /// LTO will be emitted with external linkage again; and a local will remain 107 /// local. Note that this option only affects the end result - globals may 108 /// still be internalized in the process of LTO and may be modified and/or 109 /// deleted where legal. 110 /// 111 /// The default behavior will internalize globals (unless on the preserve 112 /// list) and, if parallel code generation is enabled, will externalize 113 /// all locals. 114 void setShouldRestoreGlobalsLinkage(bool Value) { 115 ShouldRestoreGlobalsLinkage = Value; 116 } 117 118 void addMustPreserveSymbol(StringRef Sym) { MustPreserveSymbols.insert(Sym); } 119 120 /// Pass options to the driver and optimization passes. 121 /// 122 /// These options are not necessarily for debugging purpose (the function 123 /// name is misleading). This function should be called before 124 /// LTOCodeGenerator::compilexxx(), and 125 /// LTOCodeGenerator::writeMergedModules(). 126 void setCodeGenDebugOptions(ArrayRef<const char *> Opts); 127 128 /// Parse the options set in setCodeGenDebugOptions. 129 /// 130 /// Like \a setCodeGenDebugOptions(), this must be called before 131 /// LTOCodeGenerator::compilexxx() and 132 /// LTOCodeGenerator::writeMergedModules(). 133 void parseCodeGenDebugOptions(); 134 135 /// Write the merged module to the file specified by the given path. Return 136 /// true on success. 137 /// 138 /// Calls \a verifyMergedModuleOnce(). 139 bool writeMergedModules(StringRef Path); 140 141 /// Compile the merged module into a *single* output file; the path to output 142 /// file is returned to the caller via argument "name". Return true on 143 /// success. 144 /// 145 /// \note It is up to the linker to remove the intermediate output file. Do 146 /// not try to remove the object file in LTOCodeGenerator's destructor as we 147 /// don't who (LTOCodeGenerator or the output file) will last longer. 148 bool compile_to_file(const char **Name, bool DisableVerify, 149 bool DisableInline, bool DisableGVNLoadPRE, 150 bool DisableVectorization); 151 152 /// As with compile_to_file(), this function compiles the merged module into 153 /// single output file. Instead of returning the output file path to the 154 /// caller (linker), it brings the output to a buffer, and returns the buffer 155 /// to the caller. This function should delete the intermediate file once 156 /// its content is brought to memory. Return NULL if the compilation was not 157 /// successful. 158 std::unique_ptr<MemoryBuffer> compile(bool DisableVerify, bool DisableInline, 159 bool DisableGVNLoadPRE, 160 bool DisableVectorization); 161 162 /// Optimizes the merged module. Returns true on success. 163 /// 164 /// Calls \a verifyMergedModuleOnce(). 165 bool optimize(bool DisableVerify, bool DisableInline, bool DisableGVNLoadPRE, 166 bool DisableVectorization); 167 168 /// Compiles the merged optimized module into a single output file. It brings 169 /// the output to a buffer, and returns the buffer to the caller. Return NULL 170 /// if the compilation was not successful. 171 std::unique_ptr<MemoryBuffer> compileOptimized(); 172 173 /// Compile the merged optimized module into out.size() output files each 174 /// representing a linkable partition of the module. If out contains more 175 /// than one element, code generation is done in parallel with out.size() 176 /// threads. Output files will be written to members of out. Returns true on 177 /// success. 178 /// 179 /// Calls \a verifyMergedModuleOnce(). 180 bool compileOptimized(ArrayRef<raw_pwrite_stream *> Out); 181 182 /// Enable the Freestanding mode: indicate that the optimizer should not 183 /// assume builtins are present on the target. 184 void setFreestanding(bool Enabled) { Freestanding = Enabled; } 185 186 void setDiagnosticHandler(lto_diagnostic_handler_t, void *); 187 188 LLVMContext &getContext() { return Context; } 189 190 void resetMergedModule() { MergedModule.reset(); } 191 void DiagnosticHandler(const DiagnosticInfo &DI); 192 193private: 194 void initializeLTOPasses(); 195 196 /// Verify the merged module on first call. 197 /// 198 /// Sets \a HasVerifiedInput on first call and doesn't run again on the same 199 /// input. 200 void verifyMergedModuleOnce(); 201 202 bool compileOptimizedToFile(const char **Name); 203 void restoreLinkageForExternals(); 204 void applyScopeRestrictions(); 205 void preserveDiscardableGVs( 206 Module &TheModule, 207 llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV); 208 209 bool determineTarget(); 210 std::unique_ptr<TargetMachine> createTargetMachine(); 211 212 void emitError(const std::string &ErrMsg); 213 void emitWarning(const std::string &ErrMsg); 214 215 void finishOptimizationRemarks(); 216 217 LLVMContext &Context; 218 std::unique_ptr<Module> MergedModule; 219 std::unique_ptr<Linker> TheLinker; 220 std::unique_ptr<TargetMachine> TargetMach; 221 bool EmitDwarfDebugInfo = false; 222 bool ScopeRestrictionsDone = false; 223 bool HasVerifiedInput = false; 224 Optional<Reloc::Model> RelocModel; 225 StringSet<> MustPreserveSymbols; 226 StringSet<> AsmUndefinedRefs; 227 StringMap<GlobalValue::LinkageTypes> ExternalSymbols; 228 std::vector<std::string> CodegenOptions; 229 std::string FeatureStr; 230 std::string MCpu; 231 std::string MAttr; 232 std::string NativeObjectPath; 233 TargetOptions Options; 234 CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default; 235 const Target *MArch = nullptr; 236 std::string TripleStr; 237 unsigned OptLevel = 2; 238 lto_diagnostic_handler_t DiagHandler = nullptr; 239 void *DiagContext = nullptr; 240 bool ShouldInternalize = EnableLTOInternalization; 241 bool ShouldEmbedUselists = false; 242 bool ShouldRestoreGlobalsLinkage = false; 243 CodeGenFileType FileType = CGFT_ObjectFile; 244 std::unique_ptr<ToolOutputFile> DiagnosticOutputFile; 245 bool Freestanding = false; 246 std::unique_ptr<ToolOutputFile> StatsFile = nullptr; 247}; 248} 249#endif 250