diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/gold/gold-plugin.cpp | 209 | ||||
-rw-r--r-- | tools/gold/gold.exports | 2 | ||||
-rw-r--r-- | tools/llc/CMakeLists.txt | 6 | ||||
-rw-r--r-- | tools/llc/llc.cpp | 258 | ||||
-rw-r--r-- | tools/llvm-dis/llvm-dis.cpp | 17 | ||||
-rw-r--r-- | tools/llvm-extract/llvm-extract.cpp | 47 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.cpp | 86 | ||||
-rw-r--r-- | tools/lto/LTOCodeGenerator.h | 10 | ||||
-rw-r--r-- | tools/lto/LTOModule.cpp | 55 | ||||
-rw-r--r-- | tools/lto/LTOModule.h | 8 | ||||
-rw-r--r-- | tools/lto/Makefile | 8 | ||||
-rw-r--r-- | tools/lto/lto.cpp | 132 | ||||
-rw-r--r-- | tools/lto/lto.exports | 15 |
14 files changed, 838 insertions, 17 deletions
diff --git a/tools/Makefile b/tools/Makefile index 2b4b9b7878..901d3f35e4 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -34,7 +34,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \ bugpoint llvm-bcanalyzer \ llvm-diff macho-dump llvm-objdump llvm-readobj \ llvm-rtdyld llvm-dwarfdump llvm-cov \ - llvm-size llvm-stress + llvm-size llvm-stress bc-wrap pso-stub # Let users override the set of tools to build from the command line. ifdef ONLY_TOOLS diff --git a/tools/gold/gold-plugin.cpp b/tools/gold/gold-plugin.cpp index 9c17da6a4c..1c99730d45 100644 --- a/tools/gold/gold-plugin.cpp +++ b/tools/gold/gold-plugin.cpp @@ -55,6 +55,25 @@ namespace { ld_plugin_set_extra_library_path set_extra_library_path = NULL; ld_plugin_get_view get_view = NULL; ld_plugin_message message = discard_message; + // @LOCALMOD-BEGIN + // REL, DYN, or EXEC + ld_plugin_output_file_type linker_output; + + // Callback for getting link soname from gold + ld_plugin_get_output_soname get_output_soname = NULL; + + // Callback for getting needed libraries from gold + ld_plugin_get_needed get_needed = NULL; + + // Callback for getting number of needed library from gold + ld_plugin_get_num_needed get_num_needed = NULL; + + // Callback for getting the number of --wrap'd symbols. + ld_plugin_get_num_wrapped get_num_wrapped = NULL; + + // Callback for getting the name of a wrapped symbol. + ld_plugin_get_wrapped get_wrapped = NULL; + // @LOCALMOD-END int api_version = 0; int gold_version = 0; @@ -62,11 +81,17 @@ namespace { struct claimed_file { void *handle; std::vector<ld_plugin_symbol> syms; + bool is_linked_in; // @LOCALMOD }; lto_codegen_model output_type = LTO_CODEGEN_PIC_MODEL_STATIC; std::string output_name = ""; std::list<claimed_file> Modules; + + // @LOCALMOD-BEGIN + std::vector<std::string> DepLibs; + // @LOCALMOD-END + std::vector<sys::Path> Cleanup; lto_code_gen_t code_gen = NULL; } @@ -123,13 +148,25 @@ namespace options { } } +// @LOCALMOD-BEGIN +static const char *get_basename(const char *path) { + if (path == NULL) + return NULL; + const char *slash = strrchr(path, '/'); + if (slash) + return slash + 1; + + return path; +} +// @LOCALMOD-END + static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, int *claimed); static ld_plugin_status all_symbols_read_hook(void); static ld_plugin_status cleanup_hook(void); -extern "C" ld_plugin_status onload(ld_plugin_tv *tv); -ld_plugin_status onload(ld_plugin_tv *tv) { +extern "C" ld_plugin_status llvm_plugin_onload(ld_plugin_tv *tv); // @LOCALMOD +ld_plugin_status llvm_plugin_onload(ld_plugin_tv *tv) { // @LOCALMOD // We're given a pointer to the first transfer vector. We read through them // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values // contain pointers to functions that we need to call to register our own @@ -150,6 +187,10 @@ ld_plugin_status onload(ld_plugin_tv *tv) { output_name = tv->tv_u.tv_string; break; case LDPT_LINKER_OUTPUT: + // @LOCALMOD-BEGIN + linker_output = + static_cast<ld_plugin_output_file_type>(tv->tv_u.tv_val); + // @LOCALMOD-END switch (tv->tv_u.tv_val) { case LDPO_REL: // .o case LDPO_DYN: // .so @@ -213,7 +254,23 @@ ld_plugin_status onload(ld_plugin_tv *tv) { break; case LDPT_GET_VIEW: get_view = tv->tv_u.tv_get_view; + // @LOCALMOD-BEGIN + case LDPT_GET_OUTPUT_SONAME: + get_output_soname = tv->tv_u.tv_get_output_soname; + break; + case LDPT_GET_NEEDED: + get_needed = tv->tv_u.tv_get_needed; + break; + case LDPT_GET_NUM_NEEDED: + get_num_needed = tv->tv_u.tv_get_num_needed; + break; + case LDPT_GET_WRAPPED: + get_wrapped = tv->tv_u.tv_get_wrapped; break; + case LDPT_GET_NUM_WRAPPED: + get_num_wrapped = tv->tv_u.tv_get_num_wrapped; + break; + // @LOCALMOD-END case LDPT_MESSAGE: message = tv->tv_u.tv_message; break; @@ -231,6 +288,24 @@ ld_plugin_status onload(ld_plugin_tv *tv) { return LDPS_ERR; } + // @LOCALMOD-BEGIN + // Parse extra command-line options + // Although lto_codegen provides a way to parse command-line arguments, + // we need the arguments to be parsed and applied before LTOModules are + // even created. In particular, this is needed because the + // "-add-nacl-read-tp-dependency" flag affects how modules are created. + if (!options::extra.empty()) { + for (std::vector<std::string>::iterator it = options::extra.begin(); + it != options::extra.end(); ++it) { + lto_add_command_line_option((*it).c_str()); + } + lto_parse_command_line_options(); + // We clear the options so that they don't get parsed again in + // lto_codegen_debug_options. + options::extra.clear(); + } + // @LOCALMOD-END + return LDPS_OK; } @@ -297,7 +372,21 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, ld_plugin_symbol &sym = cf.syms.back(); sym.name = const_cast<char *>(lto_module_get_symbol_name(M, i)); sym.name = strdup(sym.name); + // @LOCALMOD-BEGIN + // Localmods have disabled the use of the 'version' field for passing + // version information to Gold. Instead, the version is now transmitted as + // part of the 'name' field, which has the form "sym@VER" or "sym@@VER". + // This is nicer because it communicates one extra bit of information (@@ + // marks the default version), and allows us to access the real symbol + // name in all_symbols_read. + + // These fields are set by Gold to communicate the updated version info + // to the plugin. They are used in all_symbols_read_hook(). + // Initialize them for predictability. sym.version = NULL; + sym.is_default = false; + sym.dynfile = NULL; + // @LOCALMOD-END int scope = attrs & LTO_SYMBOL_SCOPE_MASK; switch (scope) { @@ -346,16 +435,37 @@ static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, } cf.syms.reserve(cf.syms.size()); + // @LOCALMOD-BEGIN + bool is_shared = + (lto_module_get_output_format(M) == LTO_OUTPUT_FORMAT_SHARED); + const char* soname = lto_module_get_soname(M); + if (soname[0] == '\0') + soname = NULL; + // @LOCALMOD-END if (!cf.syms.empty()) { - if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0]) != LDPS_OK) { + if ((*add_symbols)(cf.handle, cf.syms.size(), &cf.syms[0], + is_shared, soname) != LDPS_OK) { // @LOCALMOD (*message)(LDPL_ERROR, "Unable to add symbols!"); return LDPS_ERR; } } - if (code_gen) - lto_codegen_add_module(code_gen, M); + // @LOCALMOD-BEGIN + // Do not merge the module if it's a PSO. + // If the PSO's soname is set, add it to DepLibs. + cf.is_linked_in = false; + if (code_gen) { + if (is_shared) { + if (soname && strlen(soname) > 0) { + DepLibs.push_back(soname); + } + } else { + lto_codegen_add_module(code_gen, M); + cf.is_linked_in = true; + } + } + // @LOCALMOD-END lto_module_dispose(M); @@ -387,13 +497,46 @@ static ld_plugin_status all_symbols_read_hook(void) { continue; (*get_symbols)(I->handle, I->syms.size(), &I->syms[0]); for (unsigned i = 0, e = I->syms.size(); i != e; i++) { + // @LOCALMOD-BEGIN + // Don't process the symbols inside a dynamic object. + if (!I->is_linked_in) + continue; + // @LOCALMOD-END + if (I->syms[i].resolution == LDPR_PREVAILING_DEF) { + // @LOCALMOD-BEGIN + // Set the symbol version in the module. + if (linker_output != LDPO_REL && I->syms[i].version) { + // NOTE: This may change the name of the symbol, so it must happen + // before the call to lto_codegen_add_must_preserve_symbols() below. + I->syms[i].name = const_cast<char *>( + lto_codegen_set_symbol_def_version(code_gen, I->syms[i].name, + I->syms[i].version, + I->syms[i].is_default)); + } lto_codegen_add_must_preserve_symbol(code_gen, I->syms[i].name); + // @LOCALMOD-END anySymbolsPreserved = true; if (options::generate_api_file) api_file << I->syms[i].name << "\n"; } + // @LOCALMOD-BEGIN + else if (linker_output != LDPO_REL && + (I->syms[i].resolution == LDPR_RESOLVED_DYN || + I->syms[i].resolution == LDPR_UNDEF)) { + // This symbol is provided by an external object. + // Set the version and source dynamic file for it. + const char *ver = I->syms[i].version; + const char *dynfile = I->syms[i].dynfile; + dynfile = get_basename(dynfile); + // NOTE: This may change the name of the symbol. + I->syms[i].name = const_cast<char *>( + lto_codegen_set_symbol_needed(code_gen, I->syms[i].name, + ver ? ver : "", + dynfile ? dynfile : "")); + } + // @LOCALMOD-END } } @@ -411,6 +554,11 @@ static ld_plugin_status all_symbols_read_hook(void) { if (!options::mcpu.empty()) lto_codegen_set_cpu(code_gen, options::mcpu.c_str()); + // @LOCALMOD-BEGIN (COMMENT) + // "extra" will always be empty below, because we process the extra + // options earlier, at the end of onload(). + // @LOCALMOD-END + // Pass through extra options to the code generator. if (!options::extra.empty()) { for (std::vector<std::string>::iterator it = options::extra.begin(); @@ -419,6 +567,57 @@ static ld_plugin_status all_symbols_read_hook(void) { } } + // @LOCALMOD-BEGIN + // Store the linker output format into the bitcode. + lto_output_format format; + switch (linker_output) { + case LDPO_REL: + format = LTO_OUTPUT_FORMAT_OBJECT; + break; + case LDPO_DYN: + format = LTO_OUTPUT_FORMAT_SHARED; + break; + case LDPO_EXEC: + format = LTO_OUTPUT_FORMAT_EXEC; + break; + default: + (*message)(LDPL_FATAL, "Unknown linker output format (gold-plugin)"); + abort(); + break; + } + lto_codegen_set_merged_module_output_format(code_gen, format); + // @LOCALMOD-END + + // @LOCALMOD-BEGIN + // For -shared linking, store the soname into the bitcode. + if (linker_output == LDPO_DYN) { + const char *soname = (*get_output_soname)(); + lto_codegen_set_merged_module_soname(code_gen, soname); + } + // @LOCALMOD-END + + // @LOCALMOD-BEGIN + // Add the needed libraries to the bitcode. + unsigned int num_needed = (*get_num_needed)(); + for (unsigned i=0; i < num_needed; ++i) { + const char *soname = (*get_needed)(i); + soname = get_basename(soname); + lto_codegen_add_merged_module_library_dep(code_gen, soname); + } + for (std::vector<std::string>::iterator I = DepLibs.begin(), + E = DepLibs.end(); I != E; ++I) { + lto_codegen_add_merged_module_library_dep(code_gen, I->c_str()); + } + // @LOCALMOD-END + + // @LOCALMOD-BEGIN + // Perform symbol wrapping. + unsigned int num_wrapped = (*get_num_wrapped)(); + for (unsigned i=0; i < num_wrapped; ++i) { + const char *sym = (*get_wrapped)(i); + lto_codegen_wrap_symbol_in_merged_module(code_gen, sym); + } + // @LOCALMOD-END if (options::generate_bc_file != options::BC_NO) { std::string path; if (options::generate_bc_file == options::BC_ONLY) diff --git a/tools/gold/gold.exports b/tools/gold/gold.exports index 277a33a1ec..89d8640427 100644 --- a/tools/gold/gold.exports +++ b/tools/gold/gold.exports @@ -1 +1 @@ -onload +llvm_plugin_onload diff --git a/tools/llc/CMakeLists.txt b/tools/llc/CMakeLists.txt index 683f29862d..9c695bcdea 100644 --- a/tools/llc/CMakeLists.txt +++ b/tools/llc/CMakeLists.txt @@ -1,5 +1,11 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} bitreader asmparser) add_llvm_tool(llc +# LOCALMOD BEGIN +# This file provides wrappers to lseek(2), read(2), etc. + nacl_file.cpp + StubMaker.cpp + TextStubWriter.cpp +# LOCALMOD END llc.cpp ) diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index a99d0b787a..f87978ec43 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -18,7 +18,9 @@ #include "llvm/PassManager.h" #include "llvm/Pass.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/DataStream.h" #include "llvm/Support/IRReader.h" +#include "llvm/CodeGen/IntrinsicLowering.h" // @LOCALMOD #include "llvm/CodeGen/LinkAllAsmWriterComponents.h" #include "llvm/CodeGen/LinkAllCodegenComponents.h" #include "llvm/MC/SubtargetFeature.h" @@ -26,7 +28,9 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" +#if !defined(__native_client__) #include "llvm/Support/PluginLoader.h" +#endif #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/Host.h" @@ -36,8 +40,33 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include <memory> + +// @LOCALMOD-BEGIN +#include "StubMaker.h" +#include "TextStubWriter.h" +// @LOCALMOD-END + using namespace llvm; +// @LOCALMOD-BEGIN +// NOTE: this tool can be build as a "sandboxed" translator. +// There are two ways to build the translator +// SRPC-style: no file operations are allowed +// see nacl_file.cc for support code +// non-SRPC-style: some basic file operations are allowed +// This can be useful for debugging but will +// not be deployed. +#if defined(__native_client__) && defined(NACL_SRPC) +MemoryBuffer* NaClGetMemoryBufferForFile(const char* filename); +void NaClOutputStringToFile(const char* filename, const std::string& data); +// The following two functions communicate metadata to the SRPC wrapper for LLC. +void NaClRecordObjectInformation(bool is_shared, const std::string& soname); +void NaClRecordSharedLibraryDependency(const std::string& library_name); +DataStreamer* NaClBitcodeStreamer; +#endif +// @LOCALMOD-END + + // General options for llc. Other pass-specific options are specified // within the corresponding llc passes, and target-specific options // and back-end code generation options are specified with the target machine. @@ -48,6 +77,12 @@ InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-")); static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); +// @LOCALMOD-BEGIN +static cl::opt<std::string> +MetadataTextFilename("metadata-text", cl::desc("Metadata as text, out filename"), + cl::value_desc("filename")); +// @LOCALMOD-END + // Determine optimization level. static cl::opt<char> OptLevel("O", @@ -244,6 +279,26 @@ SegmentedStacks("segmented-stacks", cl::desc("Use segmented stacks if possible."), cl::init(false)); +// @LOCALMOD-BEGIN +// Using bitcode streaming has a couple of ramifications. Primarily it means +// that the module in the file will be compiled one function at a time rather +// than the whole module. This allows earlier functions to be compiled before +// later functions are read from the bitcode but of course means no whole-module +// optimizations. For now, streaming is only supported for files and stdin. +static cl::opt<bool> +LazyBitcode("streaming-bitcode", + cl::desc("Use lazy bitcode streaming for file inputs"), + cl::init(false)); + +// The option below overlaps very much with bitcode streaming. +// We keep it separate because it is still experimental and we want +// to use it without changing the outside behavior which is especially +// relevant for the sandboxed case. +static cl::opt<bool> +ReduceMemoryFootprint("reduce-memory-footprint", + cl::desc("Aggressively reduce memory used by llc"), + cl::init(false)); +// @LOCALMOD-END // GetFileNameRoot - Helper function to get the basename of a filename. static inline std::string @@ -323,9 +378,60 @@ static tool_output_file *GetOutputStream(const char *TargetName, return FDOut; } +// @LOCALMOD-BEGIN +#if defined(__native_client__) && defined(NACL_SRPC) +void RecordMetadataForSrpc(const Module &mod) { + bool is_shared = (mod.getOutputFormat() == Module::SharedOutputFormat); + std::string soname = mod.getSOName(); + NaClRecordObjectInformation(is_shared, soname); + for (Module::lib_iterator L = mod.lib_begin(), + E = mod.lib_end(); + L != E; ++L) { + NaClRecordSharedLibraryDependency(*L); + } +} +#endif // defined(__native_client__) && defined(NACL_SRPC) +// @LOCALMOD-END + + +// @LOCALMOD-BEGIN + +// Write the ELF Stubs to the metadata file, in text format +// Returns 0 on success, non-zero on error. +int WriteTextMetadataFile(const Module &M, const Triple &TheTriple) { + // Build the ELF stubs (in high level format) + SmallVector<ELFStub*, 8> StubList; + // NOTE: The triple is unnecessary for the text version. + MakeAllStubs(M, TheTriple, &StubList); + // For each stub, write the ELF object to the metadata file. + std::string s; + for (unsigned i = 0; i < StubList.size(); i++) { + WriteTextELFStub(StubList[i], &s); + } + FreeStubList(&StubList); + +#if defined(__native_client__) && defined(NACL_SRPC) + NaClOutputStringToFile(MetadataTextFilename.c_str(), s); +#else + std::string error; + OwningPtr<tool_output_file> MOut( + new tool_output_file(MetadataTextFilename.c_str(), error, + raw_fd_ostream::F_Binary)); + if (!error.empty()) { + errs() << error << '\n'; + return 1; + } + MOut->os().write(s.data(), s.size()); + MOut->keep(); +#endif + return 0; +} + +// @LOCALMOD-END + // main - Entry point for the llc compiler. // -int main(int argc, char **argv) { +int llc_main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); @@ -350,13 +456,64 @@ int main(int argc, char **argv) { SMDiagnostic Err; std::auto_ptr<Module> M; - M.reset(ParseIRFile(InputFilename, Err, Context)); + // @LOCALMOD-BEGIN +#if defined(__native_client__) && defined(NACL_SRPC) + if (LazyBitcode) { + std::string StrError; + M.reset(getStreamedBitcodeModule(std::string("<SRPC stream>"), + NaClBitcodeStreamer, Context, &StrError)); + if (!StrError.empty()) { + Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError); + } + } else { + // In the NACL_SRPC case, fake a memory mapped file + // TODO(jvoung): revert changes in MemoryBuffer.cpp, no longer needed + M.reset(ParseIR(NaClGetMemoryBufferForFile(InputFilename.c_str()), + Err, + Context)); + M->setModuleIdentifier(InputFilename); + } +#else + if (LazyBitcode) { + std::string StrError; + DataStreamer *streamer = getDataFileStreamer(InputFilename, &StrError); + if (streamer) { + M.reset(getStreamedBitcodeModule(InputFilename, streamer, Context, + &StrError)); + } + if (!StrError.empty()) { + Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError); + } + } else { + M.reset(ParseIRFile(InputFilename, Err, Context)); + } +#endif + // @LOCALMOD-END + if (M.get() == 0) { Err.print(argv[0], errs()); return 1; } Module &mod = *M.get(); + // @LOCALMOD-BEGIN +#if defined(__native_client__) && defined(NACL_SRPC) + RecordMetadataForSrpc(mod); + + // To determine if we should compile PIC or not, we needed to load at + // least the metadata. Since we've already constructed the commandline, + // we have to hack this in after commandline processing. + if (mod.getOutputFormat() == Module::SharedOutputFormat) { + RelocModel = Reloc::PIC_; + } + // Also set PIC_ for dynamic executables: + // BUG= http://code.google.com/p/nativeclient/issues/detail?id=2351 + if (mod.lib_size() > 0) { + RelocModel = Reloc::PIC_; + } +#endif // defined(__native_client__) && defined(NACL_SRPC) + // @LOCALMOD-END + // If we are supposed to override the target triple, do so now. if (!TargetTriple.empty()) mod.setTargetTriple(Triple::normalize(TargetTriple)); @@ -379,6 +536,11 @@ int main(int argc, char **argv) { std::string FeaturesStr; if (MAttrs.size()) { SubtargetFeatures Features; + // @LOCALMOD-BEGIN + // Use the same default attribute settings as libLTO. + // TODO(pdox): Figure out why this isn't done for upstream llc. + Features.getDefaultSubtargetFeatures(TheTriple); + // @LOCALMOD-END for (unsigned i = 0; i != MAttrs.size(); ++i) Features.AddFeature(MAttrs[i]); FeaturesStr = Features.getString(); @@ -443,19 +605,27 @@ int main(int argc, char **argv) { TheTriple.isMacOSXVersionLT(10, 6)) Target.setMCUseLoc(false); +#if !defined(NACL_SRPC) // Figure out where we are going to send the output... OwningPtr<tool_output_file> Out (GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0])); if (!Out) return 1; - +#endif + // Build up all of the passes that we want to do to the module. - PassManager PM; + // @LOCALMOD-BEGIN + OwningPtr<PassManagerBase> PM; + if (LazyBitcode || ReduceMemoryFootprint) + PM.reset(new FunctionPassManager(&mod)); + else + PM.reset(new PassManager()); + // @LOCALMOD-END // Add the target data from the target machine, if it exists, or the module. if (const TargetData *TD = Target.getTargetData()) - PM.add(new TargetData(*TD)); + PM->add(new TargetData(*TD)); else - PM.add(new TargetData(&mod)); + PM->add(new TargetData(&mod)); // Override default to generate verbose assembly. Target.setAsmVerbosityDefault(true); @@ -468,11 +638,44 @@ int main(int argc, char **argv) { Target.setMCRelaxAll(true); } + + +#if defined __native_client__ && defined(NACL_SRPC) + { + std::string s; + raw_string_ostream ROS(s); + formatted_raw_ostream FOS(ROS); + // Ask the target to add backend passes as necessary. + if (Target.addPassesToEmitFile(*PM, FOS, FileType, NoVerify)) { + errs() << argv[0] << ": target does not support generation of this" + << " file type!\n"; + return 1; + } + + if (LazyBitcode || ReduceMemoryFootprint) { + FunctionPassManager* P = static_cast<FunctionPassManager*>(PM.get()); + P->doInitialization(); + for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I) { + P->run(*I); + if (ReduceMemoryFootprint) { + I->Dematerialize(); + } + } + P->doFinalization(); + } else { + static_cast<PassManager*>(PM.get())->run(mod); + } + FOS.flush(); + ROS.flush(); + NaClOutputStringToFile(OutputFilename.c_str(), ROS.str()); + } +#else + { formatted_raw_ostream FOS(Out->os()); // Ask the target to add backend passes as necessary. - if (Target.addPassesToEmitFile(PM, FOS, FileType, NoVerify)) { + if (Target.addPassesToEmitFile(*PM, FOS, FileType, NoVerify)) { errs() << argv[0] << ": target does not support generation of this" << " file type!\n"; return 1; @@ -481,11 +684,50 @@ int main(int argc, char **argv) { // Before executing passes, print the final values of the LLVM options. cl::PrintOptionValues(); - PM.run(mod); + if (LazyBitcode || ReduceMemoryFootprint) { + FunctionPassManager *P = static_cast<FunctionPassManager*>(PM.get()); + P->doInitialization(); + for (Module::iterator I = mod.begin(), E = mod.end(); I != E; ++I) { + P->run(*I); + if (ReduceMemoryFootprint) { + I->Dematerialize(); + } + } + P->doFinalization(); + } else { + static_cast<PassManager*>(PM.get())->run(mod); + } } // Declare success. Out->keep(); +#endif + + // @LOCALMOD-BEGIN + // Write out the metadata. + // + // We need to ensure that intrinsic prototypes are available, in case + // we have a NeededRecord for one of them. + // They may have been eliminated by the StripDeadPrototypes pass, + // or some other pass that is unaware of NeededRecords / IntrinsicLowering. + IntrinsicLowering IL(*target->getTargetData()); + IL.AddPrototypes(*M); + + if (!MetadataTextFilename.empty()) { + int err = WriteTextMetadataFile(*M.get(), TheTriple); + if (err != 0) + return err; + } + // @LOCALMOD-END return 0; } + +#if !defined(NACL_SRPC) +int +main (int argc, char **argv) { + return llc_main(argc, argv); +} +#else +// main() is in nacl_file.cpp. +#endif diff --git a/tools/llvm-dis/llvm-dis.cpp b/tools/llvm-dis/llvm-dis.cpp index 6450ea6ac7..a5f68a6418 100644 --- a/tools/llvm-dis/llvm-dis.cpp +++ b/tools/llvm-dis/llvm-dis.cpp @@ -51,6 +51,13 @@ static cl::opt<bool> ShowAnnotations("show-annotations", cl::desc("Add informational comments to the .ll file")); +// @LOCALMOD-BEGIN +// Print bitcode metadata only, in text format. +// (includes output format, soname, and dependencies). +static cl::opt<bool> +DumpMetadata("dump-metadata", cl::desc("Dump bitcode metadata")); +// @LOCALMOD-END + namespace { static void printDebugLoc(const DebugLoc &DL, formatted_raw_ostream &OS) { @@ -156,7 +163,7 @@ int main(int argc, char **argv) { OutputFilename = "-"; if (OutputFilename.empty()) { // Unspecified output, infer it. - if (InputFilename == "-") { + if (InputFilename == "-" || DumpMetadata) { // @LOCALMOD OutputFilename = "-"; } else { const std::string &IFN = InputFilename; @@ -178,6 +185,14 @@ int main(int argc, char **argv) { return 1; } + // @LOCALMOD-BEGIN + if (DumpMetadata) { + M->dumpMeta(Out->os()); + Out->keep(); + return 0; + } + // @LOCALMOD-END + OwningPtr<AssemblyAnnotationWriter> Annotator; if (ShowAnnotations) Annotator.reset(new CommentWriter()); diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 2ed11c52b2..4ea1a9080d 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -20,6 +20,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" // @LOCALMOD #include "llvm/Support/IRReader.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" @@ -47,6 +48,18 @@ Force("f", cl::desc("Enable binary output on terminals")); static cl::opt<bool> DeleteFn("delete", cl::desc("Delete specified Globals from Module")); +// @LOCALMOD-BEGIN +static cl::opt<unsigned> +Divisor("divisor", + cl::init(0), + cl::desc("select GV by position (pos % divisor = remainder ")); + +static cl::opt<unsigned> +Remainder("remainder", + cl::init(0), + cl::desc("select GV by position (pos % divisor = remainder ")); +// @LOCALMOD-END + // ExtractFuncs - The functions to extract from the module. static cl::list<std::string> ExtractFuncs("func", cl::desc("Specify function to extract"), @@ -131,6 +144,24 @@ int main(int argc, char **argv) { } } + // @LOCALMOD-BEGIN + // Extract globals via modulo operation. + size_t count_globals = 0; + if (Divisor != 0) { + size_t pos = 0; + for (Module::global_iterator GV = M->global_begin(), E = M->global_end(); + GV != E; + GV++, pos++) { + if (pos % Divisor == Remainder) { + GVs.insert(&*GV); + } + } + dbgs() << "total globals: " << pos << "\n"; + count_globals = GVs.size(); + dbgs() << "selected globals: " << count_globals << "\n"; + } + // @LOCALMOD-END + // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); @@ -165,6 +196,22 @@ int main(int argc, char **argv) { } } + // @LOCALMOD-BEGIN + // Extract functions via modulo operation. + if (Divisor != 0) { + size_t pos = 0; + for (Module::iterator F = M->begin(), E = M->end(); + F != E; + F++, pos++) { + if (pos % Divisor == Remainder) { + GVs.insert(&*F); + } + } + dbgs() << "total functions: " << pos << "\n"; + dbgs() << "selected functions: " << GVs.size() - count_globals << "\n"; + } + // @LOCALMOD-END + // Materialize requisite global values. if (!DeleteFn) for (size_t i = 0, e = GVs.size(); i != e; ++i) { diff --git a/tools/lto/LTOCodeGenerator.cpp b/tools/lto/LTOCodeGenerator.cpp index 08139470be..c28f8732b5 100644 --- a/tools/lto/LTOCodeGenerator.cpp +++ b/tools/lto/LTOCodeGenerator.cpp @@ -23,6 +23,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/IntrinsicLowering.h" // @LOCALMOD #include "llvm/Config/config.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -69,6 +70,16 @@ LTOCodeGenerator::LTOCodeGenerator() InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); + + // @LOCALMOD-BEGIN + // Preserve symbols which may be referenced due to the lowering + // of an intrinsic. + const llvm::StringSet<> &IntrinsicSymbols = IntrinsicLowering::GetFuncNames(); + for (llvm::StringSet<>::const_iterator it = IntrinsicSymbols.begin(), + ie = IntrinsicSymbols.end(); it != ie; ++it) { + _mustPreserveSymbols[it->getKey().str().c_str()] = 1; + } + // @LOCALMOD-END } LTOCodeGenerator::~LTOCodeGenerator() { @@ -116,6 +127,81 @@ bool LTOCodeGenerator::setCodePICModel(lto_codegen_model model, llvm_unreachable("Unknown PIC model!"); } +// @LOCALMOD-BEGIN +void LTOCodeGenerator::setMergedModuleOutputFormat(lto_output_format format) +{ + Module::OutputFormat outputFormat; + switch (format) { + case LTO_OUTPUT_FORMAT_OBJECT: + outputFormat = Module::ObjectOutputFormat; + break; + case LTO_OUTPUT_FORMAT_SHARED: + outputFormat = Module::SharedOutputFormat; + break; + case LTO_OUTPUT_FORMAT_EXEC: + outputFormat = Module::ExecutableOutputFormat; + break; + } + Module *mergedModule = _linker.getModule(); + mergedModule->setOutputFormat(outputFormat); +} + +void LTOCodeGenerator::setMergedModuleSOName(const char *soname) +{ + Module *mergedModule = _linker.getModule(); + mergedModule->setSOName(soname); +} + +void LTOCodeGenerator::addLibraryDep(const char *lib) +{ + Module *mergedModule = _linker.getModule(); + mergedModule->addLibrary(lib); +} + +void LTOCodeGenerator::wrapSymbol(const char *sym) +{ + Module *mergedModule = _linker.getModule(); + mergedModule->wrapSymbol(sym); +} + +const char* LTOCodeGenerator::setSymbolDefVersion(const char *sym, + const char *ver, + bool is_default) +{ + Module *mergedModule = _linker.getModule(); + GlobalValue *GV = mergedModule->getNamedValue(sym); + if (!GV) { + llvm_unreachable("Invalid global in setSymbolDefVersion"); + } + GV->setVersionDef(ver, is_default); + return strdup(GV->getName().str().c_str()); +} + +const char* LTOCodeGenerator::setSymbolNeeded(const char *sym, + const char *ver, + const char *dynfile) +{ + Module *mergedModule = _linker.getModule(); + GlobalValue *GV = mergedModule->getNamedValue(sym); + if (!GV) { + // Symbol lookup may have failed because this symbol was already + // renamed for versioning. Make sure this is the case. + if (strchr(sym, '@') != NULL || ver == NULL || ver[0] == '\0') { + llvm_unreachable("Unexpected |