OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/IceBrowserCompileServer.cpp - Browser Compile server ---===// | |
Jim Stichnoth
2015/03/25 16:34:06
lowercase compile?
jvoung (off chromium)
2015/03/25 18:14:35
Done.
| |
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 <argz.h> | |
19 #include <cstring> | |
20 #include <cstdlib> | |
21 #include <irt.h> | |
22 #include <irt_dev.h> | |
23 #include <thread> | |
24 | |
25 #include "llvm/Support/QueueStreamer.h" | |
26 | |
27 #include "IceBrowserCompileServer.h" | |
28 | |
29 namespace Ice { | |
30 | |
31 // Create C wrappers around callback handlers for the IRT interface. | |
32 namespace { | |
33 | |
34 BrowserCompileServer *gCompileServer; | |
35 struct nacl_irt_private_pnacl_translator_compile gIRTFuncs; | |
36 | |
37 void getIRTInterfaces() { | |
38 size_t QueryResult = | |
39 nacl_interface_query(NACL_IRT_PRIVATE_PNACL_TRANSLATOR_COMPILE_v0_1, | |
40 &gIRTFuncs, sizeof(gIRTFuncs)); | |
41 if (QueryResult != sizeof(gIRTFuncs)) | |
42 llvm::report_fatal_error("Failed to get translator_subzero IRT interface"); | |
Jim Stichnoth
2015/03/25 16:34:06
Is "translator_subzero" still an accurate descript
jvoung (off chromium)
2015/03/25 18:14:35
Done.
| |
43 } | |
44 | |
45 int onInitCallback(uint32_t NumThreads, int *ObjFileFDs, size_t ObjFileFDCount, | |
46 const char *CmdFlags, size_t CmdFlagsLen) { | |
47 if (ObjFileFDCount < 1) { | |
48 llvm::errs() << "Invalid number of FDs for onInitCallback " | |
49 << ObjFileFDCount << "\n"; | |
50 return 1; | |
51 } | |
52 int ObjFileFD = ObjFileFDs[0]; | |
53 if (ObjFileFD < 0) { | |
54 llvm::errs() << "Invalid number of FD given for onInitCallback " | |
55 << ObjFileFD << "\n"; | |
56 return 1; | |
57 } | |
58 // CmdFlags is a caller owned string, so we make copies. | |
59 std::vector<char *> CmdFlagList; | |
60 // Push some dummy argument for the program name to satisfy | |
61 // the argument parser. | |
62 CmdFlagList.push_back(strdup("pnacl-sz")); | |
63 const char *NextEntry = CmdFlags; | |
64 while (NextEntry != nullptr && CmdFlagsLen) { | |
65 CmdFlagList.push_back(strdup(NextEntry)); | |
66 // re: const cast -- the string pointed-to by each "NextEntry" is | |
67 // only used temporarily by getParsedFlags(), and we make a | |
68 // copy anyway. | |
69 NextEntry = argz_next(const_cast<char *>(CmdFlags), CmdFlagsLen, NextEntry); | |
70 } | |
71 // Make an argv array from the CmdFlagList, parse and then free. | |
72 size_t argc = CmdFlagList.size(); | |
73 char **argv = new char *[argc + 1]; | |
74 for (size_t i = 0; i < argc; ++i) | |
75 argv[i] = CmdFlagList[i]; | |
76 argv[argc] = nullptr; | |
77 gCompileServer->getParsedFlags(NumThreads, argc, argv); | |
78 for (size_t i = 0; i < argc; ++i) | |
79 free(argv[i]); | |
80 delete[] argv; | |
81 gCompileServer->startCompileThread(ObjFileFD); | |
82 return 0; | |
83 } | |
84 | |
85 int onDataCallback(unsigned char *Data, size_t NumBytes) { | |
86 return gCompileServer->pushInputBytes(Data, NumBytes) ? 1 : 0; | |
87 } | |
88 | |
89 int onEndCallback() { | |
90 gCompileServer->endInputStream(); | |
91 gCompileServer->waitForCompileThread(); | |
92 // TODO(jvoung): Also return an error string, and UMA data. | |
93 // Set up a report_fatal_error handler to grab that string. | |
94 return gCompileServer->getErrorCode().value(); | |
95 } | |
96 | |
97 struct irt_pnacl_compile_funcs SubzeroCallbacks { | |
98 &onInitCallback, &onDataCallback, &onEndCallback | |
99 }; | |
100 | |
101 std::unique_ptr<llvm::raw_fd_ostream> getOutputStream(int FD) { | |
102 if (FD <= 0) | |
103 llvm::report_fatal_error("Invalid output FD"); | |
104 const bool CloseOnDtor = true; | |
105 const bool Unbuffered = false; | |
106 return std::unique_ptr<llvm::raw_fd_ostream>( | |
107 new llvm::raw_fd_ostream(FD, CloseOnDtor, Unbuffered)); | |
108 } | |
109 | |
110 } // end of anonymous namespace | |
111 | |
112 BrowserCompileServer::~BrowserCompileServer() {} | |
113 | |
114 void BrowserCompileServer::run() { | |
115 gCompileServer = this; | |
116 // TODO(jvoung): make a useful fatal error handler that can | |
117 // exit all *worker* threads, keep the server thread alive, | |
118 // and be able to handle a server request for the last error string. | |
119 getIRTInterfaces(); | |
120 gIRTFuncs.serve_translate_request(&SubzeroCallbacks); | |
121 } | |
122 | |
123 void BrowserCompileServer::getParsedFlags(uint32_t NumThreads, int argc, | |
124 char **argv) { | |
125 ClFlags::parseFlags(argc, argv); | |
126 ClFlags::getParsedClFlags(Flags); | |
127 ClFlags::getParsedClFlagsExtra(ExtraFlags); | |
128 // Set some defaults which aren't specified via the argv string. | |
129 Flags.setNumTranslationThreads(NumThreads); | |
130 Flags.setUseSandboxing(true); | |
131 Flags.setOutFileType(FT_Elf); | |
132 // TODO(jvoung): allow setting different target arches. | |
133 Flags.setTargetArch(Target_X8632); | |
134 ExtraFlags.setBuildOnRead(true); | |
135 ExtraFlags.setInputFileFormat(llvm::PNaClFormat); | |
136 } | |
137 | |
138 bool BrowserCompileServer::pushInputBytes(unsigned char *Data, | |
139 size_t NumBytes) { | |
140 return InputStream->PutBytes(Data, NumBytes) != NumBytes; | |
141 } | |
142 | |
143 void BrowserCompileServer::endInputStream() { InputStream->SetDone(); } | |
144 | |
145 void BrowserCompileServer::startCompileThread(int ObjFD) { | |
146 InputStream = new llvm::QueueStreamer(); | |
147 LogStream = getOutputStream(STDOUT_FILENO); | |
148 LogStream->SetUnbuffered(); | |
149 EmitStream = getOutputStream(ObjFD); | |
150 EmitStream->SetBufferSize(1 << 14); | |
151 ELFStream.reset(new ELFStreamer(*EmitStream.get())); | |
152 Ctx.reset(new GlobalContext(LogStream.get(), EmitStream.get(), | |
153 ELFStream.get(), Flags)); | |
154 CompileThread = std::thread([this]() { | |
155 Ctx->initParserThread(); | |
156 this->getCompiler().run(ExtraFlags, *Ctx.get(), | |
157 // Retain original reference, but the compiler | |
158 // (LLVM's MemoryObject) wants to handle deletion. | |
159 std::unique_ptr<llvm::DataStreamer>(InputStream)); | |
160 }); | |
161 } | |
162 | |
163 } // end of namespace Ice | |
164 | |
165 #endif // PNACL_BROWSER_TRANSLATOR | |
OLD | NEW |