IceCompileServer.cpp revision 67f8de9adf6439881a00d8e0f081918436c71f62
144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===- subzero/src/IceCompileServer.cpp - Compile server ------------------===// 244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// 344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// The Subzero Code Generator 444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// 544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// This file is distributed under the University of Illinois Open Source 644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// License. See LICENSE.TXT for details. 744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// 844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===// 944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// 1044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// This file defines the basic commandline-based compile server. 1144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung// 1244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===// 1344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 1467f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceCompileServer.h" 1544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 1667f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlags.h" 1767f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlagsExtra.h" 1867f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceELFStreamer.h" 1967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceGlobalContext.h" 206f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// Include code to handle converting textual bitcode records to binary (for 216f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// INPUT_IS_TEXTUAL_BITCODE). 226f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" 2344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/FileSystem.h" 2444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/raw_os_ostream.h" 25b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "llvm/Support/Signals.h" 2644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/SourceMgr.h" 2744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/StreamingMemoryObject.h" 2844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 2967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <fstream> 3067f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <iostream> 3167f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <thread> 3244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace Ice { 3444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace { 3644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3720b71f5890ee8651983b126c5978594a01e0af96Jim Stichnothstatic_assert(!(BuildDefs::textualBitcode() && PNACL_BROWSER_TRANSLATOR), 3820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth "Can not define INPUT_IS_TEXTUAL_BITCODE when building browswer " 3920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth "translator"); 406f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 416f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// Define a SmallVector backed buffer as a data stream, so that it 426f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// can hold the generated binary version of the textual bitcode in the 436f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf// input file. 446f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfclass TextDataStreamer : public llvm::DataStreamer { 456f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfpublic: 466f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf TextDataStreamer() = default; 476f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf ~TextDataStreamer() final = default; 486f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf static TextDataStreamer *create(const IceString &Filename, std::string *Err); 496f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t GetBytes(unsigned char *Buf, size_t Len) final; 5020b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth 516f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfprivate: 526f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf llvm::SmallVector<char, 1024> BitcodeBuffer; 536f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t Cursor = 0; 546f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}; 556f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 566f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl SchimpfTextDataStreamer *TextDataStreamer::create(const IceString &Filename, 576f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf std::string *Err) { 586f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf TextDataStreamer *Streamer = new TextDataStreamer(); 596f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf llvm::raw_string_ostream ErrStrm(*Err); 606f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode( 616f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Filename, Streamer->BitcodeBuffer, &ErrStrm)) { 6274cd883a0b3ccb0920e5990ed860b1862ac73090Karl Schimpf ErrStrm << EC.message(); // << "\n"; 636f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf ErrStrm.flush(); 646f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf delete Streamer; 656f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return nullptr; 666f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf } 6774cd883a0b3ccb0920e5990ed860b1862ac73090Karl Schimpf // ErrStrm.flush(); 686f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return Streamer; 696f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf} 706f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 716f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfsize_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) { 726f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf if (Cursor >= BitcodeBuffer.size()) 736f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return 0; 746f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t Remaining = BitcodeBuffer.size(); 756f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Len = std::min(Len, Remaining); 766f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf for (size_t i = 0; i < Len; ++i) 776f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Buf[i] = BitcodeBuffer[Cursor + i]; 786f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Cursor += Len; 796f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return Len; 806f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf} 816f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 82620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnothstd::unique_ptr<Ostream> makeStream(const IceString &Filename, 83620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::error_code &EC) { 84620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (Filename == "-") { 8544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout)); 86620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } else { 87620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth return std::unique_ptr<Ostream>( 88620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None)); 8944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 9044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 9144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 9244c3a8046f4c81f9b4476f8c3c72723b584c312dJan VoungErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) { 9344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (Flags.getAlwaysExitSuccess()) 9444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return EC_None; 9544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return Val; 9644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 9744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 9844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of anonymous namespace 9944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 10044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungvoid CLCompileServer::run() { 10120b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (BuildDefs::dump()) { 102b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung llvm::sys::PrintStackTraceOnErrorSignal(); 103b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 10444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::parseFlags(argc, argv); 10544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags Flags; 10644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlagsExtra ExtraFlags; 10744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::getParsedClFlags(Flags); 10844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::getParsedClFlagsExtra(ExtraFlags); 10944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 110620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::error_code EC; 111620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC); 112620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (EC) { 113620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth llvm::report_fatal_error("Unable to open log file"); 114620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } 11544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Ls->SetUnbuffered(); 11644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<Ostream> Os; 11744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<ELFStreamer> ELFStr; 11844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung switch (Flags.getOutFileType()) { 11944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Elf: { 12044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (ExtraFlags.getOutputFilename() == "-") { 12144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung *Ls << "Error: writing binary ELF to stdout is unsupported\n"; 12244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 12344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 12444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream( 12544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None)); 12644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (EC) { 12744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename() 12844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung << ":\n" << EC.message() << "\n"; 12944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 13044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 13144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ELFStr.reset(new ELFStreamer(*FdOs.get())); 13244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os.reset(FdOs.release()); 13344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung // NaCl sets st_blksize to 0, and LLVM uses that to pick the 13444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung // default preferred buffer size. Set to something non-zero. 13544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os->SetBufferSize(1 << 14); 13644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } break; 13744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Asm: 13844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Iasm: { 139620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth Os = makeStream(ExtraFlags.getOutputFilename(), EC); 140620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (EC) { 141620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename() 142620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth << ":\n" << EC.message() << "\n"; 143620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 144620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } 14544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os->SetUnbuffered(); 14644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } break; 14744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 14844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 14944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung IceString StrError; 15044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<llvm::DataStreamer> InputStream( 15120b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth BuildDefs::textualBitcode() 15220b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError) 15320b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError)); 15444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (!StrError.empty() || !InputStream) { 15544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(), 15644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung llvm::SourceMgr::DK_Error, StrError); 15744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Err.print(ExtraFlags.getAppName().c_str(), *Ls); 15844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode)); 15944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 16044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 161620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth Ctx.reset( 162620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags)); 16344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (Ctx->getFlags().getNumTranslationThreads() != 0) { 16444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::thread CompileThread([this, &ExtraFlags, &InputStream]() { 16544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Ctx->initParserThread(); 16644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream)); 16744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung }); 16844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung CompileThread.join(); 16944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } else { 17044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream)); 17144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 17244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung transferErrorCode(getReturnValue( 17344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value()))); 17444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 17544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 17644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of namespace Ice 177