Index: src/IceCompiler.cpp |
diff --git a/src/main.cpp b/src/IceCompiler.cpp |
similarity index 80% |
copy from src/main.cpp |
copy to src/IceCompiler.cpp |
index 22ab0a100bb025ac73436f1b950aa17a556804ca..a4063391c9f95604bc30c4baf55a3b99e94b18fc 100644 |
--- a/src/main.cpp |
+++ b/src/IceCompiler.cpp |
@@ -1,4 +1,4 @@ |
-//===- subzero/src/main.cpp - Driver for bitcode translation --------------===// |
+//===- subzero/src/IceCompiler.cpp - Driver for bitcode translation -------===// |
// |
// The Subzero Code Generator |
// |
@@ -15,6 +15,8 @@ |
// |
//===----------------------------------------------------------------------===// |
+#include "IceCompiler.h" |
+ |
#include <fstream> |
#include <iostream> |
@@ -30,6 +32,7 @@ |
#include "IceCfg.h" |
#include "IceClFlags.h" |
+#include "IceCompileServer.h" |
#include "IceConverter.h" |
#include "IceELFObjectWriter.h" |
#include "IceELFStreamer.h" |
@@ -57,18 +60,19 @@ static cl::list<Ice::VerboseItem> VerboseList( |
clEnumValN(Ice::IceV_Most, "most", |
"Use all verbose options except 'regalloc' and 'time'"), |
clEnumValN(Ice::IceV_None, "none", "No verbosity"), clEnumValEnd)); |
-static cl::opt<Ice::TargetArch> TargetArch( |
- "target", cl::desc("Target architecture:"), cl::init(Ice::Target_X8632), |
- cl::values( |
- clEnumValN(Ice::Target_X8632, "x8632", "x86-32"), |
- clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"), |
- clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"), |
- clEnumValN(Ice::Target_X8664, "x8664", "x86-64"), |
- clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"), |
- clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"), |
- clEnumValN(Ice::Target_ARM32, "arm", "arm32"), |
- clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"), |
- clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd)); |
+static cl::opt<Ice::TargetArch> |
+ TArch("target", cl::desc("Target architecture:"), |
+ cl::init(Ice::Target_X8632), |
+ cl::values( |
+ clEnumValN(Ice::Target_X8632, "x8632", "x86-32"), |
+ clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"), |
+ clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"), |
+ clEnumValN(Ice::Target_X8664, "x8664", "x86-64"), |
+ clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"), |
+ clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"), |
+ clEnumValN(Ice::Target_ARM32, "arm", "arm32"), |
+ clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"), |
+ clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd)); |
static cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing")); |
static cl::opt<bool> |
FunctionSections("ffunction-sections", |
@@ -77,13 +81,13 @@ static cl::opt<bool> |
DataSections("fdata-sections", |
cl::desc("Emit (global) data into separate sections")); |
static cl::opt<Ice::OptLevel> |
- OptLevel(cl::desc("Optimization level"), cl::init(Ice::Opt_m1), |
- cl::value_desc("level"), |
- cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"), |
- clEnumValN(Ice::Opt_m1, "O-1", "-1"), |
- clEnumValN(Ice::Opt_0, "O0", "0"), |
- clEnumValN(Ice::Opt_1, "O1", "1"), |
- clEnumValN(Ice::Opt_2, "O2", "2"), clEnumValEnd)); |
+ OLevel(cl::desc("Optimization level"), cl::init(Ice::Opt_m1), |
+ cl::value_desc("level"), |
+ cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"), |
+ clEnumValN(Ice::Opt_m1, "O-1", "-1"), |
+ clEnumValN(Ice::Opt_0, "O0", "0"), |
+ clEnumValN(Ice::Opt_1, "O1", "1"), |
+ clEnumValN(Ice::Opt_2, "O2", "2"), clEnumValEnd)); |
static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), |
cl::init("-")); |
static cl::opt<std::string> OutputFilename("o", |
@@ -238,7 +242,7 @@ static struct { |
static void ValidateAndGenerateBuildAttributes(Ice::Ostream *Stream) { |
if (Stream) |
- *Stream << TargetArch << "\n"; |
+ *Stream << TArch << "\n"; |
for (size_t i = 0; i < array_lengthof(ConditionalBuildAttributes); ++i) { |
switch (ConditionalBuildAttributes[i].FlagValue) { |
@@ -262,7 +266,7 @@ static void ValidateAndGenerateBuildAttributes(Ice::Ostream *Stream) { |
} |
} |
-int main(int argc, char **argv) { |
+void Ice::Compiler::run(int argc, char **argv, Ice::CompileServer &Server) { |
cl::ParseCommandLineOptions(argc, argv); |
@@ -289,12 +293,12 @@ int main(int argc, char **argv) { |
ValidateAndGenerateBuildAttributes(GenerateBuildAtts ? Ls.get() : nullptr); |
if (GenerateBuildAtts) |
- return GetReturnValue(Ice::EC_None); |
+ return setReturnValue(GetReturnValue(Ice::EC_None)); |
if (!ALLOW_DISABLE_IR_GEN && DisableIRGeneration) { |
*Ls << "Error: Build doesn't allow --no-ir-gen when not " |
<< "ALLOW_DISABLE_IR_GEN!\n"; |
- return GetReturnValue(Ice::EC_Args); |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
} |
Ice::ClFlags Flags; |
@@ -322,38 +326,52 @@ int main(int argc, char **argv) { |
// Force -build-on-read=0 for .ll files. |
const std::string LLSuffix = ".ll"; |
- if (IRFilename.length() >= LLSuffix.length() && |
+ if (ALLOW_LLVM_IR_AS_INPUT && IRFilename.length() >= LLSuffix.length() && |
IRFilename.compare(IRFilename.length() - LLSuffix.length(), |
LLSuffix.length(), LLSuffix) == 0) |
BuildOnRead = false; |
- // With the ELF writer, use a raw_fd_ostream to allow seeking. |
- // Also don't buffer, otherwise it gets pretty slow. |
std::unique_ptr<Ice::Ostream> Os; |
std::unique_ptr<Ice::ELFStreamer> ELFStr; |
- std::ofstream Ofs; |
switch (OutFileType) { |
case Ice::FT_Elf: { |
if (OutputFilename == "-") { |
*Ls << "Error: writing binary ELF to stdout is unsupported\n"; |
- return GetReturnValue(Ice::EC_Args); |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
} |
std::error_code EC; |
- raw_fd_ostream *FdOs = |
- new raw_fd_ostream(OutputFilename, EC, sys::fs::F_None); |
- // NaCl sets st_blksize to 0, and LLVM uses that to pick the |
- // default preferred buffer size. Set to something non-zero. |
- FdOs->SetBufferSize(1 << 14); |
- Os.reset(FdOs); |
+ std::unique_ptr<llvm::raw_fd_ostream> FdOs = |
+ Server.getOutputStream(OutputFilename, EC); |
if (EC) { |
*Ls << "Failed to open output file: " << OutputFilename << ":\n" |
<< EC.message() << "\n"; |
- return GetReturnValue(Ice::EC_Args); |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
} |
- ELFStr.reset(new Ice::ELFStreamer(*FdOs)); |
+ ELFStr.reset(new Ice::ELFStreamer(*FdOs.get())); |
+ Os.reset(FdOs.release()); |
+ // NaCl sets st_blksize to 0, and LLVM uses that to pick the |
+ // default preferred buffer size. Set to something non-zero. |
+ Os->SetBufferSize(1 << 14); |
} break; |
case Ice::FT_Asm: |
case Ice::FT_Iasm: { |
+ if (PNACL_BROWSER_TRANSLATOR) { |
+ *Ls << "Asm/Iasm is not supported under PNACL_BROWSER_TRANSLATOR\n"; |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
+ } |
+ // Use raw_os_ostream instead of raw_fd_ostream. If both the |
+ // LogFilename and OutputFilename are stdout, then having |
+ // Os be a raw_fd_ostream while Ls is a raw_os_ostream backed by |
+ // a std::ofstream will confuse the buffering and have odd |
+ // interleavings (even with explicit flushes, for some reason). |
+ // So, make sure both are the same type of stream. In this case, |
+ // choose ofstream + raw_os_ostream for both. |
+ // This avoids asking the compiler server for the output file, |
+ // which won't work in the PNACL_BROWSER_TRANSLATOR case. |
+ // An alternative is to choose raw_fd_ostream for both, but then |
+ // you have to explicitly tell raw_fd_ostream not to own the |
+ // fd since it is shared by the two streams (you'll get a double-close). |
+ std::ofstream Ofs; |
if (OutputFilename != "-") { |
Ofs.open(OutputFilename.c_str(), std::ofstream::out); |
Os.reset(new raw_os_ostream(Ofs)); |
@@ -364,8 +382,8 @@ int main(int argc, char **argv) { |
} break; |
} |
- Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), VMask, TargetArch, |
- OptLevel, TestPrefix, Flags); |
+ Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), VMask, TArch, OLevel, |
+ TestPrefix, Flags); |
Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx); |
@@ -381,18 +399,22 @@ int main(int argc, char **argv) { |
std::unique_ptr<Ice::PNaClTranslator> PTranslator( |
new Ice::PNaClTranslator(&Ctx)); |
std::string StrError; |
- std::unique_ptr<DataStreamer> FileStreamer( |
- getDataFileStreamer(IRFilename, &StrError)); |
+ std::unique_ptr<DataStreamer> FileStreamer = |
+ Server.getInputStream(IRFilename, StrError); |
if (!StrError.empty() || !FileStreamer) { |
SMDiagnostic Err(IRFilename, SourceMgr::DK_Error, StrError); |
Err.print(argv[0], errs()); |
- return GetReturnValue(Ice::EC_Bitcode); |
+ return setReturnValue(GetReturnValue(Ice::EC_Bitcode)); |
} |
std::unique_ptr<StreamingMemoryObject> MemObj( |
new StreamingMemoryObjectImpl(FileStreamer.release())); |
PTranslator->translate(IRFilename, std::move(MemObj)); |
Translator.reset(PTranslator.release()); |
} else if (ALLOW_LLVM_IR) { |
+ if (PNACL_BROWSER_TRANSLATOR) { |
+ *Ls << "non BuildOnRead is not supported w/ PNACL_BROWSER_TRANSLATOR\n"; |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
+ } |
// Parse the input LLVM IR file into a module. |
SMDiagnostic Err; |
Ice::TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx); |
@@ -401,7 +423,7 @@ int main(int argc, char **argv) { |
IRFilename, InputFileFormat, Err, Verbose, getGlobalContext()); |
if (!Mod) { |
Err.print(argv[0], errs()); |
- return GetReturnValue(Ice::EC_Bitcode); |
+ return setReturnValue(GetReturnValue(Ice::EC_Bitcode)); |
} |
std::unique_ptr<Ice::Converter> Converter( |
@@ -411,7 +433,7 @@ int main(int argc, char **argv) { |
} else { |
*Ls << "Error: Build doesn't allow LLVM IR, " |
<< "--build-on-read=0 not allowed\n"; |
- return GetReturnValue(Ice::EC_Args); |
+ return setReturnValue(GetReturnValue(Ice::EC_Args)); |
} |
Ctx.waitForWorkerThreads(); |
@@ -431,5 +453,5 @@ int main(int argc, char **argv) { |
} |
const bool FinalStats = true; |
Ctx.dumpStats("_FINAL_", FinalStats); |
- return GetReturnValue(Ctx.getErrorStatus()->value()); |
+ return setReturnValue(GetReturnValue(Ctx.getErrorStatus()->value())); |
} |