1//===-- llvm-lto: a simple command-line program to link modules with LTO --===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This program takes in a list of bitcode files, links them, performs link-time 11// optimization, and outputs an object file. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/ADT/StringSet.h" 16#include "llvm/CodeGen/CommandFlags.h" 17#include "llvm/LTO/LTOCodeGenerator.h" 18#include "llvm/LTO/LTOModule.h" 19#include "llvm/Support/CommandLine.h" 20#include "llvm/Support/FileSystem.h" 21#include "llvm/Support/ManagedStatic.h" 22#include "llvm/Support/PrettyStackTrace.h" 23#include "llvm/Support/Signals.h" 24#include "llvm/Support/TargetSelect.h" 25#include "llvm/Support/raw_ostream.h" 26 27using namespace llvm; 28 29static cl::opt<char> 30OptLevel("O", 31 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " 32 "(default = '-O2')"), 33 cl::Prefix, 34 cl::ZeroOrMore, 35 cl::init('2')); 36 37static cl::opt<bool> 38DisableInline("disable-inlining", cl::init(false), 39 cl::desc("Do not run the inliner pass")); 40 41static cl::opt<bool> 42DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), 43 cl::desc("Do not run the GVN load PRE pass")); 44 45static cl::opt<bool> 46DisableLTOVectorization("disable-lto-vectorization", cl::init(false), 47 cl::desc("Do not run loop or slp vectorization during LTO")); 48 49static cl::opt<bool> 50UseDiagnosticHandler("use-diagnostic-handler", cl::init(false), 51 cl::desc("Use a diagnostic handler to test the handler interface")); 52 53static cl::list<std::string> 54InputFilenames(cl::Positional, cl::OneOrMore, 55 cl::desc("<input bitcode files>")); 56 57static cl::opt<std::string> 58OutputFilename("o", cl::init(""), 59 cl::desc("Override output filename"), 60 cl::value_desc("filename")); 61 62static cl::list<std::string> 63ExportedSymbols("exported-symbol", 64 cl::desc("Symbol to export from the resulting object file"), 65 cl::ZeroOrMore); 66 67static cl::list<std::string> 68DSOSymbols("dso-symbol", 69 cl::desc("Symbol to put in the symtab in the resulting dso"), 70 cl::ZeroOrMore); 71 72static cl::opt<bool> ListSymbolsOnly( 73 "list-symbols-only", cl::init(false), 74 cl::desc("Instead of running LTO, list the symbols in each IR file")); 75 76static cl::opt<bool> SetMergedModule( 77 "set-merged-module", cl::init(false), 78 cl::desc("Use the first input module as the merged module")); 79 80namespace { 81struct ModuleInfo { 82 std::vector<bool> CanBeHidden; 83}; 84} 85 86static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity, 87 const char *Msg, void *) { 88 switch (Severity) { 89 case LTO_DS_NOTE: 90 errs() << "note: "; 91 break; 92 case LTO_DS_REMARK: 93 errs() << "remark: "; 94 break; 95 case LTO_DS_ERROR: 96 errs() << "error: "; 97 break; 98 case LTO_DS_WARNING: 99 errs() << "warning: "; 100 break; 101 } 102 errs() << Msg << "\n"; 103} 104 105static std::unique_ptr<LTOModule> 106getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer, 107 const TargetOptions &Options, std::string &Error) { 108 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 109 MemoryBuffer::getFile(Path); 110 if (std::error_code EC = BufferOrErr.getError()) { 111 Error = EC.message(); 112 return nullptr; 113 } 114 Buffer = std::move(BufferOrErr.get()); 115 return std::unique_ptr<LTOModule>(LTOModule::createInLocalContext( 116 Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Error, Path)); 117} 118 119/// \brief List symbols in each IR file. 120/// 121/// The main point here is to provide lit-testable coverage for the LTOModule 122/// functionality that's exposed by the C API to list symbols. Moreover, this 123/// provides testing coverage for modules that have been created in their own 124/// contexts. 125static int listSymbols(StringRef Command, const TargetOptions &Options) { 126 for (auto &Filename : InputFilenames) { 127 std::string Error; 128 std::unique_ptr<MemoryBuffer> Buffer; 129 std::unique_ptr<LTOModule> Module = 130 getLocalLTOModule(Filename, Buffer, Options, Error); 131 if (!Module) { 132 errs() << Command << ": error loading file '" << Filename 133 << "': " << Error << "\n"; 134 return 1; 135 } 136 137 // List the symbols. 138 outs() << Filename << ":\n"; 139 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I) 140 outs() << Module->getSymbolName(I) << "\n"; 141 } 142 return 0; 143} 144 145int main(int argc, char **argv) { 146 // Print a stack trace if we signal out. 147 sys::PrintStackTraceOnErrorSignal(); 148 PrettyStackTraceProgram X(argc, argv); 149 150 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 151 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); 152 153 if (OptLevel < '0' || OptLevel > '3') { 154 errs() << argv[0] << ": optimization level must be between 0 and 3\n"; 155 return 1; 156 } 157 158 // Initialize the configured targets. 159 InitializeAllTargets(); 160 InitializeAllTargetMCs(); 161 InitializeAllAsmPrinters(); 162 InitializeAllAsmParsers(); 163 164 // set up the TargetOptions for the machine 165 TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 166 167 if (ListSymbolsOnly) 168 return listSymbols(argv[0], Options); 169 170 unsigned BaseArg = 0; 171 172 LTOCodeGenerator CodeGen; 173 174 if (UseDiagnosticHandler) 175 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr); 176 177 switch (RelocModel) { 178 case Reloc::Static: 179 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC); 180 break; 181 case Reloc::PIC_: 182 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC); 183 break; 184 case Reloc::DynamicNoPIC: 185 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC); 186 break; 187 default: 188 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT); 189 } 190 191 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); 192 CodeGen.setTargetOptions(Options); 193 194 llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; 195 for (unsigned i = 0; i < DSOSymbols.size(); ++i) 196 DSOSymbolsSet.insert(DSOSymbols[i]); 197 198 std::vector<std::string> KeptDSOSyms; 199 200 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) { 201 std::string error; 202 std::unique_ptr<LTOModule> Module( 203 LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error)); 204 if (!error.empty()) { 205 errs() << argv[0] << ": error loading file '" << InputFilenames[i] 206 << "': " << error << "\n"; 207 return 1; 208 } 209 210 LTOModule *LTOMod = Module.get(); 211 212 // We use the first input module as the destination module when 213 // SetMergedModule is true. 214 if (SetMergedModule && i == BaseArg) { 215 // Transfer ownership to the code generator. 216 CodeGen.setModule(Module.release()); 217 } else if (!CodeGen.addModule(Module.get())) 218 return 1; 219 220 unsigned NumSyms = LTOMod->getSymbolCount(); 221 for (unsigned I = 0; I < NumSyms; ++I) { 222 StringRef Name = LTOMod->getSymbolName(I); 223 if (!DSOSymbolsSet.count(Name)) 224 continue; 225 lto_symbol_attributes Attrs = LTOMod->getSymbolAttributes(I); 226 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; 227 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN) 228 KeptDSOSyms.push_back(Name); 229 } 230 } 231 232 // Add all the exported symbols to the table of symbols to preserve. 233 for (unsigned i = 0; i < ExportedSymbols.size(); ++i) 234 CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str()); 235 236 // Add all the dso symbols to the table of symbols to expose. 237 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) 238 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); 239 240 // Set cpu and attrs strings for the default target/subtarget. 241 CodeGen.setCpu(MCPU.c_str()); 242 243 CodeGen.setOptLevel(OptLevel - '0'); 244 245 std::string attrs; 246 for (unsigned i = 0; i < MAttrs.size(); ++i) { 247 if (i > 0) 248 attrs.append(","); 249 attrs.append(MAttrs[i]); 250 } 251 252 if (!attrs.empty()) 253 CodeGen.setAttr(attrs.c_str()); 254 255 if (!OutputFilename.empty()) { 256 size_t len = 0; 257 std::string ErrorInfo; 258 const void *Code = 259 CodeGen.compile(&len, DisableInline, DisableGVNLoadPRE, 260 DisableLTOVectorization, ErrorInfo); 261 if (!Code) { 262 errs() << argv[0] 263 << ": error compiling the code: " << ErrorInfo << "\n"; 264 return 1; 265 } 266 267 std::error_code EC; 268 raw_fd_ostream FileStream(OutputFilename, EC, sys::fs::F_None); 269 if (EC) { 270 errs() << argv[0] << ": error opening the file '" << OutputFilename 271 << "': " << EC.message() << "\n"; 272 return 1; 273 } 274 275 FileStream.write(reinterpret_cast<const char *>(Code), len); 276 } else { 277 std::string ErrorInfo; 278 const char *OutputName = nullptr; 279 if (!CodeGen.compile_to_file(&OutputName, DisableInline, 280 DisableGVNLoadPRE, DisableLTOVectorization, 281 ErrorInfo)) { 282 errs() << argv[0] 283 << ": error compiling the code: " << ErrorInfo 284 << "\n"; 285 return 1; 286 } 287 288 outs() << "Wrote native object file '" << OutputName << "'\n"; 289 } 290 291 return 0; 292} 293