#include "llvm-c/lto.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Errno.h"
#include "llvm/System/Path.h"
+#include "llvm/System/Program.h"
#include <cerrno>
#include <cstdlib>
#include <cstring>
+#include <fstream>
#include <list>
#include <vector>
int api_version = 0;
int gold_version = 0;
+ bool generate_api_file = false;
+ const char *as_path = NULL;
+
struct claimed_file {
lto_module_t M;
void *handle;
//output_type = LTO_CODEGEN_PIC_MODEL_DYNAMIC_NO_PIC;
break;
case LDPT_OPTION:
- (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string);
+ if (strcmp("generate-api-file", tv->tv_u.tv_string) == 0) {
+ generate_api_file = true;
+ } else if (strncmp("as=", tv->tv_u.tv_string, 3) == 0) {
+ if (as_path) {
+ (*message)(LDPL_WARNING, "Path to as specified twice. "
+ "Discarding %s", tv->tv_u.tv_string);
+ } else {
+ as_path = strdup(tv->tv_u.tv_string + 3);
+ }
+ } else {
+ (*message)(LDPL_WARNING, "Ignoring flag %s", tv->tv_u.tv_string);
+ }
break;
case LDPT_REGISTER_CLAIM_FILE_HOOK: {
ld_plugin_register_claim_file callback;
}
}
- if (!registeredClaimFile || !registeredAllSymbolsRead || !registeredCleanup ||
- !add_symbols || !get_symbols || !add_input_file) {
- (*message)(LDPL_ERROR, "Not all hooks registered for LLVMgold.");
+ if (!registeredClaimFile) {
+ (*message)(LDPL_ERROR, "register_claim_file not passed to LLVMgold.");
+ return LDPS_ERR;
+ }
+ if (!add_symbols) {
+ (*message)(LDPL_ERROR, "add_symbols not passed to LLVMgold.");
return LDPS_ERR;
}
(*message)(LDPL_ERROR,
"Failed to seek to archive member of %s at offset %d: %s\n",
file->name,
- file->offset, strerror(errno));
+ file->offset, sys::StrError(errno).c_str());
return LDPS_ERR;
}
buf = malloc(file->filesize);
"Failed to read archive member of %s at offset %d: %s\n",
file->name,
file->offset,
- strerror(errno));
+ sys::StrError(errno).c_str());
free(buf);
return LDPS_ERR;
}
case LTO_SYMBOL_DEFINITION_WEAK:
sym.def = LDPK_WEAKDEF;
break;
+ case LTO_SYMBOL_DEFINITION_WEAKUNDEF:
+ sym.def = LDPK_WEAKUNDEF;
+ break;
default:
(*message)(LDPL_ERROR, "Unknown definition attribute: %d", definition);
return LDPS_ERR;
E = Modules.end(); I != E; ++I)
lto_codegen_add_module(cg, I->M);
+ std::ofstream api_file;
+ if (generate_api_file) {
+ api_file.open("apifile.txt", std::ofstream::out | std::ofstream::trunc);
+ if (!api_file.is_open()) {
+ (*message)(LDPL_FATAL, "Unable to open apifile.txt for writing.");
+ abort();
+ }
+ }
+
// If we don't preserve any symbols, libLTO will assume that all symbols are
// needed. Keep all symbols unless we're producing a final executable.
if (output_type == LTO_CODEGEN_PIC_MODEL_STATIC) {
E = Modules.end(); I != E; ++I) {
(*get_symbols)(I->handle, I->syms.size(), &I->syms[0]);
for (unsigned i = 0, e = I->syms.size(); i != e; i++) {
- (*message)(LDPL_WARNING, "def: %d visibility: %d resolution %d",
- I->syms[i].def, I->syms[i].visibility, I->syms[i].resolution);
if (I->syms[i].resolution == LDPR_PREVAILING_DEF ||
(I->syms[i].def == LDPK_COMMON &&
I->syms[i].resolution == LDPR_RESOLVED_IR)) {
lto_codegen_add_must_preserve_symbol(cg, I->syms[i].name);
anySymbolsPreserved = true;
+
+ if (generate_api_file)
+ api_file << I->syms[i].name << "\n";
}
}
}
+ if (generate_api_file)
+ api_file.close();
+
if (!anySymbolsPreserved) {
// This entire file is unnecessary!
lto_codegen_dispose(cg);
lto_codegen_set_pic_model(cg, output_type);
lto_codegen_set_debug_model(cg, LTO_DEBUG_MODEL_DWARF);
+ if (as_path) {
+ sys::Path p = sys::Program::FindProgramByName(as_path);
+ lto_codegen_set_assembler_path(cg, p.c_str());
+ }
size_t bufsize = 0;
const char *buffer = static_cast<const char *>(lto_codegen_compile(cg,