Index: src/IceBrowserCompileServer.cpp |
diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c1f5c3f3898f3c1a9ece5ed9fdca02b6e10caaf6 |
--- /dev/null |
+++ b/src/IceBrowserCompileServer.cpp |
@@ -0,0 +1,162 @@ |
+//===- subzero/src/IceBrowserCompileServer.cpp - Browser Compile server ---===// |
+// |
+// The Subzero Code Generator |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This file defines the browser-based compile server. |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+// Can only compile this with the NaCl compiler (needs irt.h, and the |
+// unsandboxed LLVM build using the trusted compiler does not have irt.h). |
+#if PNACL_BROWSER_TRANSLATOR |
+ |
+#include "IceBrowserCompileServer.h" |
+ |
+#include <argz.h> |
+#include <cstring> |
+#include <cstdlib> |
+#include <thread> |
+ |
+#include "llvm/Support/FileSystem.h" |
+#include "llvm/Support/raw_os_ostream.h" |
+#include "llvm/Support/QueueStreamer.h" |
+ |
+#include <irt.h> |
+#include <irt_dev.h> |
+ |
+namespace Ice { |
+ |
+// Create C wrappers around callback handlers for the IRT interface. |
+namespace { |
+ |
+struct nacl_irt_private_pnacl_translator_subzero gIRTTranslatorSubzero; |
+BrowserCompileServer *gCompileServer; |
+ |
+void getIRTInterfaces() { |
+ size_t query_result = nacl_interface_query( |
+ NACL_IRT_PRIVATE_PNACL_TRANSLATOR_SUBZERO_v0_1, &gIRTTranslatorSubzero, |
+ sizeof(gIRTTranslatorSubzero)); |
+ if (query_result != sizeof(gIRTTranslatorSubzero)) |
+ llvm::report_fatal_error("Failed to get translator_subzero IRT interface"); |
+} |
+ |
+int onInitCallback(uint32_t NumThreads, int ObjFileFD, const char *CmdFlags, |
+ size_t CmdFlagsLen) { |
+ (void)NumThreads; |
+ std::vector<char *> CmdFlagList; |
+ // Push some dummy arguments for the program name, input file, and |
+ // output file to satisfy the argument parser and the sanity checks |
+ // (e.g., never write ELF binary to stdout). |
+ // We also always do binary output, so set that as the default. |
+ CmdFlagList.push_back(strdup("pnacl-sz")); |
+ CmdFlagList.push_back(strdup("browser_input.pexe")); |
+ CmdFlagList.push_back(strdup("-o=browser_output.o")); |
+ CmdFlagList.push_back(strdup("--filetype=obj")); |
+ CmdFlagList.push_back(strdup("--sandbox")); |
+ // TODO(jvoung): Make sure we don't send unnecessary arguments |
+ // like -split-module=N. |
+ IceString ThreadStrBuffer; |
+ llvm::raw_string_ostream ThreadStr(ThreadStrBuffer); |
+ ThreadStr << "-threads=" << NumThreads; |
+ CmdFlagList.push_back(strdup(ThreadStr.str().c_str())); |
+ const char *NextEntry = CmdFlags; |
+ while (NextEntry != nullptr && CmdFlagsLen) { |
+ // Make a copy of each null-terminated segment, since the |
+ // incoming string is owned by the caller. |
+ CmdFlagList.push_back(strdup(NextEntry)); |
+ // re: const cast -- the string pointed-to by each "NextEntry" is |
+ // ultimately strdup'ed so the original won't be modified. |
+ NextEntry = argz_next(const_cast<char *>(CmdFlags), CmdFlagsLen, NextEntry); |
+ } |
+ // Make an argv array from the input vector. |
+ size_t argc = CmdFlagList.size(); |
+ char **argv = new char *[argc + 1]; |
+ for (size_t i = 0; i < argc; ++i) { |
+ argv[i] = CmdFlagList[i]; |
+ } |
+ argv[argc] = nullptr; |
+ gCompileServer->takeArgs(static_cast<int>(argc), argv); |
+ gCompileServer->setOutputFD(ObjFileFD); |
+ gCompileServer->startCompileThread(); |
+ return gCompileServer->getReturnValue(); |
+} |
+ |
+int onDataCallback(unsigned char *Data, size_t NumBytes) { |
+ return gCompileServer->pushInputBytes(Data, NumBytes) ? 1 : 0; |
+} |
+ |
+int onEndCallback() { |
+ gCompileServer->endInputStream(); |
+ gCompileServer->waitForCompileThread(); |
+ // TODO(jvoung): Also return an error string, and UMA data. |
+ // Set up a report_fatal_error handler to grab that string. |
+ return gCompileServer->getReturnValue(); |
+} |
+ |
+struct PNaClSubzeroFunctions SubzeroCallbacks { |
Mircea Trofin
2015/03/13 22:01:34
are we still using the subzero name?
Jim Stichnoth
2015/03/14 02:31:05
Yeah, Subzero (maybe abbreviated sz) is the "offic
jvoung (off chromium)
2015/03/18 15:39:09
Acknowledged.
|
+ &onInitCallback, &onDataCallback, &onEndCallback |
+}; |
+ |
+} // end of anonymous namespace |
+ |
+BrowserCompileServer::~BrowserCompileServer() { |
+ // strings were strdup'ed so free instead of delete. |
+ for (int i = 0; i < argc; ++i) |
+ free(argv[i]); |
+ delete[] argv; |
+} |
+ |
+void BrowserCompileServer::run() { |
+ gCompileServer = this; |
+ getIRTInterfaces(); |
+ gIRTTranslatorSubzero.serve_translate_request(&SubzeroCallbacks); |
+} |
+ |
+std::unique_ptr<llvm::DataStreamer> |
+BrowserCompileServer::getInputStream(const IceString &InputFilename, |
+ std::string &ErrorString) { |
+ // There is no real filename / and there should be no error. |
+ (void)InputFilename; |
+ (void)ErrorString; |
+ std::unique_ptr<llvm::QueueStreamer> Result(new llvm::QueueStreamer()); |
+ InputStream = Result.get(); |
+ return std::move(Result); |
+} |
+ |
+std::unique_ptr<llvm::raw_fd_ostream> |
+BrowserCompileServer::getOutputStream(const IceString &OutputFilename, |
+ std::error_code &EC) { |
+ // There is no real filename / and there should be no error |
+ // since the fd is already opened. |
+ (void)OutputFilename; |
+ (void)EC; |
+ if (OutputFD <= 0) |
+ llvm::report_fatal_error("Invalid output FD"); |
+ const bool CloseOnDtor = true; |
+ const bool Unbuffered = false; |
+ std::unique_ptr<llvm::raw_fd_ostream> Result( |
+ new llvm::raw_fd_ostream(OutputFD, CloseOnDtor, Unbuffered)); |
+ OutputFD = -1; |
+ return std::move(Result); |
+} |
+ |
+bool BrowserCompileServer::pushInputBytes(unsigned char *Data, |
+ size_t NumBytes) { |
+ return InputStream->PutBytes(Data, NumBytes) != NumBytes; |
+} |
+ |
+void BrowserCompileServer::endInputStream() { return InputStream->SetDone(); } |
+ |
+void BrowserCompileServer::startCompileThread() { |
+ CompileThread = |
+ std::thread([this]() { this->getCompiler().run(argc, argv, *this); }); |
+} |
+ |
+} // end of namespace Ice |
+ |
+#endif // PNACL_BROWSER_TRANSLATOR |