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