lto.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. //===-lto.cpp - LLVM Link Time Optimizer ----------------------------------===//
  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 file implements the Link Time Optimization library. This library is
  11. // intended to be used by linker to optimize code at link time.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm-c/lto.h"
  15. #include "llvm/ADT/STLExtras.h"
  16. #include "llvm/CodeGen/CommandFlags.h"
  17. #include "llvm/IR/LLVMContext.h"
  18. #include "llvm/LTO/LTOCodeGenerator.h"
  19. #include "llvm/LTO/LTOModule.h"
  20. #include "llvm/Support/MemoryBuffer.h"
  21. #include "llvm/Support/Signals.h"
  22. #include "llvm/Support/TargetSelect.h"
  23. // extra command-line flags needed for LTOCodeGenerator
  24. static cl::opt<char>
  25. OptLevel("O",
  26. cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
  27. "(default = '-O2')"),
  28. cl::Prefix,
  29. cl::ZeroOrMore,
  30. cl::init('2'));
  31. static cl::opt<bool>
  32. DisableInline("disable-inlining", cl::init(false),
  33. cl::desc("Do not run the inliner pass"));
  34. static cl::opt<bool>
  35. DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
  36. cl::desc("Do not run the GVN load PRE pass"));
  37. static cl::opt<bool>
  38. DisableLTOVectorization("disable-lto-vectorization", cl::init(false),
  39. cl::desc("Do not run loop or slp vectorization during LTO"));
  40. // Holds most recent error string.
  41. // *** Not thread safe ***
  42. static std::string sLastErrorString;
  43. // Holds the initialization state of the LTO module.
  44. // *** Not thread safe ***
  45. static bool initialized = false;
  46. // Holds the command-line option parsing state of the LTO module.
  47. static bool parsedOptions = false;
  48. // Initialize the configured targets if they have not been initialized.
  49. static void lto_initialize() {
  50. if (!initialized) {
  51. #ifdef LLVM_ON_WIN32
  52. // Dialog box on crash disabling doesn't work across DLL boundaries, so do
  53. // it here.
  54. llvm::sys::DisableSystemDialogsOnCrash();
  55. #endif
  56. InitializeAllTargetInfos();
  57. InitializeAllTargets();
  58. InitializeAllTargetMCs();
  59. InitializeAllAsmParsers();
  60. InitializeAllAsmPrinters();
  61. InitializeAllDisassemblers();
  62. initialized = true;
  63. }
  64. }
  65. namespace {
  66. // This derived class owns the native object file. This helps implement the
  67. // libLTO API semantics, which require that the code generator owns the object
  68. // file.
  69. struct LibLTOCodeGenerator : LTOCodeGenerator {
  70. LibLTOCodeGenerator() {}
  71. LibLTOCodeGenerator(std::unique_ptr<LLVMContext> Context)
  72. : LTOCodeGenerator(std::move(Context)) {}
  73. std::unique_ptr<MemoryBuffer> NativeObjectFile;
  74. };
  75. }
  76. DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LibLTOCodeGenerator, lto_code_gen_t)
  77. DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t)
  78. // Convert the subtarget features into a string to pass to LTOCodeGenerator.
  79. static void lto_add_attrs(lto_code_gen_t cg) {
  80. LTOCodeGenerator *CG = unwrap(cg);
  81. if (MAttrs.size()) {
  82. std::string attrs;
  83. for (unsigned i = 0; i < MAttrs.size(); ++i) {
  84. if (i > 0)
  85. attrs.append(",");
  86. attrs.append(MAttrs[i]);
  87. }
  88. CG->setAttr(attrs.c_str());
  89. }
  90. if (OptLevel < '0' || OptLevel > '3')
  91. report_fatal_error("Optimization level must be between 0 and 3");
  92. CG->setOptLevel(OptLevel - '0');
  93. }
  94. extern const char* lto_get_version() {
  95. return LTOCodeGenerator::getVersionString();
  96. }
  97. const char* lto_get_error_message() {
  98. return sLastErrorString.c_str();
  99. }
  100. bool lto_module_is_object_file(const char* path) {
  101. return LTOModule::isBitcodeFile(path);
  102. }
  103. bool lto_module_is_object_file_for_target(const char* path,
  104. const char* target_triplet_prefix) {
  105. ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path);
  106. if (!Buffer)
  107. return false;
  108. return LTOModule::isBitcodeForTarget(Buffer->get(), target_triplet_prefix);
  109. }
  110. bool lto_module_is_object_file_in_memory(const void* mem, size_t length) {
  111. return LTOModule::isBitcodeFile(mem, length);
  112. }
  113. bool
  114. lto_module_is_object_file_in_memory_for_target(const void* mem,
  115. size_t length,
  116. const char* target_triplet_prefix) {
  117. std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length));
  118. if (!buffer)
  119. return false;
  120. return LTOModule::isBitcodeForTarget(buffer.get(), target_triplet_prefix);
  121. }
  122. lto_module_t lto_module_create(const char* path) {
  123. lto_initialize();
  124. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  125. return wrap(LTOModule::createFromFile(path, Options, sLastErrorString));
  126. }
  127. lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) {
  128. lto_initialize();
  129. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  130. return wrap(
  131. LTOModule::createFromOpenFile(fd, path, size, Options, sLastErrorString));
  132. }
  133. lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path,
  134. size_t file_size,
  135. size_t map_size,
  136. off_t offset) {
  137. lto_initialize();
  138. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  139. return wrap(LTOModule::createFromOpenFileSlice(fd, path, map_size, offset,
  140. Options, sLastErrorString));
  141. }
  142. lto_module_t lto_module_create_from_memory(const void* mem, size_t length) {
  143. lto_initialize();
  144. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  145. return wrap(LTOModule::createFromBuffer(mem, length, Options, sLastErrorString));
  146. }
  147. lto_module_t lto_module_create_from_memory_with_path(const void* mem,
  148. size_t length,
  149. const char *path) {
  150. lto_initialize();
  151. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  152. return wrap(
  153. LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path));
  154. }
  155. lto_module_t lto_module_create_in_local_context(const void *mem, size_t length,
  156. const char *path) {
  157. lto_initialize();
  158. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  159. return wrap(LTOModule::createInLocalContext(mem, length, Options,
  160. sLastErrorString, path));
  161. }
  162. lto_module_t lto_module_create_in_codegen_context(const void *mem,
  163. size_t length,
  164. const char *path,
  165. lto_code_gen_t cg) {
  166. lto_initialize();
  167. llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  168. return wrap(LTOModule::createInContext(mem, length, Options, sLastErrorString,
  169. path, &unwrap(cg)->getContext()));
  170. }
  171. void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); }
  172. const char* lto_module_get_target_triple(lto_module_t mod) {
  173. return unwrap(mod)->getTargetTriple().c_str();
  174. }
  175. void lto_module_set_target_triple(lto_module_t mod, const char *triple) {
  176. return unwrap(mod)->setTargetTriple(triple);
  177. }
  178. unsigned int lto_module_get_num_symbols(lto_module_t mod) {
  179. return unwrap(mod)->getSymbolCount();
  180. }
  181. const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) {
  182. return unwrap(mod)->getSymbolName(index);
  183. }
  184. lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod,
  185. unsigned int index) {
  186. return unwrap(mod)->getSymbolAttributes(index);
  187. }
  188. const char* lto_module_get_linkeropts(lto_module_t mod) {
  189. return unwrap(mod)->getLinkerOpts();
  190. }
  191. void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,
  192. lto_diagnostic_handler_t diag_handler,
  193. void *ctxt) {
  194. unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt);
  195. }
  196. static lto_code_gen_t createCodeGen(bool InLocalContext) {
  197. lto_initialize();
  198. TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
  199. LibLTOCodeGenerator *CodeGen =
  200. InLocalContext ? new LibLTOCodeGenerator(make_unique<LLVMContext>())
  201. : new LibLTOCodeGenerator();
  202. CodeGen->setTargetOptions(Options);
  203. return wrap(CodeGen);
  204. }
  205. lto_code_gen_t lto_codegen_create(void) {
  206. return createCodeGen(/* InLocalContext */ false);
  207. }
  208. lto_code_gen_t lto_codegen_create_in_local_context(void) {
  209. return createCodeGen(/* InLocalContext */ true);
  210. }
  211. void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); }
  212. bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) {
  213. return !unwrap(cg)->addModule(unwrap(mod));
  214. }
  215. void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) {
  216. unwrap(cg)->setModule(unwrap(mod));
  217. }
  218. bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {
  219. unwrap(cg)->setDebugInfo(debug);
  220. return false;
  221. }
  222. bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) {
  223. unwrap(cg)->setCodePICModel(model);
  224. return false;
  225. }
  226. void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) {
  227. return unwrap(cg)->setCpu(cpu);
  228. }
  229. void lto_codegen_set_assembler_path(lto_code_gen_t cg, const char *path) {
  230. // In here only for backwards compatibility. We use MC now.
  231. }
  232. void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args,
  233. int nargs) {
  234. // In here only for backwards compatibility. We use MC now.
  235. }
  236. void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg,
  237. const char *symbol) {
  238. unwrap(cg)->addMustPreserveSymbol(symbol);
  239. }
  240. static void maybeParseOptions(lto_code_gen_t cg) {
  241. if (!parsedOptions) {
  242. unwrap(cg)->parseCodeGenDebugOptions();
  243. lto_add_attrs(cg);
  244. parsedOptions = true;
  245. }
  246. }
  247. bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) {
  248. maybeParseOptions(cg);
  249. return !unwrap(cg)->writeMergedModules(path, sLastErrorString);
  250. }
  251. const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) {
  252. maybeParseOptions(cg);
  253. LibLTOCodeGenerator *CG = unwrap(cg);
  254. CG->NativeObjectFile = CG->compile(DisableInline, DisableGVNLoadPRE,
  255. DisableLTOVectorization, sLastErrorString);
  256. if (!CG->NativeObjectFile)
  257. return nullptr;
  258. *length = CG->NativeObjectFile->getBufferSize();
  259. return CG->NativeObjectFile->getBufferStart();
  260. }
  261. bool lto_codegen_optimize(lto_code_gen_t cg) {
  262. maybeParseOptions(cg);
  263. return !unwrap(cg)->optimize(DisableInline,
  264. DisableGVNLoadPRE, DisableLTOVectorization,
  265. sLastErrorString);
  266. }
  267. const void *lto_codegen_compile_optimized(lto_code_gen_t cg, size_t *length) {
  268. maybeParseOptions(cg);
  269. LibLTOCodeGenerator *CG = unwrap(cg);
  270. CG->NativeObjectFile = CG->compileOptimized(sLastErrorString);
  271. if (!CG->NativeObjectFile)
  272. return nullptr;
  273. *length = CG->NativeObjectFile->getBufferSize();
  274. return CG->NativeObjectFile->getBufferStart();
  275. }
  276. bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) {
  277. maybeParseOptions(cg);
  278. return !unwrap(cg)->compile_to_file(
  279. name, DisableInline, DisableGVNLoadPRE,
  280. DisableLTOVectorization, sLastErrorString);
  281. }
  282. void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) {
  283. unwrap(cg)->setCodeGenDebugOptions(opt);
  284. }
  285. unsigned int lto_api_version() { return LTO_API_VERSION; }
  286. void lto_codegen_set_should_internalize(lto_code_gen_t cg,
  287. bool ShouldInternalize) {
  288. unwrap(cg)->setShouldInternalize(ShouldInternalize);
  289. }
  290. void lto_codegen_set_should_embed_uselists(lto_code_gen_t cg,
  291. lto_bool_t ShouldEmbedUselists) {
  292. unwrap(cg)->setShouldEmbedUselists(ShouldEmbedUselists);
  293. }