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

Side by Side Diff: tools/pnacl-llc/srpc_main.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===-- srpc_main.cpp - PNaCl sandboxed translator invocation -------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Main invocation of the sandboxed translator through SRPC.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #if defined(PNACL_BROWSER_TRANSLATOR)
15
16 // Headers which are not properly part of the SDK are included by their
17 // path in the NaCl tree.
18 #include "native_client/src/shared/srpc/nacl_srpc.h"
19 #ifdef __pnacl__
20 #include "native_client/src/untrusted/nacl/pnacl.h"
21 #endif // __pnacl__
22
23 #include "SRPCStreamer.h"
24
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/Option/Option.h"
27 #include "llvm/Support/ErrorHandling.h"
28
29 #include <argz.h>
30 #include <cstdio>
31 #include <cstdlib>
32 #include <cstring>
33 #include <string>
34
35 using namespace llvm;
36 using namespace llvm::opt;
37 using std::string;
38
39 // Imported from pnacl-llc.cpp
40 extern int llc_main(int argc, char **argv);
41
42 namespace {
43
44 // The filename used internally for looking up the bitcode file.
45 const char kBitcodeFilename[] = "pnacl.pexe";
46 // The filename used internally for looking up the object code file.
47 const char kObjectFilename[] = "pnacl.o";
48 // Maximum number of modules supported for splitting. Can't be changed without
49 // also changing the SRPC signature for StreamInitWithSplit
50 const int kMaxModuleSplit = 16;
51 // Object which manages streaming bitcode over SRPC and threading.
52 SRPCStreamer *srpc_streamer;
53 // FDs of the object file(s).
54 int object_file_fd[kMaxModuleSplit];
55
56 DataStreamer *NaClBitcodeStreamer;
57
58 int DoTranslate(ArgStringList *CmdLineArgs) {
59 if (CmdLineArgs == NULL) {
60 return 1;
61 }
62 // Make an argv array from the input vector.
63 size_t argc = CmdLineArgs->size();
64 char **argv = new char *[argc + 1];
65 for (size_t i = 0; i < argc; ++i) {
66 // llc_main will not mutate the command line, so this is safe.
67 argv[i] = const_cast<char *>((*CmdLineArgs)[i]);
68 }
69 argv[argc] = NULL;
70 // Call main.
71 return llc_main(static_cast<int>(argc), argv);
72 }
73
74 ArgStringList *CommandLineFromArgz(char *str, size_t str_len) {
75 char *entry = str;
76 ArgStringList *CmdLineArgs = new ArgStringList;
77 while (entry != NULL && str_len) {
78 // Call strdup(entry) since the str argument will ultimately be
79 // freed by the SRPC message sender.
80 CmdLineArgs->push_back(strdup(entry));
81 entry = argz_next(str, str_len, entry);
82 }
83 return CmdLineArgs;
84 }
85
86 void AddFixedArguments(ArgStringList *CmdLineArgs) {
87 // Add fixed arguments to the command line. These specify the bitcode
88 // and object code filenames, removing them from the contract with the
89 // coordinator.
90 CmdLineArgs->push_back(kBitcodeFilename);
91 CmdLineArgs->push_back("-o");
92 CmdLineArgs->push_back(kObjectFilename);
93 }
94
95 bool AddDefaultCPU(ArgStringList *CmdLineArgs) {
96 #if defined(__pnacl__)
97 switch (__builtin_nacl_target_arch()) {
98 case PnaclTargetArchitectureX86_32: {
99 CmdLineArgs->push_back("-mcpu=pentium4m");
100 break;
101 }
102 case PnaclTargetArchitectureX86_64: {
103 CmdLineArgs->push_back("-mcpu=x86-64");
104 break;
105 }
106 case PnaclTargetArchitectureARM_32: {
107 CmdLineArgs->push_back("-mcpu=cortex-a9");
108 break;
109 }
110 default:
111 fprintf(stderr, "no target architecture match.\n");
112 return false;
113 }
114 // Some cases for building this with nacl-gcc.
115 #elif defined(__i386__)
116 CmdLineArgs->push_back("-mcpu=pentium4m");
117 #elif defined(__x86_64__)
118 CmdLineArgs->push_back("-mcpu=x86-64");
119 #elif defined(__arm__)
120 CmdLineArgs->push_back("-mcpu=cortex-a9");
121 #else
122 #error "Unknown architecture"
123 #endif
124 return true;
125 }
126
127 bool HasCPUOverride(ArgStringList *CmdLineArgs) {
128 const char *Mcpu = "-mcpu";
129 size_t McpuLen = strlen(Mcpu);
130 for (size_t i = 0; i < CmdLineArgs->size(); ++i) {
131 if (strncmp((*CmdLineArgs)[i], Mcpu, McpuLen) == 0) {
132 return true;
133 }
134 }
135 return false;
136 }
137
138 ArgStringList *GetDefaultCommandLine() {
139 ArgStringList *command_line = new ArgStringList;
140 // First, those common to all architectures.
141 static const char *common_args[] = { "pnacl_translator", "-filetype=obj" };
142 for (size_t i = 0; i < array_lengthof(common_args); ++i) {
143 command_line->push_back(common_args[i]);
144 }
145 // Then those particular to a platform.
146 static const char *llc_args_x8632[] = { "-mtriple=i686-none-nacl-gnu", NULL };
147 static const char *llc_args_x8664[] = { "-mtriple=x86_64-none-nacl-gnu",
148 NULL };
149 static const char *llc_args_arm[] = {
150 "-mtriple=armv7a-none-nacl-gnueabi", "-mattr=+neon",
151 "-float-abi=hard", NULL
152 };
153
154 const char **llc_args = NULL;
155 #if defined(__pnacl__)
156 switch (__builtin_nacl_target_arch()) {
157 case PnaclTargetArchitectureX86_32: {
158 llc_args = llc_args_x8632;
159 break;
160 }
161 case PnaclTargetArchitectureX86_64: {
162 llc_args = llc_args_x8664;
163 break;
164 }
165 case PnaclTargetArchitectureARM_32: {
166 llc_args = llc_args_arm;
167 break;
168 }
169 default:
170 fprintf(stderr, "no target architecture match.\n");
171 delete command_line;
172 return NULL;
173 }
174 // Some cases for building this with nacl-gcc.
175 #elif defined(__i386__)
176 (void)llc_args_x8664;
177 (void)llc_args_arm;
178 llc_args = llc_args_x8632;
179 #elif defined(__x86_64__)
180 (void)llc_args_x8632;
181 (void)llc_args_arm;
182 llc_args = llc_args_x8664;
183 #elif defined(__arm__)
184 (void)llc_args_x8632;
185 (void)llc_args_x8664;
186 llc_args = llc_args_arm;
187 #else
188 #error "Unknown architecture"
189 #endif
190 for (size_t i = 0; llc_args[i] != NULL; i++)
191 command_line->push_back(llc_args[i]);
192 return command_line;
193 }
194
195 // Data passed from main thread to compile thread.
196 // Takes ownership of the commandline vector.
197 class StreamingThreadData {
198 public:
199 StreamingThreadData(int module_count, ArgStringList *cmd_line_vec)
200 : module_count_(module_count), cmd_line_vec_(cmd_line_vec) {}
201 ArgStringList *CmdLineVec() const { return cmd_line_vec_.get(); }
202 int module_count_;
203 const std::unique_ptr<ArgStringList> cmd_line_vec_;
204 };
205
206 void *run_streamed(void *arg) {
207 StreamingThreadData *data = reinterpret_cast<StreamingThreadData *>(arg);
208 data->CmdLineVec()->push_back("-streaming-bitcode");
209 if (DoTranslate(data->CmdLineVec()) != 0) {
210 // llc_main only returns 1 (as opposed to calling report_fatal_error)
211 // in conditions we never expect to see in the browser (e.g. bad
212 // command-line flags).
213 srpc_streamer->setFatalError("llc_main unspecified failure");
214 return NULL;
215 }
216 delete data;
217 return NULL;
218 }
219
220 // Actually do the work for stream initialization.
221 void do_stream_init(NaClSrpcRpc *rpc, NaClSrpcArg **out_args,
222 NaClSrpcClosure *done, StreamingThreadData* thread_data) {
223 NaClSrpcClosureRunner runner(done);
224 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
225 srpc_streamer = new SRPCStreamer();
226 std::string StrError;
227
228 NaClBitcodeStreamer = srpc_streamer->init(
229 run_streamed, reinterpret_cast<void *>(thread_data), &StrError);
230 if (NaClBitcodeStreamer) {
231 rpc->result = NACL_SRPC_RESULT_OK;
232 out_args[0]->arrays.str = strdup("no error");
233 } else {
234 out_args[0]->arrays.str = strdup(StrError.c_str());
235 }
236 }
237
238 void stream_init_with_split(NaClSrpcRpc *rpc, NaClSrpcArg **in_args,
239 NaClSrpcArg **out_args, NaClSrpcClosure *done) {
240 ArgStringList *cmd_line_vec = GetDefaultCommandLine();
241 if (!cmd_line_vec) {
242 NaClSrpcClosureRunner runner(done);
243 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
244 out_args[0]->arrays.str = strdup("Failed to get default commandline.");
245 return;
246 }
247 AddFixedArguments(cmd_line_vec);
248
249 int num_modules = in_args[0]->u.ival;
250 if (num_modules < 1 || num_modules > kMaxModuleSplit) {
251 NaClSrpcClosureRunner runner(done);
252 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
253 out_args[0]->arrays.str = strdup("Invalid module split count.");
254 return;
255 }
256
257 StreamingThreadData *thread_data =
258 new StreamingThreadData(num_modules, cmd_line_vec);
259
260 for (int i = 1; i <= num_modules; i++) {
261 object_file_fd[i - 1] = in_args[i]->u.hval;
262 }
263
264 char *command_line = in_args[kMaxModuleSplit + 1]->arrays.carr;
265 size_t command_line_len = in_args[kMaxModuleSplit + 1]->u.count;
266 std::unique_ptr<ArgStringList> extra_vec(
267 CommandLineFromArgz(command_line, command_line_len));
268 cmd_line_vec->insert(cmd_line_vec->end(), extra_vec->begin(),
269 extra_vec->end());
270 // Make sure some -mcpu override exists for now to prevent
271 // auto-cpu feature detection from triggering instructions that
272 // we do not validate yet.
273 if (!HasCPUOverride(extra_vec.get())) {
274 AddDefaultCPU(cmd_line_vec);
275 }
276 extra_vec.reset(NULL);
277
278 // cmd_line_vec is freed by the translation thread in run_streamed.
279 do_stream_init(rpc, out_args, done, thread_data);
280 }
281
282 // Invoked by the StreamChunk RPC. Receives a chunk of the bitcode and
283 // buffers it for later retrieval by the compilation thread.
284 void stream_chunk(NaClSrpcRpc *rpc, NaClSrpcArg **in_args,
285 NaClSrpcArg **out_args, NaClSrpcClosure *done) {
286 NaClSrpcClosureRunner runner(done);
287 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
288 size_t len = in_args[0]->u.count;
289 unsigned char *bytes =
290 reinterpret_cast<unsigned char *>(in_args[0]->arrays.carr);
291 if (srpc_streamer->gotChunk(bytes, len) != len) {
292 return;
293 }
294 rpc->result = NACL_SRPC_RESULT_OK;
295 }
296
297 // Invoked by the StreamEnd RPC. Waits until the compilation finishes,
298 // then returns. Returns an int indicating whether the bitcode is a
299 // shared library, a string with the soname, a string with dependencies,
300 // and a string which contains an error message if applicable.
301 void stream_end(NaClSrpcRpc *rpc, NaClSrpcArg **in_args, NaClSrpcArg **out_args,
302 NaClSrpcClosure *done) {
303 NaClSrpcClosureRunner runner(done);
304 // TODO(eliben): We don't really use shared libraries now. At some
305 // point this should be cleaned up from SRPC as well.
306 out_args[0]->u.ival = false;
307 out_args[1]->arrays.str = strdup("");
308 out_args[2]->arrays.str = strdup("");
309 rpc->result = NACL_SRPC_RESULT_APP_ERROR;
310 std::string StrError;
311 if (srpc_streamer->streamEnd(&StrError)) {
312 out_args[3]->arrays.str = strdup(StrError.c_str());
313 return;
314 }
315 // SRPC deletes the strings returned when the closure is invoked.
316 // Therefore we need to use strdup.
317 out_args[3]->arrays.str = strdup("");
318 rpc->result = NACL_SRPC_RESULT_OK;
319 }
320
321 const struct NaClSrpcHandlerDesc srpc_methods[] = {
322 // Protocol for streaming:
323 // StreamInitWithSplit(num_split, obj_fd x 16, cmdline_flags) -> error_str
324 // StreamChunk(data) +
325 // StreamEnd() -> (is_shared_lib,soname,dependencies,error_str)
326 { "StreamInitWithSplit:ihhhhhhhhhhhhhhhhC:s", stream_init_with_split },
327 { "StreamChunk:C:", stream_chunk },
328 { "StreamEnd::isss", stream_end },
329 { NULL, NULL },
330 };
331
332 } // namespace
333
334 int getObjectFileFD(unsigned Index) {
335 assert(Index < kMaxModuleSplit);
336 return object_file_fd[Index];
337 }
338
339 DataStreamer *getNaClBitcodeStreamer() { return NaClBitcodeStreamer; }
340
341 // Called from the compilation thread
342 void FatalErrorHandler(void *user_data, const std::string& reason,
343 bool gen_crash_diag) {
344 srpc_streamer->setFatalError(reason);
345 }
346
347 fatal_error_handler_t getSRPCErrorHandler() { return FatalErrorHandler; }
348
349 int srpc_main(int argc, char **argv) {
350 if (!NaClSrpcModuleInit()) {
351 return 1;
352 }
353
354 if (!NaClSrpcAcceptClientConnection(srpc_methods)) {
355 return 1;
356 }
357 NaClSrpcModuleFini();
358 return 0;
359 }
360
361 #endif // __native_client__
OLDNEW
« 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