blob: db0694b9556653f230c8af08b6271dd2baff9f69 [file] [log] [blame]
Jan Voung44c3a802015-03-27 16:29:08 -07001//===- subzero/src/IceCompileServer.cpp - Compile server ------------------===//
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//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
11/// This file defines the basic commandline-based compile server.
12///
Jan Voung44c3a802015-03-27 16:29:08 -070013//===----------------------------------------------------------------------===//
14
John Porto67f8de92015-06-25 10:14:17 -070015#include "IceCompileServer.h"
Jan Voung44c3a802015-03-27 16:29:08 -070016
John Porto67f8de92015-06-25 10:14:17 -070017#include "IceClFlags.h"
18#include "IceClFlagsExtra.h"
19#include "IceELFStreamer.h"
20#include "IceGlobalContext.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070021
22#pragma clang diagnostic push
23#pragma clang diagnostic ignored "-Wunused-parameter"
Karl Schimpf6f9ba112015-06-22 13:20:23 -070024#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h"
Jan Voung44c3a802015-03-27 16:29:08 -070025#include "llvm/Support/FileSystem.h"
26#include "llvm/Support/raw_os_ostream.h"
Jan Voungb2d50842015-05-12 09:53:50 -070027#include "llvm/Support/Signals.h"
Jan Voung44c3a802015-03-27 16:29:08 -070028#include "llvm/Support/SourceMgr.h"
29#include "llvm/Support/StreamingMemoryObject.h"
Jim Stichnoth98da9662015-06-27 06:38:08 -070030#pragma clang diagnostic pop
Jan Voung44c3a802015-03-27 16:29:08 -070031
John Porto67f8de92015-06-25 10:14:17 -070032#include <fstream>
33#include <iostream>
34#include <thread>
Jan Voung44c3a802015-03-27 16:29:08 -070035
36namespace Ice {
37
38namespace {
39
Andrew Scull57e12682015-09-16 11:30:19 -070040// Define a SmallVector backed buffer as a data stream, so that it can hold the
41// generated binary version of the textual bitcode in the input file.
Karl Schimpf6f9ba112015-06-22 13:20:23 -070042class TextDataStreamer : public llvm::DataStreamer {
43public:
44 TextDataStreamer() = default;
45 ~TextDataStreamer() final = default;
46 static TextDataStreamer *create(const IceString &Filename, std::string *Err);
47 size_t GetBytes(unsigned char *Buf, size_t Len) final;
Jim Stichnoth20b71f52015-06-24 15:52:24 -070048
Karl Schimpf6f9ba112015-06-22 13:20:23 -070049private:
50 llvm::SmallVector<char, 1024> BitcodeBuffer;
51 size_t Cursor = 0;
52};
53
54TextDataStreamer *TextDataStreamer::create(const IceString &Filename,
55 std::string *Err) {
56 TextDataStreamer *Streamer = new TextDataStreamer();
57 llvm::raw_string_ostream ErrStrm(*Err);
58 if (std::error_code EC = llvm::readNaClRecordTextAndBuildBitcode(
59 Filename, Streamer->BitcodeBuffer, &ErrStrm)) {
Karl Schimpfcb6e95a2015-07-23 09:10:03 -070060 ErrStrm << EC.message();
Karl Schimpf6f9ba112015-06-22 13:20:23 -070061 ErrStrm.flush();
62 delete Streamer;
63 return nullptr;
64 }
Karl Schimpfcb6e95a2015-07-23 09:10:03 -070065 ErrStrm.flush();
Karl Schimpf6f9ba112015-06-22 13:20:23 -070066 return Streamer;
67}
68
69size_t TextDataStreamer::GetBytes(unsigned char *Buf, size_t Len) {
70 if (Cursor >= BitcodeBuffer.size())
71 return 0;
72 size_t Remaining = BitcodeBuffer.size();
73 Len = std::min(Len, Remaining);
74 for (size_t i = 0; i < Len; ++i)
75 Buf[i] = BitcodeBuffer[Cursor + i];
76 Cursor += Len;
77 return Len;
78}
79
Jim Stichnoth620ad732015-04-28 14:12:20 -070080std::unique_ptr<Ostream> makeStream(const IceString &Filename,
81 std::error_code &EC) {
82 if (Filename == "-") {
Jan Voung44c3a802015-03-27 16:29:08 -070083 return std::unique_ptr<Ostream>(new llvm::raw_os_ostream(std::cout));
Jim Stichnoth620ad732015-04-28 14:12:20 -070084 } else {
85 return std::unique_ptr<Ostream>(
86 new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
Jan Voung44c3a802015-03-27 16:29:08 -070087 }
88}
89
90ErrorCodes getReturnValue(const Ice::ClFlagsExtra &Flags, ErrorCodes Val) {
91 if (Flags.getAlwaysExitSuccess())
92 return EC_None;
93 return Val;
94}
95
96} // end of anonymous namespace
97
98void CLCompileServer::run() {
Jim Stichnoth20b71f52015-06-24 15:52:24 -070099 if (BuildDefs::dump()) {
Jan Voungb2d50842015-05-12 09:53:50 -0700100 llvm::sys::PrintStackTraceOnErrorSignal();
101 }
Jan Voung44c3a802015-03-27 16:29:08 -0700102 ClFlags::parseFlags(argc, argv);
103 ClFlags Flags;
104 ClFlagsExtra ExtraFlags;
105 ClFlags::getParsedClFlags(Flags);
106 ClFlags::getParsedClFlagsExtra(ExtraFlags);
107
Jim Stichnoth620ad732015-04-28 14:12:20 -0700108 std::error_code EC;
109 std::unique_ptr<Ostream> Ls = makeStream(ExtraFlags.getLogFilename(), EC);
110 if (EC) {
111 llvm::report_fatal_error("Unable to open log file");
112 }
Jan Voung44c3a802015-03-27 16:29:08 -0700113 Ls->SetUnbuffered();
114 std::unique_ptr<Ostream> Os;
115 std::unique_ptr<ELFStreamer> ELFStr;
116 switch (Flags.getOutFileType()) {
117 case FT_Elf: {
118 if (ExtraFlags.getOutputFilename() == "-") {
119 *Ls << "Error: writing binary ELF to stdout is unsupported\n";
120 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
121 }
Jan Voung44c3a802015-03-27 16:29:08 -0700122 std::unique_ptr<llvm::raw_fd_ostream> FdOs(new llvm::raw_fd_ostream(
123 ExtraFlags.getOutputFilename(), EC, llvm::sys::fs::F_None));
124 if (EC) {
125 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
126 << ":\n" << EC.message() << "\n";
127 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
128 }
129 ELFStr.reset(new ELFStreamer(*FdOs.get()));
130 Os.reset(FdOs.release());
Andrew Scull57e12682015-09-16 11:30:19 -0700131 // NaCl sets st_blksize to 0, and LLVM uses that to pick the default
132 // preferred buffer size. Set to something non-zero.
Jan Voung44c3a802015-03-27 16:29:08 -0700133 Os->SetBufferSize(1 << 14);
134 } break;
135 case FT_Asm:
136 case FT_Iasm: {
Jim Stichnoth620ad732015-04-28 14:12:20 -0700137 Os = makeStream(ExtraFlags.getOutputFilename(), EC);
138 if (EC) {
139 *Ls << "Failed to open output file: " << ExtraFlags.getOutputFilename()
140 << ":\n" << EC.message() << "\n";
141 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Args));
142 }
Jan Voung44c3a802015-03-27 16:29:08 -0700143 Os->SetUnbuffered();
144 } break;
145 }
146
Karl Schimpfcb6e95a2015-07-23 09:10:03 -0700147 if (BuildDefs::minimal() && ExtraFlags.getBitcodeAsText())
148 llvm::report_fatal_error("Can't specify 'bitcode-as-text' flag in "
149 "minimal build");
150
Jan Voung44c3a802015-03-27 16:29:08 -0700151 IceString StrError;
152 std::unique_ptr<llvm::DataStreamer> InputStream(
Karl Schimpfcb6e95a2015-07-23 09:10:03 -0700153 (!BuildDefs::minimal() && ExtraFlags.getBitcodeAsText())
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700154 ? TextDataStreamer::create(ExtraFlags.getIRFilename(), &StrError)
155 : llvm::getDataFileStreamer(ExtraFlags.getIRFilename(), &StrError));
Jan Voung44c3a802015-03-27 16:29:08 -0700156 if (!StrError.empty() || !InputStream) {
157 llvm::SMDiagnostic Err(ExtraFlags.getIRFilename(),
158 llvm::SourceMgr::DK_Error, StrError);
159 Err.print(ExtraFlags.getAppName().c_str(), *Ls);
160 return transferErrorCode(getReturnValue(ExtraFlags, Ice::EC_Bitcode));
161 }
162
Jim Stichnoth620ad732015-04-28 14:12:20 -0700163 Ctx.reset(
164 new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get(), Flags));
Jan Voung44c3a802015-03-27 16:29:08 -0700165 if (Ctx->getFlags().getNumTranslationThreads() != 0) {
166 std::thread CompileThread([this, &ExtraFlags, &InputStream]() {
167 Ctx->initParserThread();
168 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
169 });
170 CompileThread.join();
171 } else {
172 getCompiler().run(ExtraFlags, *Ctx.get(), std::move(InputStream));
173 }
174 transferErrorCode(getReturnValue(
175 ExtraFlags, static_cast<ErrorCodes>(Ctx->getErrorStatus()->value())));
176}
177
178} // end of namespace Ice