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