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 15 #include "llvm-c/lto.h" 16 #include "llvm/CodeGen/CommandFlags.h" 17 #include "llvm/LTO/LTOCodeGenerator.h" 18 #include "llvm/LTO/LTOModule.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/TargetSelect.h" 21 22 // extra command-line flags needed for LTOCodeGenerator 23 static cl::opt<bool> 24 DisableOpt("disable-opt", cl::init(false), 25 cl::desc("Do not run any optimization passes")); 26 27 static cl::opt<bool> 28 DisableInline("disable-inlining", cl::init(false), 29 cl::desc("Do not run the inliner pass")); 30 31 static cl::opt<bool> 32 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), 33 cl::desc("Do not run the GVN load PRE pass")); 34 35 // Holds most recent error string. 36 // *** Not thread safe *** 37 static std::string sLastErrorString; 38 39 // Holds the initialization state of the LTO module. 40 // *** Not thread safe *** 41 static bool initialized = false; 42 43 // Holds the command-line option parsing state of the LTO module. 44 static bool parsedOptions = false; 45 46 // Initialize the configured targets if they have not been initialized. 47 static void lto_initialize() { 48 if (!initialized) { 49 InitializeAllTargetInfos(); 50 InitializeAllTargets(); 51 InitializeAllTargetMCs(); 52 InitializeAllAsmParsers(); 53 InitializeAllAsmPrinters(); 54 InitializeAllDisassemblers(); 55 initialized = true; 56 } 57 } 58 59 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOCodeGenerator, lto_code_gen_t) 60 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LTOModule, lto_module_t) 61 62 // Convert the subtarget features into a string to pass to LTOCodeGenerator. 63 static void lto_add_attrs(lto_code_gen_t cg) { 64 LTOCodeGenerator *CG = unwrap(cg); 65 if (MAttrs.size()) { 66 std::string attrs; 67 for (unsigned i = 0; i < MAttrs.size(); ++i) { 68 if (i > 0) 69 attrs.append(","); 70 attrs.append(MAttrs[i]); 71 } 72 73 CG->setAttr(attrs.c_str()); 74 } 75 } 76 77 extern const char* lto_get_version() { 78 return LTOCodeGenerator::getVersionString(); 79 } 80 81 const char* lto_get_error_message() { 82 return sLastErrorString.c_str(); 83 } 84 85 bool lto_module_is_object_file(const char* path) { 86 return LTOModule::isBitcodeFile(path); 87 } 88 89 bool lto_module_is_object_file_for_target(const char* path, 90 const char* target_triplet_prefix) { 91 ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer = MemoryBuffer::getFile(path); 92 if (!Buffer) 93 return false; 94 return LTOModule::isBitcodeForTarget(Buffer->get(), target_triplet_prefix); 95 } 96 97 bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { 98 return LTOModule::isBitcodeFile(mem, length); 99 } 100 101 bool 102 lto_module_is_object_file_in_memory_for_target(const void* mem, 103 size_t length, 104 const char* target_triplet_prefix) { 105 std::unique_ptr<MemoryBuffer> buffer(LTOModule::makeBuffer(mem, length)); 106 if (!buffer) 107 return false; 108 return LTOModule::isBitcodeForTarget(buffer.get(), target_triplet_prefix); 109 } 110 111 lto_module_t lto_module_create(const char* path) { 112 lto_initialize(); 113 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 114 return wrap(LTOModule::createFromFile(path, Options, sLastErrorString)); 115 } 116 117 lto_module_t lto_module_create_from_fd(int fd, const char *path, size_t size) { 118 lto_initialize(); 119 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 120 return wrap( 121 LTOModule::createFromOpenFile(fd, path, size, Options, sLastErrorString)); 122 } 123 124 lto_module_t lto_module_create_from_fd_at_offset(int fd, const char *path, 125 size_t file_size, 126 size_t map_size, 127 off_t offset) { 128 lto_initialize(); 129 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 130 return wrap(LTOModule::createFromOpenFileSlice(fd, path, map_size, offset, 131 Options, sLastErrorString)); 132 } 133 134 lto_module_t lto_module_create_from_memory(const void* mem, size_t length) { 135 lto_initialize(); 136 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 137 return wrap(LTOModule::createFromBuffer(mem, length, Options, sLastErrorString)); 138 } 139 140 lto_module_t lto_module_create_from_memory_with_path(const void* mem, 141 size_t length, 142 const char *path) { 143 lto_initialize(); 144 llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 145 return wrap( 146 LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path)); 147 } 148 149 void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); } 150 151 const char* lto_module_get_target_triple(lto_module_t mod) { 152 return unwrap(mod)->getTargetTriple().c_str(); 153 } 154 155 void lto_module_set_target_triple(lto_module_t mod, const char *triple) { 156 return unwrap(mod)->setTargetTriple(triple); 157 } 158 159 unsigned int lto_module_get_num_symbols(lto_module_t mod) { 160 return unwrap(mod)->getSymbolCount(); 161 } 162 163 const char* lto_module_get_symbol_name(lto_module_t mod, unsigned int index) { 164 return unwrap(mod)->getSymbolName(index); 165 } 166 167 lto_symbol_attributes lto_module_get_symbol_attribute(lto_module_t mod, 168 unsigned int index) { 169 return unwrap(mod)->getSymbolAttributes(index); 170 } 171 172 unsigned int lto_module_get_num_deplibs(lto_module_t mod) { 173 return unwrap(mod)->getDependentLibraryCount(); 174 } 175 176 const char* lto_module_get_deplib(lto_module_t mod, unsigned int index) { 177 return unwrap(mod)->getDependentLibrary(index); 178 } 179 180 unsigned int lto_module_get_num_linkeropts(lto_module_t mod) { 181 return unwrap(mod)->getLinkerOptCount(); 182 } 183 184 const char* lto_module_get_linkeropt(lto_module_t mod, unsigned int index) { 185 return unwrap(mod)->getLinkerOpt(index); 186 } 187 188 void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg, 189 lto_diagnostic_handler_t diag_handler, 190 void *ctxt) { 191 unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt); 192 } 193 194 lto_code_gen_t lto_codegen_create(void) { 195 lto_initialize(); 196 197 TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); 198 199 LTOCodeGenerator *CodeGen = new LTOCodeGenerator(); 200 if (CodeGen) 201 CodeGen->setTargetOptions(Options); 202 return wrap(CodeGen); 203 } 204 205 void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); } 206 207 bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { 208 return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString); 209 } 210 211 bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { 212 unwrap(cg)->setDebugInfo(debug); 213 return false; 214 } 215 216 bool lto_codegen_set_pic_model(lto_code_gen_t cg, lto_codegen_model model) { 217 unwrap(cg)->setCodePICModel(model); 218 return false; 219 } 220 221 void lto_codegen_set_cpu(lto_code_gen_t cg, const char *cpu) { 222 return unwrap(cg)->setCpu(cpu); 223 } 224 225 void lto_codegen_set_attr(lto_code_gen_t cg, const char *attr) { 226 return unwrap(cg)->setAttr(attr); 227 } 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 233 void lto_codegen_set_assembler_args(lto_code_gen_t cg, const char **args, 234 int nargs) { 235 // In here only for backwards compatibility. We use MC now. 236 } 237 238 void lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, 239 const char *symbol) { 240 unwrap(cg)->addMustPreserveSymbol(symbol); 241 } 242 243 bool lto_codegen_write_merged_modules(lto_code_gen_t cg, const char *path) { 244 if (!parsedOptions) { 245 unwrap(cg)->parseCodeGenDebugOptions(); 246 lto_add_attrs(cg); 247 parsedOptions = true; 248 } 249 return !unwrap(cg)->writeMergedModules(path, sLastErrorString); 250 } 251 252 const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { 253 if (!parsedOptions) { 254 unwrap(cg)->parseCodeGenDebugOptions(); 255 lto_add_attrs(cg); 256 parsedOptions = true; 257 } 258 return unwrap(cg)->compile(length, DisableOpt, DisableInline, 259 DisableGVNLoadPRE, sLastErrorString); 260 } 261 262 bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { 263 if (!parsedOptions) { 264 unwrap(cg)->parseCodeGenDebugOptions(); 265 lto_add_attrs(cg); 266 parsedOptions = true; 267 } 268 return !unwrap(cg)->compile_to_file(name, DisableOpt, DisableInline, 269 DisableGVNLoadPRE, sLastErrorString); 270 } 271 272 void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { 273 unwrap(cg)->setCodeGenDebugOptions(opt); 274 } 275