OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/IceBrowserCompileServer.cpp - Browser Compile server ---===// | |
2 // | |
3 // The Subzero Code Generator | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // This file defines the browser-based compile server. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 // Can only compile this with the NaCl compiler (needs irt.h, and the | |
15 // unsandboxed LLVM build using the trusted compiler does not have irt.h). | |
16 #if PNACL_BROWSER_TRANSLATOR | |
17 | |
18 #include "IceBrowserCompileServer.h" | |
Jim Stichnoth
2015/03/13 04:55:00
Move after llvm/ includes?
jvoung (off chromium)
2015/03/18 15:39:09
Done.
Oops, I got mixed up with some other coding
| |
19 | |
20 #include <argz.h> | |
21 #include <cstring> | |
22 #include <cstdlib> | |
23 #include <thread> | |
24 | |
25 #include "llvm/Support/FileSystem.h" | |
26 #include "llvm/Support/raw_os_ostream.h" | |
Jim Stichnoth
2015/03/13 04:55:00
sort these includes
jvoung (off chromium)
2015/03/18 15:39:09
Done.
| |
27 #include "llvm/Support/QueueStreamer.h" | |
28 | |
29 #include <irt.h> | |
jvoung (off chromium)
2015/03/18 15:39:09
I moved these to be with the other <...> includes.
| |
30 #include <irt_dev.h> | |
31 | |
32 namespace Ice { | |
33 | |
34 // Create C wrappers around callback handlers for the IRT interface. | |
35 namespace { | |
36 | |
37 struct nacl_irt_private_pnacl_translator_subzero gIRTTranslatorSubzero; | |
38 BrowserCompileServer *gCompileServer; | |
39 | |
40 void getIRTInterfaces() { | |
41 size_t query_result = nacl_interface_query( | |
42 NACL_IRT_PRIVATE_PNACL_TRANSLATOR_SUBZERO_v0_1, &gIRTTranslatorSubzero, | |
43 sizeof(gIRTTranslatorSubzero)); | |
44 if (query_result != sizeof(gIRTTranslatorSubzero)) | |
45 llvm::report_fatal_error("Failed to get translator_subzero IRT interface"); | |
46 } | |
47 | |
48 int onInitCallback(uint32_t NumThreads, int ObjFileFD, const char *CmdFlags, | |
49 size_t CmdFlagsLen) { | |
50 (void)NumThreads; | |
51 std::vector<char *> CmdFlagList; | |
52 // Push some dummy arguments for the program name, input file, and | |
53 // output file to satisfy the argument parser and the sanity checks | |
54 // (e.g., never write ELF binary to stdout). | |
55 // We also always do binary output, so set that as the default. | |
56 CmdFlagList.push_back(strdup("pnacl-sz")); | |
57 CmdFlagList.push_back(strdup("browser_input.pexe")); | |
58 CmdFlagList.push_back(strdup("-o=browser_output.o")); | |
59 CmdFlagList.push_back(strdup("-filetype=obj")); | |
60 // TODO(jvoung): Make sure we don't send unnecessary arguments | |
61 // like -split-module=N. | |
62 IceString ThreadStrBuffer; | |
63 llvm::raw_string_ostream ThreadStr(ThreadStrBuffer); | |
64 ThreadStr << "-threads=" << NumThreads; | |
65 CmdFlagList.push_back(strdup(ThreadStr.str().c_str())); | |
66 const char *NextEntry = CmdFlags; | |
67 while (NextEntry != nullptr && CmdFlagsLen) { | |
68 // Make a copy of each null-terminated segment, since the | |
69 // incoming string is owned by the caller. | |
70 CmdFlagList.push_back(strdup(NextEntry)); | |
71 // re: const cast -- the string pointed-to by each "NextEntry" is | |
72 // ultimately strdup'ed so the original won't be modified. | |
73 NextEntry = argz_next(const_cast<char *>(CmdFlags), CmdFlagsLen, NextEntry); | |
74 } | |
75 // Make an argv array from the input vector. | |
76 size_t argc = CmdFlagList.size(); | |
77 char **argv = new char *[argc + 1]; | |
78 for (size_t i = 0; i < argc; ++i) { | |
79 argv[i] = CmdFlagList[i]; | |
80 } | |
81 argv[argc] = nullptr; | |
82 gCompileServer->takeArgs(static_cast<int>(argc), argv); | |
83 gCompileServer->setOutputFD(ObjFileFD); | |
84 gCompileServer->startCompileThread(); | |
85 return gCompileServer->getReturnValue(); | |
86 } | |
87 | |
88 int onDataCallback(unsigned char *Data, size_t NumBytes) { | |
89 return gCompileServer->pushInputBytes(Data, NumBytes) ? 1 : 0; | |
90 } | |
91 | |
92 int onEndCallback() { | |
93 gCompileServer->endInputStream(); | |
94 gCompileServer->waitForCompileThread(); | |
95 // TODO(jvoung): Also return an error string, and UMA data. | |
96 // Set up a report_fatal_error handler to grab that string. | |
97 return gCompileServer->getReturnValue(); | |
98 } | |
99 | |
100 struct PNaClSubzeroFunctions SubzeroCallbacks { | |
101 &onInitCallback, &onDataCallback, &onEndCallback | |
102 }; | |
103 | |
104 } // end of anonymous namespace | |
105 | |
106 BrowserCompileServer::~BrowserCompileServer() { | |
107 // strings were strdup'ed so free instead of delete. | |
108 for (int i = 0; i < argc; ++i) | |
109 free(argv[i]); | |
110 delete[] argv; | |
111 } | |
112 | |
113 void BrowserCompileServer::run() { | |
114 gCompileServer = this; | |
115 getIRTInterfaces(); | |
116 gIRTTranslatorSubzero.serve_translate_request(&SubzeroCallbacks); | |
117 } | |
118 | |
119 std::unique_ptr<llvm::DataStreamer> | |
120 BrowserCompileServer::getInputStream(const IceString &InputFilename, | |
121 std::string &ErrorString) { | |
122 // There is no real filename / and there should be no error. | |
123 (void)InputFilename; | |
124 (void)ErrorString; | |
125 std::unique_ptr<llvm::QueueStreamer> Result(new llvm::QueueStreamer()); | |
126 InputStream = Result.get(); | |
127 return std::move(Result); | |
128 } | |
129 | |
130 std::unique_ptr<llvm::raw_fd_ostream> | |
131 BrowserCompileServer::getOutputStream(const IceString &OutputFilename, | |
132 std::error_code &EC) { | |
133 // There is no real filename / and there should be no error | |
134 // since the fd is already opened. | |
135 (void)OutputFilename; | |
136 (void)EC; | |
137 if (OutputFD <= 0) | |
138 llvm::report_fatal_error("Invalid output FD"); | |
139 const bool CloseOnDtor = true; | |
140 const bool Unbuffered = false; | |
141 std::unique_ptr<llvm::raw_fd_ostream> Result( | |
142 new llvm::raw_fd_ostream(OutputFD, CloseOnDtor, Unbuffered)); | |
143 OutputFD = -1; | |
144 return std::move(Result); | |
145 } | |
146 | |
147 bool BrowserCompileServer::pushInputBytes(unsigned char *Data, | |
148 size_t NumBytes) { | |
149 return InputStream->PutBytes(Data, NumBytes) != NumBytes; | |
150 } | |
151 | |
152 void BrowserCompileServer::endInputStream() { return InputStream->SetDone(); } | |
153 | |
154 void BrowserCompileServer::startCompileThread() { | |
155 CompileThread = | |
156 std::thread([this]() { this->getCompiler().run(argc, argv, *this); }); | |
157 } | |
158 | |
159 } // end of namespace Ice | |
160 | |
161 #endif // PNACL_BROWSER_TRANSLATOR | |
OLD | NEW |