Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Unified Diff: tools/pnacl-llc/srpc_main.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/pnacl-llc/pnacl-llc.cpp ('k') | tools/pnacl-thaw/CMakeLists.txt » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/pnacl-llc/srpc_main.cpp
diff --git a/tools/pnacl-llc/srpc_main.cpp b/tools/pnacl-llc/srpc_main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..40d3242b9c08e45bf7e160c66281974a1deb327b
--- /dev/null
+++ b/tools/pnacl-llc/srpc_main.cpp
@@ -0,0 +1,361 @@
+//===-- srpc_main.cpp - PNaCl sandboxed translator invocation -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Main invocation of the sandboxed translator through SRPC.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(PNACL_BROWSER_TRANSLATOR)
+
+// Headers which are not properly part of the SDK are included by their
+// path in the NaCl tree.
+#include "native_client/src/shared/srpc/nacl_srpc.h"
+#ifdef __pnacl__
+#include "native_client/src/untrusted/nacl/pnacl.h"
+#endif // __pnacl__
+
+#include "SRPCStreamer.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include <argz.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+using namespace llvm;
+using namespace llvm::opt;
+using std::string;
+
+// Imported from pnacl-llc.cpp
+extern int llc_main(int argc, char **argv);
+
+namespace {
+
+// The filename used internally for looking up the bitcode file.
+const char kBitcodeFilename[] = "pnacl.pexe";
+// The filename used internally for looking up the object code file.
+const char kObjectFilename[] = "pnacl.o";
+// Maximum number of modules supported for splitting. Can't be changed without
+// also changing the SRPC signature for StreamInitWithSplit
+const int kMaxModuleSplit = 16;
+// Object which manages streaming bitcode over SRPC and threading.
+SRPCStreamer *srpc_streamer;
+// FDs of the object file(s).
+int object_file_fd[kMaxModuleSplit];
+
+DataStreamer *NaClBitcodeStreamer;
+
+int DoTranslate(ArgStringList *CmdLineArgs) {
+ if (CmdLineArgs == NULL) {
+ return 1;
+ }
+ // Make an argv array from the input vector.
+ size_t argc = CmdLineArgs->size();
+ char **argv = new char *[argc + 1];
+ for (size_t i = 0; i < argc; ++i) {
+ // llc_main will not mutate the command line, so this is safe.
+ argv[i] = const_cast<char *>((*CmdLineArgs)[i]);
+ }
+ argv[argc] = NULL;
+ // Call main.
+ return llc_main(static_cast<int>(argc), argv);
+}
+
+ArgStringList *CommandLineFromArgz(char *str, size_t str_len) {
+ char *entry = str;
+ ArgStringList *CmdLineArgs = new ArgStringList;
+ while (entry != NULL && str_len) {
+ // Call strdup(entry) since the str argument will ultimately be
+ // freed by the SRPC message sender.
+ CmdLineArgs->push_back(strdup(entry));
+ entry = argz_next(str, str_len, entry);
+ }
+ return CmdLineArgs;
+}
+
+void AddFixedArguments(ArgStringList *CmdLineArgs) {
+ // Add fixed arguments to the command line. These specify the bitcode
+ // and object code filenames, removing them from the contract with the
+ // coordinator.
+ CmdLineArgs->push_back(kBitcodeFilename);
+ CmdLineArgs->push_back("-o");
+ CmdLineArgs->push_back(kObjectFilename);
+}
+
+bool AddDefaultCPU(ArgStringList *CmdLineArgs) {
+#if defined(__pnacl__)
+ switch (__builtin_nacl_target_arch()) {
+ case PnaclTargetArchitectureX86_32: {
+ CmdLineArgs->push_back("-mcpu=pentium4m");
+ break;
+ }
+ case PnaclTargetArchitectureX86_64: {
+ CmdLineArgs->push_back("-mcpu=x86-64");
+ break;
+ }
+ case PnaclTargetArchitectureARM_32: {
+ CmdLineArgs->push_back("-mcpu=cortex-a9");
+ break;
+ }
+ default:
+ fprintf(stderr, "no target architecture match.\n");
+ return false;
+ }
+// Some cases for building this with nacl-gcc.
+#elif defined(__i386__)
+ CmdLineArgs->push_back("-mcpu=pentium4m");
+#elif defined(__x86_64__)
+ CmdLineArgs->push_back("-mcpu=x86-64");
+#elif defined(__arm__)
+ CmdLineArgs->push_back("-mcpu=cortex-a9");
+#else
+#error "Unknown architecture"
+#endif
+ return true;
+}
+
+bool HasCPUOverride(ArgStringList *CmdLineArgs) {
+ const char *Mcpu = "-mcpu";
+ size_t McpuLen = strlen(Mcpu);
+ for (size_t i = 0; i < CmdLineArgs->size(); ++i) {
+ if (strncmp((*CmdLineArgs)[i], Mcpu, McpuLen) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+ArgStringList *GetDefaultCommandLine() {
+ ArgStringList *command_line = new ArgStringList;
+ // First, those common to all architectures.
+ static const char *common_args[] = { "pnacl_translator", "-filetype=obj" };
+ for (size_t i = 0; i < array_lengthof(common_args); ++i) {
+ command_line->push_back(common_args[i]);
+ }
+ // Then those particular to a platform.
+ static const char *llc_args_x8632[] = { "-mtriple=i686-none-nacl-gnu", NULL };
+ static const char *llc_args_x8664[] = { "-mtriple=x86_64-none-nacl-gnu",
+ NULL };
+ static const char *llc_args_arm[] = {
+ "-mtriple=armv7a-none-nacl-gnueabi", "-mattr=+neon",
+ "-float-abi=hard", NULL
+ };
+
+ const char **llc_args = NULL;
+#if defined(__pnacl__)
+ switch (__builtin_nacl_target_arch()) {
+ case PnaclTargetArchitectureX86_32: {
+ llc_args = llc_args_x8632;
+ break;
+ }
+ case PnaclTargetArchitectureX86_64: {
+ llc_args = llc_args_x8664;
+ break;
+ }
+ case PnaclTargetArchitectureARM_32: {
+ llc_args = llc_args_arm;
+ break;
+ }
+ default:
+ fprintf(stderr, "no target architecture match.\n");
+ delete command_line;
+ return NULL;
+ }
+// Some cases for building this with nacl-gcc.
+#elif defined(__i386__)
+ (void)llc_args_x8664;
+ (void)llc_args_arm;
+ llc_args = llc_args_x8632;
+#elif defined(__x86_64__)
+ (void)llc_args_x8632;
+ (void)llc_args_arm;
+ llc_args = llc_args_x8664;
+#elif defined(__arm__)
+ (void)llc_args_x8632;
+ (void)llc_args_x8664;
+ llc_args = llc_args_arm;
+#else
+#error "Unknown architecture"
+#endif
+ for (size_t i = 0; llc_args[i] != NULL; i++)
+ command_line->push_back(llc_args[i]);
+ return command_line;
+}
+
+// Data passed from main thread to compile thread.
+// Takes ownership of the commandline vector.
+class StreamingThreadData {
+public:
+ StreamingThreadData(int module_count, ArgStringList *cmd_line_vec)
+ : module_count_(module_count), cmd_line_vec_(cmd_line_vec) {}
+ ArgStringList *CmdLineVec() const { return cmd_line_vec_.get(); }
+ int module_count_;
+ const std::unique_ptr<ArgStringList> cmd_line_vec_;
+};
+
+void *run_streamed(void *arg) {
+ StreamingThreadData *data = reinterpret_cast<StreamingThreadData *>(arg);
+ data->CmdLineVec()->push_back("-streaming-bitcode");
+ if (DoTranslate(data->CmdLineVec()) != 0) {
+ // llc_main only returns 1 (as opposed to calling report_fatal_error)
+ // in conditions we never expect to see in the browser (e.g. bad
+ // command-line flags).
+ srpc_streamer->setFatalError("llc_main unspecified failure");
+ return NULL;
+ }
+ delete data;
+ return NULL;
+}
+
+// Actually do the work for stream initialization.
+void do_stream_init(NaClSrpcRpc *rpc, NaClSrpcArg **out_args,
+ NaClSrpcClosure *done, StreamingThreadData* thread_data) {
+ NaClSrpcClosureRunner runner(done);
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR;
+ srpc_streamer = new SRPCStreamer();
+ std::string StrError;
+
+ NaClBitcodeStreamer = srpc_streamer->init(
+ run_streamed, reinterpret_cast<void *>(thread_data), &StrError);
+ if (NaClBitcodeStreamer) {
+ rpc->result = NACL_SRPC_RESULT_OK;
+ out_args[0]->arrays.str = strdup("no error");
+ } else {
+ out_args[0]->arrays.str = strdup(StrError.c_str());
+ }
+}
+
+void stream_init_with_split(NaClSrpcRpc *rpc, NaClSrpcArg **in_args,
+ NaClSrpcArg **out_args, NaClSrpcClosure *done) {
+ ArgStringList *cmd_line_vec = GetDefaultCommandLine();
+ if (!cmd_line_vec) {
+ NaClSrpcClosureRunner runner(done);
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR;
+ out_args[0]->arrays.str = strdup("Failed to get default commandline.");
+ return;
+ }
+ AddFixedArguments(cmd_line_vec);
+
+ int num_modules = in_args[0]->u.ival;
+ if (num_modules < 1 || num_modules > kMaxModuleSplit) {
+ NaClSrpcClosureRunner runner(done);
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR;
+ out_args[0]->arrays.str = strdup("Invalid module split count.");
+ return;
+ }
+
+ StreamingThreadData *thread_data =
+ new StreamingThreadData(num_modules, cmd_line_vec);
+
+ for (int i = 1; i <= num_modules; i++) {
+ object_file_fd[i - 1] = in_args[i]->u.hval;
+ }
+
+ char *command_line = in_args[kMaxModuleSplit + 1]->arrays.carr;
+ size_t command_line_len = in_args[kMaxModuleSplit + 1]->u.count;
+ std::unique_ptr<ArgStringList> extra_vec(
+ CommandLineFromArgz(command_line, command_line_len));
+ cmd_line_vec->insert(cmd_line_vec->end(), extra_vec->begin(),
+ extra_vec->end());
+ // Make sure some -mcpu override exists for now to prevent
+ // auto-cpu feature detection from triggering instructions that
+ // we do not validate yet.
+ if (!HasCPUOverride(extra_vec.get())) {
+ AddDefaultCPU(cmd_line_vec);
+ }
+ extra_vec.reset(NULL);
+
+ // cmd_line_vec is freed by the translation thread in run_streamed.
+ do_stream_init(rpc, out_args, done, thread_data);
+}
+
+// Invoked by the StreamChunk RPC. Receives a chunk of the bitcode and
+// buffers it for later retrieval by the compilation thread.
+void stream_chunk(NaClSrpcRpc *rpc, NaClSrpcArg **in_args,
+ NaClSrpcArg **out_args, NaClSrpcClosure *done) {
+ NaClSrpcClosureRunner runner(done);
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR;
+ size_t len = in_args[0]->u.count;
+ unsigned char *bytes =
+ reinterpret_cast<unsigned char *>(in_args[0]->arrays.carr);
+ if (srpc_streamer->gotChunk(bytes, len) != len) {
+ return;
+ }
+ rpc->result = NACL_SRPC_RESULT_OK;
+}
+
+// Invoked by the StreamEnd RPC. Waits until the compilation finishes,
+// then returns. Returns an int indicating whether the bitcode is a
+// shared library, a string with the soname, a string with dependencies,
+// and a string which contains an error message if applicable.
+void stream_end(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, NaClSrpcArg **out_args,
+ NaClSrpcClosure *done) {
+ NaClSrpcClosureRunner runner(done);
+ // TODO(eliben): We don't really use shared libraries now. At some
+ // point this should be cleaned up from SRPC as well.
+ out_args[0]->u.ival = false;
+ out_args[1]->arrays.str = strdup("");
+ out_args[2]->arrays.str = strdup("");
+ rpc->result = NACL_SRPC_RESULT_APP_ERROR;
+ std::string StrError;
+ if (srpc_streamer->streamEnd(&StrError)) {
+ out_args[3]->arrays.str = strdup(StrError.c_str());
+ return;
+ }
+ // SRPC deletes the strings returned when the closure is invoked.
+ // Therefore we need to use strdup.
+ out_args[3]->arrays.str = strdup("");
+ rpc->result = NACL_SRPC_RESULT_OK;
+}
+
+const struct NaClSrpcHandlerDesc srpc_methods[] = {
+ // Protocol for streaming:
+ // StreamInitWithSplit(num_split, obj_fd x 16, cmdline_flags) -> error_str
+ // StreamChunk(data) +
+ // StreamEnd() -> (is_shared_lib,soname,dependencies,error_str)
+ { "StreamInitWithSplit:ihhhhhhhhhhhhhhhhC:s", stream_init_with_split },
+ { "StreamChunk:C:", stream_chunk },
+ { "StreamEnd::isss", stream_end },
+ { NULL, NULL },
+};
+
+} // namespace
+
+int getObjectFileFD(unsigned Index) {
+ assert(Index < kMaxModuleSplit);
+ return object_file_fd[Index];
+}
+
+DataStreamer *getNaClBitcodeStreamer() { return NaClBitcodeStreamer; }
+
+// Called from the compilation thread
+void FatalErrorHandler(void *user_data, const std::string& reason,
+ bool gen_crash_diag) {
+ srpc_streamer->setFatalError(reason);
+}
+
+fatal_error_handler_t getSRPCErrorHandler() { return FatalErrorHandler; }
+
+int srpc_main(int argc, char **argv) {
+ if (!NaClSrpcModuleInit()) {
+ return 1;
+ }
+
+ if (!NaClSrpcAcceptClientConnection(srpc_methods)) {
+ return 1;
+ }
+ NaClSrpcModuleFini();
+ return 0;
+}
+
+#endif // __native_client__
« no previous file with comments | « tools/pnacl-llc/pnacl-llc.cpp ('k') | tools/pnacl-thaw/CMakeLists.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698