aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile2
-rw-r--r--tools/gold/gold-plugin.cpp209
-rw-r--r--tools/gold/gold.exports2
-rw-r--r--tools/llc/CMakeLists.txt6
-rw-r--r--tools/llc/llc.cpp258
-rw-r--r--tools/llvm-dis/llvm-dis.cpp17
-rw-r--r--tools/llvm-extract/llvm-extract.cpp47
-rw-r--r--tools/lto/LTOCodeGenerator.cpp86
-rw-r--r--tools/lto/LTOCodeGenerator.h10
-rw-r--r--tools/lto/LTOModule.cpp55
-rw-r--r--tools/lto/LTOModule.h8
-rw-r--r--tools/lto/Makefile8
-rw-r--r--tools/lto/lto.cpp132
-rw-r--r--tools/lto/lto.exports15
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