1 //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// 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 is a gold plugin for LLVM. It provides an LLVM implementation of the 11 // interface described in http://gcc.gnu.org/wiki/whopr/driver . 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H 16 #include "llvm-c/lto.h" 17 #include "llvm/ADT/StringSet.h" 18 #include "llvm/CodeGen/CommandFlags.h" 19 #include "llvm/LTO/LTOCodeGenerator.h" 20 #include "llvm/LTO/LTOModule.h" 21 #include "llvm/Support/Errno.h" 22 #include "llvm/Support/FileSystem.h" 23 #include "llvm/Support/MemoryBuffer.h" 24 #include "llvm/Support/Path.h" 25 #include "llvm/Support/Program.h" 26 #include "llvm/Support/TargetSelect.h" 27 #include "llvm/Support/ToolOutputFile.h" 28 #include <cerrno> 29 #include <cstdlib> 30 #include <cstring> 31 #include <list> 32 #include <plugin-api.h> 33 #include <system_error> 34 #include <vector> 35 36 // Support Windows/MinGW crazyness. 37 #ifdef _WIN32 38 # include <io.h> 39 # define lseek _lseek 40 # define read _read 41 #endif 42 43 #ifndef LDPO_PIE 44 // FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and 45 // Precise and Debian Wheezy (binutils 2.23 is required) 46 # define LDPO_PIE 3 47 #endif 48 49 using namespace llvm; 50 51 namespace { 52 struct claimed_file { 53 void *handle; 54 std::vector<ld_plugin_symbol> syms; 55 }; 56 } 57 58 static ld_plugin_status discard_message(int level, const char *format, ...) { 59 // Die loudly. Recent versions of Gold pass ld_plugin_message as the first 60 // callback in the transfer vector. This should never be called. 61 abort(); 62 } 63 64 static ld_plugin_add_symbols add_symbols = NULL; 65 static ld_plugin_get_symbols get_symbols = NULL; 66 static ld_plugin_add_input_file add_input_file = NULL; 67 static ld_plugin_set_extra_library_path set_extra_library_path = NULL; 68 static ld_plugin_get_view get_view = NULL; 69 static ld_plugin_message message = discard_message; 70 static lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 71 static std::string output_name = ""; 72 static std::list<claimed_file> Modules; 73 static std::vector<std::string> Cleanup; 74 static LTOCodeGenerator *CodeGen = nullptr; 75 static StringSet<> CannotBeHidden; 76 static llvm::TargetOptions TargetOpts; 77 78 namespace options { 79 enum generate_bc { BC_NO, BC_ALSO, BC_ONLY }; 80 static bool generate_api_file = false; 81 static generate_bc generate_bc_file = BC_NO; 82 static std::string bc_path; 83 static std::string obj_path; 84 static std::string extra_library_path; 85 static std::string triple; 86 static std::string mcpu; 87 // Additional options to pass into the code generator. 88 // Note: This array will contain all plugin options which are not claimed 89 // as plugin exclusive to pass to the code generator. 90 // For example, "generate-api-file" and "as"options are for the plugin 91 // use only and will not be passed. 92 static std::vector<std::string> extra; 93 94 static void process_plugin_option(const char* opt_) 95 { 96 if (opt_ == NULL) 97 return; 98 llvm::StringRef opt = opt_; 99 100 if (opt == "generate-api-file") { 101 generate_api_file = true; 102 } else if (opt.startswith("mcpu=")) { 103 mcpu = opt.substr(strlen("mcpu=")); 104 } else if (opt.startswith("extra-library-path=")) { 105 extra_library_path = opt.substr(strlen("extra_library_path=")); 106 } else if (opt.startswith("mtriple=")) { 107 triple = opt.substr(strlen("mtriple=")); 108 } else if (opt.startswith("obj-path=")) { 109 obj_path = opt.substr(strlen("obj-path=")); 110 } else if (opt == "emit-llvm") { 111 generate_bc_file = BC_ONLY; 112 } else if (opt == "also-emit-llvm") { 113 generate_bc_file = BC_ALSO; 114 } else if (opt.startswith("also-emit-llvm=")) { 115 llvm::StringRef path = opt.substr(strlen("also-emit-llvm=")); 116 generate_bc_file = BC_ALSO; 117 if (!bc_path.empty()) { 118 (*message)(LDPL_WARNING, "Path to the output IL file specified twice. " 119 "Discarding %s", opt_); 120 } else { 121 bc_path = path; 122 } 123 } else { 124 // Save this option to pass to the code generator. 125 extra.push_back(opt); 126 } 127 } 128 } 129 130 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 131 int *claimed); 132 static ld_plugin_status all_symbols_read_hook(void); 133 static ld_plugin_status cleanup_hook(void); 134 135 extern "C" ld_plugin_status onload(ld_plugin_tv *tv); 136 ld_plugin_status onload(ld_plugin_tv *tv) { 137 InitializeAllTargetInfos(); 138 InitializeAllTargets(); 139 InitializeAllTargetMCs(); 140 InitializeAllAsmParsers(); 141 InitializeAllAsmPrinters(); 142 143 // We're given a pointer to the first transfer vector. We read through them 144 // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values 145 // contain pointers to functions that we need to call to register our own 146 // hooks. The others are addresses of functions we can use to call into gold 147 // for services. 148 149 bool registeredClaimFile = false; 150 bool RegisteredAllSymbolsRead = false; 151 152 for (; tv->tv_tag != LDPT_NULL; ++tv) { 153 switch (tv->tv_tag) { 154 case LDPT_OUTPUT_NAME: 155 output_name = tv->tv_u.tv_string; 156 break; 157 case LDPT_LINKER_OUTPUT: 158 switch (tv->tv_u.tv_val) { 159 case LDPO_REL: // .o 160 case LDPO_DYN: // .so 161 case LDPO_PIE: // position independent executable 162 output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC; 163 break; 164 case LDPO_EXEC: // .exe 165 output_type = LTO_CODEGEN_PIC_MODEL_STATIC; 166 break; 167 default: 168 (*message)(LDPL_ERROR, "Unknown output file type %d", 169 tv->tv_u.tv_val); 170 return LDPS_ERR; 171 } 172 break; 173 case LDPT_OPTION: 174 options::process_plugin_option(tv->tv_u.tv_string); 175 break; 176 case LDPT_REGISTER_CLAIM_FILE_HOOK: { 177 ld_plugin_register_claim_file callback; 178 callback = tv->tv_u.tv_register_claim_file; 179 180 if ((*callback)(claim_file_hook) != LDPS_OK) 181 return LDPS_ERR; 182 183 registeredClaimFile = true; 184 } break; 185 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: { 186 ld_plugin_register_all_symbols_read callback; 187 callback = tv->tv_u.tv_register_all_symbols_read; 188 189 if ((*callback)(all_symbols_read_hook) != LDPS_OK) 190 return LDPS_ERR; 191 192 RegisteredAllSymbolsRead = true; 193 } break; 194 case LDPT_REGISTER_CLEANUP_HOOK: { 195 ld_plugin_register_cleanup callback; 196 callback = tv->tv_u.tv_register_cleanup; 197 198 if ((*callback)(cleanup_hook) != LDPS_OK) 199 return LDPS_ERR; 200 } break; 201 case LDPT_ADD_SYMBOLS: 202 add_symbols = tv->tv_u.tv_add_symbols; 203 break; 204 case LDPT_GET_SYMBOLS_V2: 205 get_symbols = tv->tv_u.tv_get_symbols; 206 break; 207 case LDPT_ADD_INPUT_FILE: 208 add_input_file = tv->tv_u.tv_add_input_file; 209 break; 210 case LDPT_SET_EXTRA_LIBRARY_PATH: 211 set_extra_library_path = tv->tv_u.tv_set_extra_library_path; 212 break; 213 case LDPT_GET_VIEW: 214 get_view = tv->tv_u.tv_get_view; 215 break; 216 case LDPT_MESSAGE: 217 message = tv->tv_u.tv_message; 218 break; 219 default: 220 break; 221 } 222 } 223 224 if (!registeredClaimFile) { 225 (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); 226 return LDPS_ERR; 227 } 228 if (!add_symbols) { 229 (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold."); 230 return LDPS_ERR; 231 } 232 233 if (!RegisteredAllSymbolsRead) 234 return LDPS_OK; 235 236 CodeGen = new LTOCodeGenerator(); 237 238 // Pass through extra options to the code generator. 239 if (!options::extra.empty()) { 240 for (std::vector<std::string>::iterator it = options::extra.begin(); 241 it != options::extra.end(); ++it) { 242 CodeGen->setCodeGenDebugOptions((*it).c_str()); 243 } 244 } 245 246 CodeGen->parseCodeGenDebugOptions(); 247 if (MAttrs.size()) { 248 std::string Attrs; 249 for (unsigned I = 0; I < MAttrs.size(); ++I) { 250 if (I > 0) 251 Attrs.append(","); 252 Attrs.append(MAttrs[I]); 253 } 254 CodeGen->setAttr(Attrs.c_str()); 255 } 256 257 TargetOpts = InitTargetOptionsFromCodeGenFlags(); 258 CodeGen->setTargetOptions(TargetOpts); 259 260 return LDPS_OK; 261 } 262 263 /// Called by gold to see whether this file is one that our plugin can handle. 264 /// We'll try to open it and register all the symbols with add_symbol if 265 /// possible. 266 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, 267 int *claimed) { 268 const void *view; 269 std::unique_ptr<MemoryBuffer> buffer; 270 if (get_view) { 271 if (get_view(file->handle, &view) != LDPS_OK) { 272 (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name); 273 return LDPS_ERR; 274 } 275 } else { 276 int64_t offset = 0; 277 // Gold has found what might be IR part-way inside of a file, such as 278 // an .a archive. 279 if (file->offset) { 280 offset = file->offset; 281 } 282 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 283 MemoryBuffer::getOpenFileSlice(file->fd, file->name, file->filesize, 284 offset); 285 if (std::error_code EC = BufferOrErr.getError()) { 286 (*message)(LDPL_ERROR, EC.message().c_str()); 287 return LDPS_ERR; 288 } 289 buffer = std::move(BufferOrErr.get()); 290 view = buffer->getBufferStart(); 291 } 292 293 if (!LTOModule::isBitcodeFile(view, file->filesize)) 294 return LDPS_OK; 295 296 std::string Error; 297 LTOModule *M = 298 LTOModule::createFromBuffer(view, file->filesize, TargetOpts, Error); 299 if (!M) { 300 (*message)(LDPL_ERROR, 301 "LLVM gold plugin has failed to create LTO module: %s", 302 Error.c_str()); 303 return LDPS_OK; 304 } 305 306 *claimed = 1; 307 Modules.resize(Modules.size() + 1); 308 claimed_file &cf = Modules.back(); 309 310 if (!options::triple.empty()) 311 M->setTargetTriple(options::triple.c_str()); 312 313 cf.handle = file->handle; 314 unsigned sym_count = M->getSymbolCount(); 315 cf.syms.reserve(sym_count); 316 317 for (unsigned i = 0; i != sym_count; ++i) { 318 lto_symbol_attributes attrs = M->getSymbolAttributes(i); 319 if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL) 320 continue; 321 322 cf.syms.push_back(ld_plugin_symbol()); 323 ld_plugin_symbol &sym = cf.syms.back(); 324 sym.name = strdup(M->getSymbolName(i)); 325 sym.version = NULL; 326 327 int scope = attrs & LTO_SYMBOL_SCOPE_MASK; 328 bool CanBeHidden = scope == LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; 329 if (!CanBeHidden) 330 CannotBeHidden.insert(sym.name); 331 switch (scope) { 332 case LTO_SYMBOL_SCOPE_HIDDEN: 333 sym.visibility = LDPV_HIDDEN; 334 break; 335 case LTO_SYMBOL_SCOPE_PROTECTED: 336 sym.visibility = LDPV_PROTECTED; 337 break; 338 case 0: // extern 339 case LTO_SYMBOL_SCOPE_DEFAULT: 340 case LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN: 341 sym.visibility = LDPV_DEFAULT; 342 break; 343 default: 344 (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope); 345 return LDPS_ERR; 346 } 347 348 int definition = attrs & LTO_SYMBOL_DEFINITION_MASK; 349 sym.comdat_key = NULL; 350 switch (definition) { 351 case LTO_SYMBOL_DEFINITION_REGULAR: 352 sym.def = LDPK_DEF; 353 break; 354 case LTO_SYMBOL_DEFINITION_UNDEFINED: 355 sym.def = LDPK_UNDEF; 356 break; 357 case LTO_SYMBOL_DEFINITION_TENTATIVE: 358 sym.def = LDPK_COMMON; 359 break; 360 case LTO_SYMBOL_DEFINITION_WEAK: 361 sym.comdat_key = sym.name; 362 sym.def = LDPK_WEAKDEF; 363 break; 364 case LTO_SYMBOL_DEFINITION_WEAKUNDEF: 365 sym.def = LDPK_WEAKUNDEF; 366 break; 367 default: 368 (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition); 369 return LDPS_ERR; 370 } 371 372 sym.size = 0; 373 374 sym.resolution = LDPR_UNKNOWN; 375 } 376 377 cf.syms.reserve(cf.syms.size()); 378 379 if (!cf.syms.empty()) { 380 if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { 381 (*message)(LDPL_ERROR, "Unable to add symbols!"); 382 return LDPS_ERR; 383 } 384 } 385 386 if (CodeGen) { 387 std::string Error; 388 if (!CodeGen->addModule(M, Error)) { 389 (*message)(LDPL_ERROR, "Error linking module: %s", Error.c_str()); 390 return LDPS_ERR; 391 } 392 } 393 394 delete M; 395 396 return LDPS_OK; 397 } 398 399 static bool mustPreserve(const claimed_file &F, int i) { 400 if (F.syms[i].resolution == LDPR_PREVAILING_DEF) 401 return true; 402 if (F.syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) 403 return CannotBeHidden.count(F.syms[i].name); 404 return false; 405 } 406 407 /// all_symbols_read_hook - gold informs us that all symbols have been read. 408 /// At this point, we use get_symbols to see if any of our definitions have 409 /// been overridden by a native object file. Then, perform optimization and 410 /// codegen. 411 static ld_plugin_status all_symbols_read_hook(void) { 412 // FIXME: raw_fd_ostream should be able to represent an unopened file. 413 std::unique_ptr<raw_fd_ostream> api_file; 414 415 assert(CodeGen); 416 417 if (options::generate_api_file) { 418 std::string Error; 419 api_file.reset(new raw_fd_ostream("apifile.txt", Error, sys::fs::F_None)); 420 if (!Error.empty()) 421 (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing: %s", 422 Error.c_str()); 423 } 424 425 for (std::list<claimed_file>::iterator I = Modules.begin(), 426 E = Modules.end(); I != E; ++I) { 427 if (I->syms.empty()) 428 continue; 429 (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); 430 for (unsigned i = 0, e = I->syms.size(); i != e; i++) { 431 if (mustPreserve(*I, i)) { 432 CodeGen->addMustPreserveSymbol(I->syms[i].name); 433 434 if (options::generate_api_file) 435 (*api_file) << I->syms[i].name << "\n"; 436 } 437 } 438 } 439 440 CodeGen->setCodePICModel(output_type); 441 CodeGen->setDebugInfo(LTO_DEBUG_MODEL_DWARF); 442 if (!options::mcpu.empty()) 443 CodeGen->setCpu(options::mcpu.c_str()); 444 445 if (options::generate_bc_file != options::BC_NO) { 446 std::string path; 447 if (options::generate_bc_file == options::BC_ONLY) 448 path = output_name; 449 else if (!options::bc_path.empty()) 450 path = options::bc_path; 451 else 452 path = output_name + ".bc"; 453 std::string Error; 454 if (!CodeGen->writeMergedModules(path.c_str(), Error)) 455 (*message)(LDPL_FATAL, "Failed to write the output file."); 456 if (options::generate_bc_file == options::BC_ONLY) { 457 delete CodeGen; 458 exit(0); 459 } 460 } 461 462 std::string ObjPath; 463 { 464 const char *Temp; 465 std::string Error; 466 if (!CodeGen->compile_to_file(&Temp, /*DisableOpt*/ false, /*DisableInline*/ 467 false, /*DisableGVNLoadPRE*/ false, Error)) 468 (*message)(LDPL_ERROR, "Could not produce a combined object file\n"); 469 ObjPath = Temp; 470 } 471 472 delete CodeGen; 473 for (std::list<claimed_file>::iterator I = Modules.begin(), 474 E = Modules.end(); I != E; ++I) { 475 for (unsigned i = 0; i != I->syms.size(); ++i) { 476 ld_plugin_symbol &sym = I->syms[i]; 477 free(sym.name); 478 } 479 } 480 481 if ((*add_input_file)(ObjPath.c_str()) != LDPS_OK) { 482 (*message)(LDPL_ERROR, "Unable to add .o file to the link."); 483 (*message)(LDPL_ERROR, "File left behind in: %s", ObjPath.c_str()); 484 return LDPS_ERR; 485 } 486 487 if (!options::extra_library_path.empty() && 488 set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) { 489 (*message)(LDPL_ERROR, "Unable to set the extra library path."); 490 return LDPS_ERR; 491 } 492 493 if (options::obj_path.empty()) 494 Cleanup.push_back(ObjPath); 495 496 return LDPS_OK; 497 } 498 499 static ld_plugin_status cleanup_hook(void) { 500 for (int i = 0, e = Cleanup.size(); i != e; ++i) { 501 std::error_code EC = sys::fs::remove(Cleanup[i]); 502 if (EC) 503 (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(), 504 EC.message().c_str()); 505 } 506 507 return LDPS_OK; 508 } 509