1 //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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 .
13 //===----------------------------------------------------------------------===//
15 #include "plugin-api.h"
17 #include "llvm-c/lto.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/System/Path.h"
32 ld_plugin_status
discard_message(int level
, const char *format
, ...) {
33 // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
34 // callback in the transfer vector. This should never be called.
38 ld_plugin_add_symbols add_symbols
= NULL
;
39 ld_plugin_get_symbols get_symbols
= NULL
;
40 ld_plugin_add_input_file add_input_file
= NULL
;
41 ld_plugin_message message
= discard_message
;
46 bool generate_api_file
= false;
47 const char *gcc_path
= NULL
;
52 std::vector
<ld_plugin_symbol
> syms
;
55 lto_codegen_model output_type
= LTO_CODEGEN_PIC_MODEL_STATIC
;
56 std::list
<claimed_file
> Modules
;
57 std::vector
<sys::Path
> Cleanup
;
60 ld_plugin_status
claim_file_hook(const ld_plugin_input_file
*file
,
62 ld_plugin_status
all_symbols_read_hook(void);
63 ld_plugin_status
cleanup_hook(void);
65 extern "C" ld_plugin_status
onload(ld_plugin_tv
*tv
);
66 ld_plugin_status
onload(ld_plugin_tv
*tv
) {
67 // We're given a pointer to the first transfer vector. We read through them
68 // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
69 // contain pointers to functions that we need to call to register our own
70 // hooks. The others are addresses of functions we can use to call into gold
73 bool registeredClaimFile
= false;
74 bool registeredAllSymbolsRead
= false;
75 bool registeredCleanup
= false;
77 for (; tv
->tv_tag
!= LDPT_NULL
; ++tv
) {
79 case LDPT_API_VERSION
:
80 api_version
= tv
->tv_u
.tv_val
;
82 case LDPT_GOLD_VERSION
: // major * 100 + minor
83 gold_version
= tv
->tv_u
.tv_val
;
85 case LDPT_LINKER_OUTPUT
:
86 switch (tv
->tv_u
.tv_val
) {
89 output_type
= LTO_CODEGEN_PIC_MODEL_DYNAMIC
;
91 case LDPO_EXEC
: // .exe
92 output_type
= LTO_CODEGEN_PIC_MODEL_STATIC
;
95 (*message
)(LDPL_ERROR
, "Unknown output file type %d",
99 // TODO: add an option to disable PIC.
100 //output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
103 if (strcmp("generate-api-file", tv
->tv_u
.tv_string
) == 0) {
104 generate_api_file
= true;
105 } else if (strncmp("gcc=", tv
->tv_u
.tv_string
, 4) == 0) {
107 (*message
)(LDPL_WARNING
, "Path to gcc specified twice. "
108 "Discarding %s", tv
->tv_u
.tv_string
);
110 gcc_path
= strdup(tv
->tv_u
.tv_string
+ 4);
113 (*message
)(LDPL_WARNING
, "Ignoring flag %s", tv
->tv_u
.tv_string
);
116 case LDPT_REGISTER_CLAIM_FILE_HOOK
: {
117 ld_plugin_register_claim_file callback
;
118 callback
= tv
->tv_u
.tv_register_claim_file
;
120 if ((*callback
)(claim_file_hook
) != LDPS_OK
)
123 registeredClaimFile
= true;
125 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
: {
126 ld_plugin_register_all_symbols_read callback
;
127 callback
= tv
->tv_u
.tv_register_all_symbols_read
;
129 if ((*callback
)(all_symbols_read_hook
) != LDPS_OK
)
132 registeredAllSymbolsRead
= true;
134 case LDPT_REGISTER_CLEANUP_HOOK
: {
135 ld_plugin_register_cleanup callback
;
136 callback
= tv
->tv_u
.tv_register_cleanup
;
138 if ((*callback
)(cleanup_hook
) != LDPS_OK
)
141 registeredCleanup
= true;
143 case LDPT_ADD_SYMBOLS
:
144 add_symbols
= tv
->tv_u
.tv_add_symbols
;
146 case LDPT_GET_SYMBOLS
:
147 get_symbols
= tv
->tv_u
.tv_get_symbols
;
149 case LDPT_ADD_INPUT_FILE
:
150 add_input_file
= tv
->tv_u
.tv_add_input_file
;
153 message
= tv
->tv_u
.tv_message
;
160 if (!registeredClaimFile
) {
161 (*message
)(LDPL_ERROR
, "register_claim_file not passed to LLVMgold.");
165 (*message
)(LDPL_ERROR
, "add_symbols not passed to LLVMgold.");
172 /// claim_file_hook - called by gold to see whether this file is one that
173 /// our plugin can handle. We'll try to open it and register all the symbols
174 /// with add_symbol if possible.
175 ld_plugin_status
claim_file_hook(const ld_plugin_input_file
*file
,
179 // Gold has found what might be IR part-way inside of a file, such as
181 if (lseek(file
->fd
, file
->offset
, SEEK_SET
) == -1) {
182 (*message
)(LDPL_ERROR
,
183 "Failed to seek to archive member of %s at offset %d: %s\n",
185 file
->offset
, strerror(errno
));
188 buf
= malloc(file
->filesize
);
190 (*message
)(LDPL_ERROR
,
191 "Failed to allocate buffer for archive member of size: %d\n",
195 if (read(file
->fd
, buf
, file
->filesize
) != file
->filesize
) {
196 (*message
)(LDPL_ERROR
,
197 "Failed to read archive member of %s at offset %d: %s\n",
204 if (!lto_module_is_object_file_in_memory(buf
, file
->filesize
)) {
208 } else if (!lto_module_is_object_file(file
->name
))
212 Modules
.resize(Modules
.size() + 1);
213 claimed_file
&cf
= Modules
.back();
215 cf
.M
= buf
? lto_module_create_from_memory(buf
, file
->filesize
) :
216 lto_module_create(file
->name
);
219 (*message
)(LDPL_ERROR
, "Failed to create LLVM module: %s",
220 lto_get_error_message());
223 cf
.handle
= file
->handle
;
224 unsigned sym_count
= lto_module_get_num_symbols(cf
.M
);
225 cf
.syms
.reserve(sym_count
);
227 for (unsigned i
= 0; i
!= sym_count
; ++i
) {
228 lto_symbol_attributes attrs
= lto_module_get_symbol_attribute(cf
.M
, i
);
229 if ((attrs
& LTO_SYMBOL_SCOPE_MASK
) == LTO_SYMBOL_SCOPE_INTERNAL
)
232 cf
.syms
.push_back(ld_plugin_symbol());
233 ld_plugin_symbol
&sym
= cf
.syms
.back();
234 sym
.name
= const_cast<char *>(lto_module_get_symbol_name(cf
.M
, i
));
237 int scope
= attrs
& LTO_SYMBOL_SCOPE_MASK
;
239 case LTO_SYMBOL_SCOPE_HIDDEN
:
240 sym
.visibility
= LDPV_HIDDEN
;
242 case LTO_SYMBOL_SCOPE_PROTECTED
:
243 sym
.visibility
= LDPV_PROTECTED
;
246 case LTO_SYMBOL_SCOPE_DEFAULT
:
247 sym
.visibility
= LDPV_DEFAULT
;
250 (*message
)(LDPL_ERROR
, "Unknown scope attribute: %d", scope
);
254 int definition
= attrs
& LTO_SYMBOL_DEFINITION_MASK
;
255 switch (definition
) {
256 case LTO_SYMBOL_DEFINITION_REGULAR
:
259 case LTO_SYMBOL_DEFINITION_UNDEFINED
:
260 sym
.def
= LDPK_UNDEF
;
262 case LTO_SYMBOL_DEFINITION_TENTATIVE
:
263 sym
.def
= LDPK_COMMON
;
265 case LTO_SYMBOL_DEFINITION_WEAK
:
266 sym
.def
= LDPK_WEAKDEF
;
268 case LTO_SYMBOL_DEFINITION_WEAKUNDEF
:
269 sym
.def
= LDPK_WEAKUNDEF
;
272 (*message
)(LDPL_ERROR
, "Unknown definition attribute: %d", definition
);
276 // LLVM never emits COMDAT.
278 sym
.comdat_key
= NULL
;
280 sym
.resolution
= LDPR_UNKNOWN
;
283 cf
.syms
.reserve(cf
.syms
.size());
285 if (!cf
.syms
.empty()) {
286 if ((*add_symbols
)(cf
.handle
, cf
.syms
.size(), &cf
.syms
[0]) != LDPS_OK
) {
287 (*message
)(LDPL_ERROR
, "Unable to add symbols!");
295 /// all_symbols_read_hook - gold informs us that all symbols have been read.
296 /// At this point, we use get_symbols to see if any of our definitions have
297 /// been overridden by a native object file. Then, perform optimization and
299 ld_plugin_status
all_symbols_read_hook(void) {
300 lto_code_gen_t cg
= lto_codegen_create();
302 for (std::list
<claimed_file
>::iterator I
= Modules
.begin(),
303 E
= Modules
.end(); I
!= E
; ++I
)
304 lto_codegen_add_module(cg
, I
->M
);
306 std::ofstream api_file
;
307 if (generate_api_file
) {
308 api_file
.open("apifile.txt", std::ofstream::out
| std::ofstream::trunc
);
309 if (!api_file
.is_open()) {
310 (*message
)(LDPL_FATAL
, "Unable to open apifile.txt for writing.");
315 // If we don't preserve any symbols, libLTO will assume that all symbols are
316 // needed. Keep all symbols unless we're producing a final executable.
317 if (output_type
== LTO_CODEGEN_PIC_MODEL_STATIC
) {
318 bool anySymbolsPreserved
= false;
319 for (std::list
<claimed_file
>::iterator I
= Modules
.begin(),
320 E
= Modules
.end(); I
!= E
; ++I
) {
321 (*get_symbols
)(I
->handle
, I
->syms
.size(), &I
->syms
[0]);
322 for (unsigned i
= 0, e
= I
->syms
.size(); i
!= e
; i
++) {
323 if (I
->syms
[i
].resolution
== LDPR_PREVAILING_DEF
||
324 (I
->syms
[i
].def
== LDPK_COMMON
&&
325 I
->syms
[i
].resolution
== LDPR_RESOLVED_IR
)) {
326 lto_codegen_add_must_preserve_symbol(cg
, I
->syms
[i
].name
);
327 anySymbolsPreserved
= true;
329 if (generate_api_file
)
330 api_file
<< I
->syms
[i
].name
<< "\n";
335 if (generate_api_file
)
338 if (!anySymbolsPreserved
) {
339 // This entire file is unnecessary!
340 lto_codegen_dispose(cg
);
345 lto_codegen_set_pic_model(cg
, output_type
);
346 lto_codegen_set_debug_model(cg
, LTO_DEBUG_MODEL_DWARF
);
348 lto_codegen_set_gcc_path(cg
, gcc_path
);
351 const char *buffer
= static_cast<const char *>(lto_codegen_compile(cg
,
356 sys::Path
uniqueObjPath("/tmp/llvmgold.o");
357 if (uniqueObjPath
.createTemporaryFileOnDisk(true, &ErrMsg
)) {
358 (*message
)(LDPL_ERROR
, "%s", ErrMsg
.c_str());
361 raw_fd_ostream
*objFile
= new raw_fd_ostream(uniqueObjPath
.c_str(), true,
363 if (!ErrMsg
.empty()) {
365 (*message
)(LDPL_ERROR
, "%s", ErrMsg
.c_str());
369 objFile
->write(buffer
, bufsize
);
372 lto_codegen_dispose(cg
);
374 if ((*add_input_file
)(const_cast<char*>(uniqueObjPath
.c_str())) != LDPS_OK
) {
375 (*message
)(LDPL_ERROR
, "Unable to add .o file to the link.");
376 (*message
)(LDPL_ERROR
, "File left behind in: %s", uniqueObjPath
.c_str());
380 Cleanup
.push_back(uniqueObjPath
);
385 ld_plugin_status
cleanup_hook(void) {
388 for (int i
= 0, e
= Cleanup
.size(); i
!= e
; ++i
)
389 if (Cleanup
[i
].eraseFromDisk(false, &ErrMsg
))
390 (*message
)(LDPL_ERROR
, "Failed to delete '%s': %s", Cleanup
[i
].c_str(),