Chromium Code Reviews| 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 |