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"
     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             output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC;
    157             break;
    158           case LDPO_EXEC:  // .exe
    159             output_type = LTO_CODEGEN_PIC_MODEL_STATIC;
    160             break;
    161           default:
    162             (*message)(LDPL_ERROR, "Unknown output file type %d",
    163                        tv->tv_u.tv_val);
    164             return LDPS_ERR;
    165         }
    166         // TODO: add an option to disable PIC.
    167         //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
    168         break;
    169       case LDPT_OPTION:
    170         options::process_plugin_option(tv->tv_u.tv_string);
    171         break;
    172       case LDPT_REGISTER_CLAIM_FILE_HOOK: {
    173         ld_plugin_register_claim_file callback;
    174         callback = tv->tv_u.tv_register_claim_file;
    175 
    176         if ((*callback)(claim_file_hook) != LDPS_OK)
    177           return LDPS_ERR;
    178 
    179         registeredClaimFile = true;
    180       } break;
    181       case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
    182         ld_plugin_register_all_symbols_read callback;
    183         callback = tv->tv_u.tv_register_all_symbols_read;
    184 
    185         if ((*callback)(all_symbols_read_hook) != LDPS_OK)
    186           return LDPS_ERR;
    187 
    188         code_gen = lto_codegen_create();
    189       } break;
    190       case LDPT_REGISTER_CLEANUP_HOOK: {
    191         ld_plugin_register_cleanup callback;
    192         callback = tv->tv_u.tv_register_cleanup;
    193 
    194         if ((*callback)(cleanup_hook) != LDPS_OK)
    195           return LDPS_ERR;
    196       } break;
    197       case LDPT_ADD_SYMBOLS:
    198         add_symbols = tv->tv_u.tv_add_symbols;
    199         break;
    200       case LDPT_GET_SYMBOLS:
    201         get_symbols = tv->tv_u.tv_get_symbols;
    202         break;
    203       case LDPT_ADD_INPUT_FILE:
    204         add_input_file = tv->tv_u.tv_add_input_file;
    205         break;
    206       case LDPT_ADD_INPUT_LIBRARY:
    207         add_input_library = tv->tv_u.tv_add_input_file;
    208         break;
    209       case LDPT_SET_EXTRA_LIBRARY_PATH:
    210         set_extra_library_path = tv->tv_u.tv_set_extra_library_path;
    211         break;
    212       case LDPT_GET_VIEW:
    213         get_view = tv->tv_u.tv_get_view;
    214         break;
    215       case LDPT_MESSAGE:
    216         message = tv->tv_u.tv_message;
    217         break;
    218       default:
    219         break;
    220     }
    221   }
    222 
    223   if (!registeredClaimFile) {
    224     (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold.");
    225     return LDPS_ERR;
    226   }
    227   if (!add_symbols) {
    228     (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold.");
    229     return LDPS_ERR;
    230   }
    231 
    232   return LDPS_OK;
    233 }
    234 
    235 /// claim_file_hook - called by gold to see whether this file is one that
    236 /// our plugin can handle. We'll try to open it and register all the symbols
    237 /// with add_symbol if possible.
    238 static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
    239                                         int *claimed) {
    240   lto_module_t M;
    241   const void *view;
    242   OwningPtr<MemoryBuffer> buffer;
    243   if (get_view) {
    244     if (get_view(file->handle, &view) != LDPS_OK) {
    245       (*message)(LDPL_ERROR, "Failed to get a view of %s", file->name);
    246       return LDPS_ERR;
    247     }
    248   } else {
    249     int64_t offset = 0;
    250     // Gold has found what might be IR part-way inside of a file, such as
    251     // an .a archive.
    252     if (file->offset) {
    253       offset = file->offset;
    254     }
    255     if (error_code ec =
    256         MemoryBuffer::getOpenFile(file->fd, file->name, buffer, file->filesize,
    257                                   -1, offset, false)) {
    258       (*message)(LDPL_ERROR, ec.message().c_str());
    259       return LDPS_ERR;
    260     }
    261     view = buffer->getBufferStart();
    262   }
    263 
    264   if (!lto_module_is_object_file_in_memory(view, file->filesize))
    265     return LDPS_OK;
    266 
    267   M = lto_module_create_from_memory(view, file->filesize);
    268   if (!M) {
    269     if (const char* msg = lto_get_error_message()) {
    270       (*message)(LDPL_ERROR,
    271                  "LLVM gold plugin has failed to create LTO module: %s",
    272                  msg);
    273       return LDPS_ERR;
    274     }
    275     return LDPS_OK;
    276   }
    277 
    278   *claimed = 1;
    279   Modules.resize(Modules.size() + 1);
    280   claimed_file &cf = Modules.back();
    281 
    282   if (!options::triple.empty())
    283     lto_module_set_target_triple(M, options::triple.c_str());
    284 
    285   cf.handle = file->handle;
    286   unsigned sym_count = lto_module_get_num_symbols(M);
    287   cf.syms.reserve(sym_count);
    288 
    289   for (unsigned i = 0; i != sym_count; ++i) {
    290     lto_symbol_attributes attrs = lto_module_get_symbol_attribute(M, i);
    291     if ((attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
    292       continue;
    293 
    294     cf.syms.push_back(ld_plugin_symbol());
    295     ld_plugin_symbol &sym = cf.syms.back();
    296     sym.name = const_cast<char *>(lto_module_get_symbol_name(M, i));
    297     sym.name = strdup(sym.name);
    298     sym.version = NULL;
    299 
    300     int scope = attrs & LTO_SYMBOL_SCOPE_MASK;
    301     switch (scope) {
    302       case LTO_SYMBOL_SCOPE_HIDDEN:
    303         sym.visibility = LDPV_HIDDEN;
    304         break;
    305       case LTO_SYMBOL_SCOPE_PROTECTED:
    306         sym.visibility = LDPV_PROTECTED;
    307         break;
    308       case 0: // extern
    309       case LTO_SYMBOL_SCOPE_DEFAULT:
    310         sym.visibility = LDPV_DEFAULT;
    311         break;
    312       default:
    313         (*message)(LDPL_ERROR, "Unknown scope attribute: %d", scope);
    314         return LDPS_ERR;
    315     }
    316 
    317     int definition = attrs & LTO_SYMBOL_DEFINITION_MASK;
    318     sym.comdat_key = NULL;
    319     switch (definition) {
    320       case LTO_SYMBOL_DEFINITION_REGULAR:
    321         sym.def = LDPK_DEF;
    322         break;
    323       case LTO_SYMBOL_DEFINITION_UNDEFINED:
    324         sym.def = LDPK_UNDEF;
    325         break;
    326       case LTO_SYMBOL_DEFINITION_TENTATIVE:
    327         sym.def = LDPK_COMMON;
    328         break;
    329       case LTO_SYMBOL_DEFINITION_WEAK:
    330         sym.comdat_key = sym.name;
    331         sym.def = LDPK_WEAKDEF;
    332         break;
    333       case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
    334         sym.def = LDPK_WEAKUNDEF;
    335         break;
    336       default:
    337         (*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
    338         return LDPS_ERR;
    339     }
    340 
    341     sym.size = 0;
    342 
    343     sym.resolution = LDPR_UNKNOWN;
    344   }
    345 
    346   cf.syms.reserve(cf.syms.size());
    347 
    348   if (!cf.syms.empty()) {
    349     if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) {
    350       (*message)(LDPL_ERROR, "Unable to add symbols!");
    351       return LDPS_ERR;
    352     }
    353   }
    354 
    355   if (code_gen)
    356     lto_codegen_add_module(code_gen, M);
    357 
    358   lto_module_dispose(M);
    359 
    360   return LDPS_OK;
    361 }
    362 
    363 /// all_symbols_read_hook - gold informs us that all symbols have been read.
    364 /// At this point, we use get_symbols to see if any of our definitions have
    365 /// been overridden by a native object file. Then, perform optimization and
    366 /// codegen.
    367 static ld_plugin_status all_symbols_read_hook(void) {
    368   std::ofstream api_file;
    369   assert(code_gen);
    370 
    371   if (options::generate_api_file) {
    372     api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc);
    373     if (!api_file.is_open()) {
    374       (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing.");
    375       abort();
    376     }
    377   }
    378 
    379   // If we don't preserve any symbols, libLTO will assume that all symbols are
    380   // needed. Keep all symbols unless we're producing a final executable.
    381   bool anySymbolsPreserved = false;
    382   for (std::list<claimed_file>::iterator I = Modules.begin(),
    383          E = Modules.end(); I != E; ++I) {
    384     if (I->syms.empty())
    385       continue;
    386     (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
    387     for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
    388       if (I->syms[i].resolution == LDPR_PREVAILING_DEF) {
    389         lto_codegen_add_must_preserve_symbol(code_gen, I->syms[i].name);
    390         anySymbolsPreserved = true;
    391 
    392         if (options::generate_api_file)
    393           api_file << I->syms[i].name << "\n";
    394       }
    395     }
    396   }
    397 
    398   if (options::generate_api_file)
    399     api_file.close();
    400 
    401   if (!anySymbolsPreserved) {
    402     // All of the IL is unnecessary!
    403     lto_codegen_dispose(code_gen);
    404     return LDPS_OK;
    405   }
    406 
    407   lto_codegen_set_pic_model(code_gen, output_type);
    408   lto_codegen_set_debug_model(code_gen, LTO_DEBUG_MODEL_DWARF);
    409   if (!options::mcpu.empty())
    410     lto_codegen_set_cpu(code_gen, options::mcpu.c_str());
    411 
    412   // Pass through extra options to the code generator.
    413   if (!options::extra.empty()) {
    414     for (std::vector<std::string>::iterator it = options::extra.begin();
    415          it != options::extra.end(); ++it) {
    416       lto_codegen_debug_options(code_gen, (*it).c_str());
    417     }
    418   }
    419 
    420   if (options::generate_bc_file != options::BC_NO) {
    421     std::string path;
    422     if (options::generate_bc_file == options::BC_ONLY)
    423       path = output_name;
    424     else if (!options::bc_path.empty())
    425       path = options::bc_path;
    426     else
    427       path = output_name + ".bc";
    428     bool err = lto_codegen_write_merged_modules(code_gen, path.c_str());
    429     if (err)
    430       (*message)(LDPL_FATAL, "Failed to write the output file.");
    431     if (options::generate_bc_file == options::BC_ONLY)
    432       exit(0);
    433   }
    434   const char *objPath;
    435   if (lto_codegen_compile_to_file(code_gen, &objPath)) {
    436     (*message)(LDPL_ERROR, "Could not produce a combined object file\n");
    437   }
    438 
    439   lto_codegen_dispose(code_gen);
    440   for (std::list<claimed_file>::iterator I = Modules.begin(),
    441          E = Modules.end(); I != E; ++I) {
    442     for (unsigned i = 0; i != I->syms.size(); ++i) {
    443       ld_plugin_symbol &sym = I->syms[i];
    444       free(sym.name);
    445     }
    446   }
    447 
    448   if ((*add_input_file)(objPath) != LDPS_OK) {
    449     (*message)(LDPL_ERROR, "Unable to add .o file to the link.");
    450     (*message)(LDPL_ERROR, "File left behind in: %s", objPath);
    451     return LDPS_ERR;
    452   }
    453 
    454   if (!options::extra_library_path.empty() &&
    455       set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) {
    456     (*message)(LDPL_ERROR, "Unable to set the extra library path.");
    457     return LDPS_ERR;
    458   }
    459 
    460   if (options::obj_path.empty())
    461     Cleanup.push_back(sys::Path(objPath));
    462 
    463   return LDPS_OK;
    464 }
    465 
    466 static ld_plugin_status cleanup_hook(void) {
    467   std::string ErrMsg;
    468 
    469   for (int i = 0, e = Cleanup.size(); i != e; ++i)
    470     if (Cleanup[i].eraseFromDisk(false, &ErrMsg))
    471       (*message)(LDPL_ERROR, "Failed to delete '%s': %s", Cleanup[i].c_str(),
    472                  ErrMsg.c_str());
    473 
    474   return LDPS_OK;
    475 }
    476