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 27 using namespace llvm; 28 29 static cl::opt<bool> 30 DisableOpt("disable-opt", cl::init(false), 31 cl::desc("Do not run any optimization passes")); 32 33 static cl::opt<bool> 34 DisableInline("disable-inlining", cl::init(false), 35 cl::desc("Do not run the inliner pass")); 36 37 static cl::opt<bool> 38 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), 39 cl::desc("Do not run the GVN load PRE pass")); 40 41 static cl::list<std::string> 42 InputFilenames(cl::Positional, cl::OneOrMore, 43 cl::desc("<input bitcode files>")); 44 45 static cl::opt<std::string> 46 OutputFilename("o", cl::init(""), 47 cl::desc("Override output filename"), 48 cl::value_desc("filename")); 49 50 static cl::list<std::string> 51 ExportedSymbols("exported-symbol", 52 cl::desc("Symbol to export from the resulting object file"), 53 cl::ZeroOrMore); 54 55 static cl::list<std::string> 56 DSOSymbols("dso-symbol", 57 cl::desc("Symbol to put in the symtab in the resulting dso"), 58 cl::ZeroOrMore); 59 60 namespace { 61 struct ModuleInfo { 62 std::vector<bool> CanBeHidden; 63 }; 64 } 65 66 int main(int argc, char **argv) { 67 // Print a stack trace if we signal out. 68 sys::PrintStackTraceOnErrorSignal(); 69 PrettyStackTraceProgram X(argc, argv); 70 71 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 72 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); 73 74 // Initialize the configured targets. 75 InitializeAllTargets(); 76 InitializeAllTargetMCs(); 77 InitializeAllAsmPrinters(); 78 InitializeAllAsmParsers(); 79 80 // set up the TargetOptions for the machine 81 TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 82 83 unsigned BaseArg = 0; 84 85 LTOCodeGenerator CodeGen; 86 87 switch (RelocModel) { 88 case Reloc::Static: 89 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_STATIC); 90 break; 91 case Reloc::PIC_: 92 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC); 93 break; 94 case Reloc::DynamicNoPIC: 95 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC); 96 break; 97 default: 98 CodeGen.setCodePICModel(LTO_CODEGEN_PIC_MODEL_DEFAULT); 99 } 100 101 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); 102 CodeGen.setTargetOptions(Options); 103 104 llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; 105 for (unsigned i = 0; i < DSOSymbols.size(); ++i) 106 DSOSymbolsSet.insert(DSOSymbols[i]); 107 108 std::vector<std::string> KeptDSOSyms; 109 110 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) { 111 std::string error; 112 std::unique_ptr<LTOModule> Module( 113 LTOModule::createFromFile(InputFilenames[i].c_str(), Options, error)); 114 if (!error.empty()) { 115 errs() << argv[0] << ": error loading file '" << InputFilenames[i] 116 << "': " << error << "\n"; 117 return 1; 118 } 119 120 121 if (!CodeGen.addModule(Module.get(), error)) { 122 errs() << argv[0] << ": error adding file '" << InputFilenames[i] 123 << "': " << error << "\n"; 124 return 1; 125 } 126 127 unsigned NumSyms = Module->getSymbolCount(); 128 for (unsigned I = 0; I < NumSyms; ++I) { 129 StringRef Name = Module->getSymbolName(I); 130 if (!DSOSymbolsSet.count(Name)) 131 continue; 132 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I); 133 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; 134 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN) 135 KeptDSOSyms.push_back(Name); 136 } 137 } 138 139 // Add all the exported symbols to the table of symbols to preserve. 140 for (unsigned i = 0; i < ExportedSymbols.size(); ++i) 141 CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str()); 142 143 // Add all the dso symbols to the table of symbols to expose. 144 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) 145 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); 146 147 std::string attrs; 148 for (unsigned i = 0; i < MAttrs.size(); ++i) { 149 if (i > 0) 150 attrs.append(","); 151 attrs.append(MAttrs[i]); 152 } 153 154 if (!attrs.empty()) 155 CodeGen.setAttr(attrs.c_str()); 156 157 if (!OutputFilename.empty()) { 158 size_t len = 0; 159 std::string ErrorInfo; 160 const void *Code = CodeGen.compile(&len, DisableOpt, DisableInline, 161 DisableGVNLoadPRE, ErrorInfo); 162 if (!Code) { 163 errs() << argv[0] 164 << ": error compiling the code: " << ErrorInfo << "\n"; 165 return 1; 166 } 167 168 raw_fd_ostream FileStream(OutputFilename.c_str(), ErrorInfo, 169 sys::fs::F_None); 170 if (!ErrorInfo.empty()) { 171 errs() << argv[0] << ": error opening the file '" << OutputFilename 172 << "': " << ErrorInfo << "\n"; 173 return 1; 174 } 175 176 FileStream.write(reinterpret_cast<const char *>(Code), len); 177 } else { 178 std::string ErrorInfo; 179 const char *OutputName = nullptr; 180 if (!CodeGen.compile_to_file(&OutputName, DisableOpt, DisableInline, 181 DisableGVNLoadPRE, ErrorInfo)) { 182 errs() << argv[0] 183 << ": error compiling the code: " << ErrorInfo 184 << "\n"; 185 return 1; 186 } 187 188 outs() << "Wrote native object file '" << OutputName << "'\n"; 189 } 190 191 return 0; 192 } 193