Chromium Code Reviews| Index: src/main.cpp |
| diff --git a/src/main.cpp b/src/main.cpp |
| index 9858fa262a968d5c6bacd9a7edf6a8e3eb186a28..546e9455ee971dbf66c6a315861706e8774df43f 100644 |
| --- a/src/main.cpp |
| +++ b/src/main.cpp |
| @@ -1,4 +1,4 @@ |
| -//===- subzero/src/main.cpp - Driver for bitcode translation --------------===// |
| +//===- subzero/src/main.cpp - Entry point for bitcode translation ---------===// |
| // |
| // The Subzero Code Generator |
| // |
| @@ -7,465 +7,30 @@ |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| -// This file defines a driver for translating PNaCl bitcode into native code. |
| -// It can either directly parse the binary bitcode file, or use LLVM routines to |
| -// parse a textual bitcode file into LLVM IR and then convert LLVM IR into ICE. |
| -// In either case, the high-level ICE is then compiled down to native code, as |
| -// either an ELF object file or a textual asm file. |
| +// This file defines the entry point for translating PNaCl bitcode into |
| +// native code. |
| // |
| //===----------------------------------------------------------------------===// |
| -#include <fstream> |
| -#include <iostream> |
| - |
| -#include "llvm/ADT/STLExtras.h" |
| -#include "llvm/IR/LLVMContext.h" |
| -#include "llvm/IR/Module.h" |
| -#include "llvm/IRReader/IRReader.h" |
| -#include "llvm/Support/CommandLine.h" |
| -#include "llvm/Support/FileSystem.h" |
| -#include "llvm/Support/raw_os_ostream.h" |
| -#include "llvm/Support/SourceMgr.h" |
| -#include "llvm/Support/StreamingMemoryObject.h" |
| - |
| -#include "IceCfg.h" |
| -#include "IceClFlags.h" |
| -#include "IceConverter.h" |
| -#include "IceELFObjectWriter.h" |
| -#include "IceELFStreamer.h" |
| -#include "PNaClTranslator.h" |
| - |
| -using namespace llvm; |
| - |
| -static cl::list<Ice::VerboseItem> VerboseList( |
| - "verbose", cl::CommaSeparated, |
| - cl::desc("Verbose options (can be comma-separated):"), |
| - cl::values( |
| - clEnumValN(Ice::IceV_Instructions, "inst", "Print basic instructions"), |
| - clEnumValN(Ice::IceV_Deleted, "del", "Include deleted instructions"), |
| - clEnumValN(Ice::IceV_InstNumbers, "instnum", |
| - "Print instruction numbers"), |
| - clEnumValN(Ice::IceV_Preds, "pred", "Show predecessors"), |
| - clEnumValN(Ice::IceV_Succs, "succ", "Show successors"), |
| - clEnumValN(Ice::IceV_Liveness, "live", "Liveness information"), |
| - clEnumValN(Ice::IceV_RegOrigins, "orig", "Physical register origins"), |
| - clEnumValN(Ice::IceV_LinearScan, "regalloc", "Linear scan details"), |
| - clEnumValN(Ice::IceV_Frame, "frame", "Stack frame layout details"), |
| - clEnumValN(Ice::IceV_AddrOpt, "addropt", "Address mode optimization"), |
| - clEnumValN(Ice::IceV_Random, "random", "Randomization details"), |
| - clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), |
| - 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)); |
| - |
| -cl::opt<Ice::TargetInstructionSet> InstructionSet( |
| - "mattr", cl::desc("Target architecture attributes"), |
| - cl::init(Ice::X86InstructionSet_SSE2), |
| - cl::values(clEnumValN(Ice::X86InstructionSet_SSE2, "sse2", |
| - "Enable SSE2 instructions (default)"), |
| - clEnumValN(Ice::X86InstructionSet_SSE4_1, "sse4.1", |
| - "Enable SSE 4.1 instructions"), |
| - clEnumValEnd)); |
| - |
| -static cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing")); |
| -static cl::opt<bool> |
| - FunctionSections("ffunction-sections", |
| - cl::desc("Emit functions into separate sections")); |
| -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)); |
| -static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), |
| - cl::init("-")); |
| -static cl::opt<std::string> OutputFilename("o", |
| - cl::desc("Override output filename"), |
| - cl::init("-"), |
| - cl::value_desc("filename")); |
| -static cl::opt<std::string> LogFilename("log", cl::desc("Set log filename"), |
| - cl::init("-"), |
| - cl::value_desc("filename")); |
| -static cl::opt<std::string> |
| - TestPrefix("prefix", |
| - cl::desc("Prepend a prefix to symbol names for testing"), |
| - cl::init(""), cl::value_desc("prefix")); |
| -static cl::opt<bool> DisableInternal("externalize", |
| - cl::desc("Externalize all symbols")); |
| -static cl::opt<bool> |
| - DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); |
| -// Note: Modifiable only if ALLOW_DISABLE_IR_GEN. |
| -static cl::opt<bool> |
| - DisableIRGeneration("no-ir-gen", |
| - cl::desc("Disable generating Subzero IR.")); |
| -static cl::opt<std::string> |
| - TranslateOnly("translate-only", |
| - cl::desc("Translate only the given function"), cl::init("")); |
| - |
| -static cl::opt<bool> SubzeroTimingEnabled( |
| - "timing", cl::desc("Enable breakdown timing of Subzero translation")); |
| - |
| -static cl::opt<bool> TimeEachFunction( |
| - "timing-funcs", cl::desc("Print total translation time for each function")); |
| - |
| -static cl::opt<std::string> TimingFocusOn( |
| - "timing-focus", |
| - cl::desc("Break down timing for a specific function (use '*' for all)"), |
| - cl::init("")); |
| - |
| -static cl::opt<std::string> VerboseFocusOn( |
| - "verbose-focus", |
| - cl::desc("Temporarily enable full verbosity for a specific function"), |
| - cl::init("")); |
| - |
| -static cl::opt<bool> |
| - EnablePhiEdgeSplit("phi-edge-split", |
| - cl::desc("Enable edge splitting for Phi lowering"), |
| - cl::init(true)); |
| - |
| -static cl::opt<bool> DecorateAsm( |
| - "asm-verbose", |
| - cl::desc("Decorate textual asm output with register liveness info")); |
| - |
| -static cl::opt<bool> |
| - DumpStats("szstats", |
| - cl::desc("Print statistics after translating each function")); |
| - |
| -// This is currently needed by crosstest.py. |
| -static cl::opt<bool> AllowUninitializedGlobals( |
| - "allow-uninitialized-globals", |
| - cl::desc("Allow global variables to be uninitialized")); |
| - |
| -static cl::opt<NaClFileFormat> InputFileFormat( |
| - "bitcode-format", cl::desc("Define format of input file:"), |
| - cl::values(clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"), |
| - clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"), |
| - clEnumValEnd), |
| - cl::init(LLVMFormat)); |
| - |
| -static cl::opt<std::string> |
| - DefaultGlobalPrefix("default-global-prefix", |
| - cl::desc("Define default global prefix for naming " |
| - "unnamed globals"), |
| - cl::init("Global")); |
| - |
| -static cl::opt<std::string> |
| - DefaultFunctionPrefix("default-function-prefix", |
| - cl::desc("Define default function prefix for naming " |
| - "unnamed functions"), |
| - cl::init("Function")); |
| - |
| -// Note: While this flag isn't used in the minimal build, we keep this |
| -// flag so that tests can set this command-line flag without concern |
| -// to the type of build. We double check that this flag at runtime |
| -// to make sure the consistency is maintained. |
| -static cl::opt<bool> |
| - BuildOnRead("build-on-read", |
| - cl::desc("Build ICE instructions when reading bitcode"), |
| - cl::init(true)); |
| - |
| -static cl::opt<bool> AllowErrorRecovery( |
| - "allow-pnacl-reader-error-recovery", |
| - cl::desc("Allow error recovery when reading PNaCl bitcode."), |
| - cl::init(false)); |
| - |
| -static cl::opt<bool> LLVMVerboseErrors( |
| - "verbose-llvm-parse-errors", |
| - cl::desc("Print out more descriptive PNaCl bitcode parse errors when " |
| - "building LLVM IR first"), |
| - cl::init(false)); |
| - |
| -static cl::opt<Ice::FileType> OutFileType( |
| - "filetype", cl::desc("Output file type"), cl::init(Ice::FT_Iasm), |
| - cl::values(clEnumValN(Ice::FT_Elf, "obj", "Native ELF object ('.o') file"), |
| - clEnumValN(Ice::FT_Asm, "asm", "Assembly ('.s') file"), |
| - clEnumValN(Ice::FT_Iasm, "iasm", |
| - "Low-level integrated assembly ('.s') file"), |
| - clEnumValEnd)); |
| - |
| -static cl::opt<bool> AlwaysExitSuccess( |
| - "exit-success", cl::desc("Exit with success status, even if errors found"), |
| - cl::init(false)); |
| - |
| -static cl::opt<bool> GenerateBuildAtts( |
| - "build-atts", cl::desc("Generate list of build attributes associated with " |
| - "this executable."), |
| - cl::init(false)); |
| - |
| -// Number of translation threads (in addition to the parser thread and |
| -// the emitter thread). The special case of 0 means purely |
| -// sequential, i.e. parser, translator, and emitter all within the |
| -// same single thread. (This may need a slight rework if we expand to |
| -// multiple parser or emitter threads.) |
| -static cl::opt<uint32_t> NumThreads( |
| - "threads", |
| - cl::desc("Number of translation threads (0 for purely sequential)"), |
| - // TODO(stichnot): Settle on a good default. Consider |
| - // something related to std::thread::hardware_concurrency(). |
| - cl::init(2)); |
| - |
| -static cl::opt<bool> DoNopInsertion("nop-insertion", |
| - cl::desc("Randomly insert NOPs"), |
| - cl::init(false)); |
| - |
| -static cl::opt<int> MaxNopsPerInstruction( |
| - "max-nops-per-instruction", |
| - cl::desc("Max number of nops to insert per instruction"), cl::init(1)); |
| - |
| -static cl::opt<int> NopProbabilityAsPercentage( |
| - "nop-insertion-percentage", |
| - cl::desc("Nop insertion probability as percentage"), cl::init(10)); |
| - |
| -static cl::opt<bool> |
| - RandomizeRegisterAllocation("randomize-regalloc", |
| - cl::desc("Randomize register allocation"), |
| - cl::init(false)); |
| - |
| -// TODO(stichnot): See if we can easily use LLVM's -rng-seed option |
| -// and implementation. I expect the implementation is different and |
| -// therefore the tests would need to be changed. |
| -cl::opt<unsigned long long> |
| - RandomSeed("sz-seed", cl::desc("Seed the random number generator"), |
| - cl::init(time(0))); |
| - |
| -static int GetReturnValue(int Val) { |
| - if (AlwaysExitSuccess) |
| - return 0; |
| - return Val; |
| -} |
| - |
| -static struct { |
| - const char *FlagName; |
| - int FlagValue; |
| -} ConditionalBuildAttributes[] = {{"dump", ALLOW_DUMP}, |
| - {"disable_ir_gen", ALLOW_DISABLE_IR_GEN}, |
| - {"llvm_cl", ALLOW_LLVM_CL}, |
| - {"llvm_ir", ALLOW_LLVM_IR}, |
| - {"llvm_ir_as_input", ALLOW_LLVM_IR_AS_INPUT}, |
| - {"minimal_build", ALLOW_MINIMAL_BUILD}}; |
| - |
| -// Validates values of build attributes. Prints them to Stream if |
| -// Stream is non-null. |
| -static void ValidateAndGenerateBuildAttributes(Ice::Ostream *Stream) { |
| - |
| - if (Stream) |
| - *Stream << TargetArch << "\n"; |
| - |
| - for (size_t i = 0; i < array_lengthof(ConditionalBuildAttributes); ++i) { |
| - switch (ConditionalBuildAttributes[i].FlagValue) { |
| - case 0: |
| - if (Stream) |
| - *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n"; |
| - break; |
| - case 1: |
| - if (Stream) |
| - *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n"; |
| - break; |
| - default: { |
| - std::string Buffer; |
| - raw_string_ostream StrBuf(Buffer); |
| - StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName |
| - << " must be defined as 0/1. Found: " |
| - << ConditionalBuildAttributes[i].FlagValue; |
| - report_fatal_error(StrBuf.str()); |
| - } |
| - } |
| - } |
| -} |
| +#include "IceBrowserCompileServer.h" |
| +#include "IceCompiler.h" |
| +#include "IceCompileServer.h" |
| int main(int argc, char **argv) { |
| - |
| - cl::ParseCommandLineOptions(argc, argv); |
| - |
| - if (DisableIRGeneration) |
| - DisableTranslation = true; |
| - |
| - Ice::VerboseMask VMask = Ice::IceV_None; |
| - // Don't generate verbose messages if routines |
| - // to dump messages are not available. |
| - if (ALLOW_DUMP) { |
| - for (unsigned i = 0; i != VerboseList.size(); ++i) |
| - VMask |= VerboseList[i]; |
| - } |
| - |
| - std::ofstream Lfs; |
| - std::unique_ptr<Ice::Ostream> Ls; |
| - if (LogFilename != "-") { |
| - Lfs.open(LogFilename.c_str(), std::ofstream::out); |
| - Ls.reset(new raw_os_ostream(Lfs)); |
| - } else { |
| - Ls.reset(new raw_os_ostream(std::cout)); |
| - } |
| - Ls->SetUnbuffered(); |
| - |
| - ValidateAndGenerateBuildAttributes(GenerateBuildAtts ? Ls.get() : nullptr); |
| - if (GenerateBuildAtts) |
| - return 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); |
| - } |
| - |
| - Ice::ClFlags Flags; |
| - Flags.setAllowErrorRecovery(AllowErrorRecovery); |
| - Flags.setAllowUninitializedGlobals(AllowUninitializedGlobals); |
| - Flags.setDataSections(DataSections); |
| - Flags.setDecorateAsm(DecorateAsm); |
| - Flags.setDefaultFunctionPrefix(DefaultFunctionPrefix); |
| - Flags.setDefaultGlobalPrefix(DefaultGlobalPrefix); |
| - Flags.setDisableInternal(DisableInternal); |
| - Flags.setDisableIRGeneration(DisableIRGeneration); |
| - Flags.setDisableTranslation(DisableTranslation); |
| - Flags.setDumpStats(DumpStats); |
| - Flags.setFunctionSections(FunctionSections); |
| - Flags.setNumTranslationThreads(NumThreads); |
| - Flags.setOptLevel(OptLevel); |
| - Flags.setPhiEdgeSplit(EnablePhiEdgeSplit); |
| - Flags.setRandomSeed(RandomSeed); |
| - Flags.setShouldDoNopInsertion(DoNopInsertion); |
| - Flags.setShouldRandomizeRegAlloc(RandomizeRegisterAllocation); |
| - Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled); |
| - Flags.setTargetArch(TargetArch); |
| - Flags.setTargetInstructionSet(InstructionSet); |
| - Flags.setTestPrefix(TestPrefix); |
| - Flags.setTimeEachFunction(TimeEachFunction); |
| - Flags.setTimingFocusOn(TimingFocusOn); |
| - Flags.setTranslateOnly(TranslateOnly); |
| - Flags.setUseSandboxing(UseSandboxing); |
| - Flags.setVerboseFocusOn(VerboseFocusOn); |
| - Flags.setOutFileType(OutFileType); |
| - Flags.setMaxNopsPerInstruction(MaxNopsPerInstruction); |
| - Flags.setNopProbabilityAsPercentage(NopProbabilityAsPercentage); |
| - Flags.setVerbose(VMask); |
| - |
| - // Force -build-on-read=0 for .ll files. |
| - const std::string LLSuffix = ".ll"; |
| - if (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); |
| - } |
| - 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); |
| - if (EC) { |
| - *Ls << "Failed to open output file: " << OutputFilename << ":\n" |
| - << EC.message() << "\n"; |
| - return GetReturnValue(Ice::EC_Args); |
| - } |
| - ELFStr.reset(new Ice::ELFStreamer(*FdOs)); |
| - } break; |
| - case Ice::FT_Asm: |
| - case Ice::FT_Iasm: { |
| - if (OutputFilename != "-") { |
| - Ofs.open(OutputFilename.c_str(), std::ofstream::out); |
| - Os.reset(new raw_os_ostream(Ofs)); |
| - } else { |
| - Os.reset(new raw_os_ostream(std::cout)); |
| - } |
| - Os->SetUnbuffered(); |
| - } break; |
| - } |
| - |
| - Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), Flags); |
| - |
| - Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx); |
| - |
| - if (OutFileType == Ice::FT_Elf) { |
| - Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); |
| - Ctx.getObjectWriter()->writeInitialELFHeader(); |
| - } |
| - |
| - Ctx.startWorkerThreads(); |
| - |
| - std::unique_ptr<Ice::Translator> Translator; |
| - if (BuildOnRead) { |
| - std::unique_ptr<Ice::PNaClTranslator> PTranslator( |
| - new Ice::PNaClTranslator(&Ctx)); |
| - std::string StrError; |
| - std::unique_ptr<DataStreamer> FileStreamer( |
| - getDataFileStreamer(IRFilename, &StrError)); |
| - if (!StrError.empty() || !FileStreamer) { |
| - SMDiagnostic Err(IRFilename, SourceMgr::DK_Error, StrError); |
| - Err.print(argv[0], errs()); |
| - return 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) { |
| - // Parse the input LLVM IR file into a module. |
| - SMDiagnostic Err; |
| - Ice::TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx); |
| - raw_ostream *Verbose = LLVMVerboseErrors ? &errs() : nullptr; |
| - std::unique_ptr<Module> Mod = NaClParseIRFile( |
| - IRFilename, InputFileFormat, Err, Verbose, getGlobalContext()); |
| - if (!Mod) { |
| - Err.print(argv[0], errs()); |
| - return GetReturnValue(Ice::EC_Bitcode); |
| - } |
| - |
| - std::unique_ptr<Ice::Converter> Converter( |
| - new Ice::Converter(Mod.get(), &Ctx)); |
| - Converter->convertToIce(); |
| - Translator.reset(Converter.release()); |
| - } else { |
| - *Ls << "Error: Build doesn't allow LLVM IR, " |
| - << "--build-on-read=0 not allowed\n"; |
| - return GetReturnValue(Ice::EC_Args); |
| - } |
| - |
| - Ctx.waitForWorkerThreads(); |
| - Translator->transferErrorCode(); |
| - Translator->emitConstants(); |
| - |
| - if (OutFileType == Ice::FT_Elf) { |
| - Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); |
| - Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms()); |
| - Ctx.getObjectWriter()->writeNonUserSections(); |
| - } |
| - if (SubzeroTimingEnabled) |
| - Ctx.dumpTimers(); |
| - if (TimeEachFunction) { |
| - const bool DumpCumulative = false; |
| - Ctx.dumpTimers(Ice::GlobalContext::TSK_Funcs, DumpCumulative); |
| - } |
| - const bool FinalStats = true; |
| - Ctx.dumpStats("_FINAL_", FinalStats); |
| - return GetReturnValue(Ctx.getErrorStatus()->value()); |
| + // Start file server and "wait" for compile request. |
| + Ice::Compiler Comp; |
| +// Can only compile the BrowserCompileServer w/ the NaCl compiler. |
| +#if PNACL_BROWSER_TRANSLATOR |
| + // There are no real commandline arguments in the browser case. |
| + // They are supplied via IPC. |
| + assert(argc == 1); |
| + (void)argv; |
| + Ice::BrowserCompileServer Server(Comp); |
| + Server.run(); |
| + return Server.getErrorCode().value(); |
| +#else |
|
Jim Stichnoth
2015/03/25 16:34:06
#else // !PNACL_BROWSER_TRANSLATOR
...
#endif // !
jvoung (off chromium)
2015/03/25 18:14:35
Done.
|
| + Ice::CLCompileServer Server(Comp, argc, argv); |
| + Server.run(); |
| + return Server.getErrorCode().value(); |
| +#endif |
| } |