IceCompileServer.cpp revision 57e126899b20c65ff3ea23a3b7d7a67ab30b99dc
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//===----------------------------------------------------------------------===// 99612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 109612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// \file 119612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// This file defines the basic commandline-based compile server. 129612d32c7e5eb2cb403686ef31172d42e075e460Andrew Scull/// 1344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung//===----------------------------------------------------------------------===// 1444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 1567f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceCompileServer.h" 1644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 1767f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlags.h" 1867f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceClFlagsExtra.h" 1967f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceELFStreamer.h" 2067f8de9adf6439881a00d8e0f081918436c71f62John Porto#include "IceGlobalContext.h" 2198da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth 2298da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic push 2398da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic ignored "-Wunused-parameter" 246f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" 2544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/FileSystem.h" 2644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/raw_os_ostream.h" 27b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung#include "llvm/Support/Signals.h" 2844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/SourceMgr.h" 2944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung#include "llvm/Support/StreamingMemoryObject.h" 3098da96678bc2705d4a37e17b87bbb3c031be9ae0Jim Stichnoth#pragma clang diagnostic pop 3144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3267f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <fstream> 3367f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <iostream> 3467f8de9adf6439881a00d8e0f081918436c71f62John Porto#include <thread> 3544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace Ice { 3744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 3844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungnamespace { 3944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 4057e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// Define a SmallVector backed buffer as a data stream, so that it can hold the 4157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull// generated binary version of the textual bitcode in the input file. 426f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfclass TextDataStreamer : public llvm::DataStreamer { 436f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfpublic: 446f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf TextDataStreamer() = default; 456f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf ~TextDataStreamer() final = default; 466f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf static TextDataStreamer *create(const IceString &Filename, std::string *Err); 476f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t GetBytes(unsigned char *Buf, size_t Len) final; 4820b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth 496f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfprivate: 506f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf llvm::SmallVector<char, 1024> BitcodeBuffer; 516f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t Cursor = 0; 526f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf}; 536f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 546f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl SchimpfTextDataStreamer *TextDataStreamer::create(const IceString &Filename, 556f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf std::string *Err) { 566f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf TextDataStreamer *Streamer = new TextDataStreamer(); 576f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf llvm::raw_string_ostream ErrStrm(*Err); 586f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode( 596f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Filename, Streamer->BitcodeBuffer, &ErrStrm)) { 60cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf ErrStrm << EC.message(); 616f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf ErrStrm.flush(); 626f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf delete Streamer; 636f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return nullptr; 646f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf } 65cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf ErrStrm.flush(); 666f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return Streamer; 676f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf} 686f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 696f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpfsize_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) { 706f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf if (Cursor >= BitcodeBuffer.size()) 716f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return 0; 726f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf size_t Remaining = BitcodeBuffer.size(); 736f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Len = std::min(Len, Remaining); 746f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf for (size_t i = 0; i < Len; ++i) 756f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Buf[i] = BitcodeBuffer[Cursor + i]; 766f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf Cursor += Len; 776f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf return Len; 786f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf} 796f9ba115f546d0e3446f08bd6f4477d2b5645bd5Karl Schimpf 80620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnothstd::unique_ptr<Ostream> makeStream(const IceString &Filename, 81620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::error_code &EC) { 82620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (Filename == "-") { 8344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout)); 84620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } else { 85620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth return std::unique_ptr<Ostream>( 86620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None)); 8744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 8844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 8944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 9044c3a8046f4c81f9b4476f8c3c72723b584c312dJan VoungErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) { 9144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (Flags.getAlwaysExitSuccess()) 9244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return EC_None; 9344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return Val; 9444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 9544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 9644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of anonymous namespace 9744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 9844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voungvoid CLCompileServer::run() { 9920b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth if (BuildDefs::dump()) { 100b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung llvm::sys::PrintStackTraceOnErrorSignal(); 101b2d5084c573ef5de15eb0e87bdde5dfba59e524aJan Voung } 10244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::parseFlags(argc, argv); 10344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags Flags; 10444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlagsExtra ExtraFlags; 10544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::getParsedClFlags(Flags); 10644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ClFlags::getParsedClFlagsExtra(ExtraFlags); 10744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 108620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::error_code EC; 109620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC); 110620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (EC) { 111620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth llvm::report_fatal_error("Unable to open log file"); 112620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } 11344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Ls->SetUnbuffered(); 11444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<Ostream> Os; 11544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<ELFStreamer> ELFStr; 11644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung switch (Flags.getOutFileType()) { 11744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Elf: { 11844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (ExtraFlags.getOutputFilename() == "-") { 11944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung *Ls << "Error: writing binary ELF to stdout is unsupported\n"; 12044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 12144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 12244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream( 12344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None)); 12444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (EC) { 12544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename() 12644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung << ":\n" << EC.message() << "\n"; 12744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 12844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 12944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ELFStr.reset(new ELFStreamer(*FdOs.get())); 13044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os.reset(FdOs.release()); 13157e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // NaCl sets st_blksize to 0, and LLVM uses that to pick the default 13257e126899b20c65ff3ea23a3b7d7a67ab30b99dcAndrew Scull // preferred buffer size. Set to something non-zero. 13344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os->SetBufferSize(1 << 14); 13444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } break; 13544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Asm: 13644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung case FT_Iasm: { 137620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth Os = makeStream(ExtraFlags.getOutputFilename(), EC); 138620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth if (EC) { 139620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename() 140620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth << ":\n" << EC.message() << "\n"; 141620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args)); 142620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth } 14344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Os->SetUnbuffered(); 14444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } break; 14544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 14644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 147cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf if (BuildDefs::minimal() && ExtraFlags.getBitcodeAsText()) 148cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf llvm::report_fatal_error("Can't specify 'bitcode-as-text' flag in " 149cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf "minimal build"); 150cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf 15144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung IceString StrError; 15244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::unique_ptr<llvm::DataStreamer> InputStream( 153cb6e95aac252a35c66705fb5e30d3c5e9ba4c1dcKarl Schimpf (!BuildDefs::minimal() && ExtraFlags.getBitcodeAsText()) 15420b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError) 15520b71f5890ee8651983b126c5978594a01e0af96Jim Stichnoth : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError)); 15644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (!StrError.empty() || !InputStream) { 15744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(), 15844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung llvm::SourceMgr::DK_Error, StrError); 15944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Err.print(ExtraFlags.getAppName().c_str(), *Ls); 16044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode)); 16144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 16244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 163620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth Ctx.reset( 164620ad732db0def93eee3928f9ebebe88b279f63dJim Stichnoth new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags)); 16544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung if (Ctx->getFlags().getNumTranslationThreads() != 0) { 16644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung std::thread CompileThread([this, &ExtraFlags, &InputStream]() { 16744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung Ctx->initParserThread(); 16844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream)); 16944c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung }); 17044c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung CompileThread.join(); 17144c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } else { 17244c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream)); 17344c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung } 17444c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung transferErrorCode(getReturnValue( 17544c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value()))); 17644c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} 17744c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung 17844c3a8046f4c81f9b4476f8c3c72723b584c312dJan Voung} // end of namespace Ice 179