Chromium Code Reviews| Index: src/IceBrowserCompileServer.cpp |
| diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..91782007ac9abf0dda4ec4d903b470737af1006a |
| --- /dev/null |
| +++ b/src/IceBrowserCompileServer.cpp |
| @@ -0,0 +1,161 @@ |
| +//===- 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" |
|
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
|
| + |
| +#include <argz.h> |
| +#include <cstring> |
| +#include <cstdlib> |
| +#include <thread> |
| + |
| +#include "llvm/Support/FileSystem.h" |
| +#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.
|
| +#include "llvm/Support/QueueStreamer.h" |
| + |
| +#include <irt.h> |
|
jvoung (off chromium)
2015/03/18 15:39:09
I moved these to be with the other <...> includes.
|
| +#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")); |
| + // 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 { |
| + &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 |