Chromium Code Reviews| Index: src/IceBrowserCompileServer.cpp |
| diff --git a/src/IceBrowserCompileServer.cpp b/src/IceBrowserCompileServer.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..911b491eff91564005b07ae6c48a0615bf2c3386 |
| --- /dev/null |
| +++ b/src/IceBrowserCompileServer.cpp |
| @@ -0,0 +1,165 @@ |
| +//===- 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.
|
| +// |
| +// 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 <argz.h> |
| +#include <cstring> |
| +#include <cstdlib> |
| +#include <irt.h> |
| +#include <irt_dev.h> |
| +#include <thread> |
| + |
| +#include "llvm/Support/QueueStreamer.h" |
| + |
| +#include "IceBrowserCompileServer.h" |
| + |
| +namespace Ice { |
| + |
| +// Create C wrappers around callback handlers for the IRT interface. |
| +namespace { |
| + |
| +BrowserCompileServer *gCompileServer; |
| +struct nacl_irt_private_pnacl_translator_compile gIRTFuncs; |
| + |
| +void getIRTInterfaces() { |
| + size_t QueryResult = |
| + nacl_interface_query(NACL_IRT_PRIVATE_PNACL_TRANSLATOR_COMPILE_v0_1, |
| + &gIRTFuncs, sizeof(gIRTFuncs)); |
| + if (QueryResult != sizeof(gIRTFuncs)) |
| + 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.
|
| +} |
| + |
| +int onInitCallback(uint32_t NumThreads, int *ObjFileFDs, size_t ObjFileFDCount, |
| + const char *CmdFlags, size_t CmdFlagsLen) { |
| + if (ObjFileFDCount < 1) { |
| + llvm::errs() << "Invalid number of FDs for onInitCallback " |
| + << ObjFileFDCount << "\n"; |
| + return 1; |
| + } |
| + int ObjFileFD = ObjFileFDs[0]; |
| + if (ObjFileFD < 0) { |
| + llvm::errs() << "Invalid number of FD given for onInitCallback " |
| + << ObjFileFD << "\n"; |
| + return 1; |
| + } |
| + // CmdFlags is a caller owned string, so we make copies. |
| + std::vector<char *> CmdFlagList; |
| + // Push some dummy argument for the program name to satisfy |
| + // the argument parser. |
| + CmdFlagList.push_back(strdup("pnacl-sz")); |
| + const char *NextEntry = CmdFlags; |
| + while (NextEntry != nullptr && CmdFlagsLen) { |
| + CmdFlagList.push_back(strdup(NextEntry)); |
| + // re: const cast -- the string pointed-to by each "NextEntry" is |
| + // only used temporarily by getParsedFlags(), and we make a |
| + // copy anyway. |
| + NextEntry = argz_next(const_cast<char *>(CmdFlags), CmdFlagsLen, NextEntry); |
| + } |
| + // Make an argv array from the CmdFlagList, parse and then free. |
| + 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->getParsedFlags(NumThreads, argc, argv); |
| + for (size_t i = 0; i < argc; ++i) |
| + free(argv[i]); |
| + delete[] argv; |
| + gCompileServer->startCompileThread(ObjFileFD); |
| + return 0; |
| +} |
| + |
| +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->getErrorCode().value(); |
| +} |
| + |
| +struct irt_pnacl_compile_funcs SubzeroCallbacks { |
| + &onInitCallback, &onDataCallback, &onEndCallback |
| +}; |
| + |
| +std::unique_ptr<llvm::raw_fd_ostream> getOutputStream(int FD) { |
| + if (FD <= 0) |
| + llvm::report_fatal_error("Invalid output FD"); |
| + const bool CloseOnDtor = true; |
| + const bool Unbuffered = false; |
| + return std::unique_ptr<llvm::raw_fd_ostream>( |
| + new llvm::raw_fd_ostream(FD, CloseOnDtor, Unbuffered)); |
| +} |
| + |
| +} // end of anonymous namespace |
| + |
| +BrowserCompileServer::~BrowserCompileServer() {} |
| + |
| +void BrowserCompileServer::run() { |
| + gCompileServer = this; |
| + // TODO(jvoung): make a useful fatal error handler that can |
| + // exit all *worker* threads, keep the server thread alive, |
| + // and be able to handle a server request for the last error string. |
| + getIRTInterfaces(); |
| + gIRTFuncs.serve_translate_request(&SubzeroCallbacks); |
| +} |
| + |
| +void BrowserCompileServer::getParsedFlags(uint32_t NumThreads, int argc, |
| + char **argv) { |
| + ClFlags::parseFlags(argc, argv); |
| + ClFlags::getParsedClFlags(Flags); |
| + ClFlags::getParsedClFlagsExtra(ExtraFlags); |
| + // Set some defaults which aren't specified via the argv string. |
| + Flags.setNumTranslationThreads(NumThreads); |
| + Flags.setUseSandboxing(true); |
| + Flags.setOutFileType(FT_Elf); |
| + // TODO(jvoung): allow setting different target arches. |
| + Flags.setTargetArch(Target_X8632); |
| + ExtraFlags.setBuildOnRead(true); |
| + ExtraFlags.setInputFileFormat(llvm::PNaClFormat); |
| +} |
| + |
| +bool BrowserCompileServer::pushInputBytes(unsigned char *Data, |
| + size_t NumBytes) { |
| + return InputStream->PutBytes(Data, NumBytes) != NumBytes; |
| +} |
| + |
| +void BrowserCompileServer::endInputStream() { InputStream->SetDone(); } |
| + |
| +void BrowserCompileServer::startCompileThread(int ObjFD) { |
| + InputStream = new llvm::QueueStreamer(); |
| + LogStream = getOutputStream(STDOUT_FILENO); |
| + LogStream->SetUnbuffered(); |
| + EmitStream = getOutputStream(ObjFD); |
| + EmitStream->SetBufferSize(1 << 14); |
| + ELFStream.reset(new ELFStreamer(*EmitStream.get())); |
| + Ctx.reset(new GlobalContext(LogStream.get(), EmitStream.get(), |
| + ELFStream.get(), Flags)); |
| + CompileThread = std::thread([this]() { |
| + Ctx->initParserThread(); |
| + this->getCompiler().run(ExtraFlags, *Ctx.get(), |
| + // Retain original reference, but the compiler |
| + // (LLVM's MemoryObject) wants to handle deletion. |
| + std::unique_ptr<llvm::DataStreamer>(InputStream)); |
| + }); |
| +} |
| + |
| +} // end of namespace Ice |
| + |
| +#endif // PNACL_BROWSER_TRANSLATOR |