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