| OLD | NEW |
| 1 //===- subzero/src/main.cpp - Driver for bitcode translation --------------===// | 1 //===- subzero/src/main.cpp - Entry point for bitcode translation ---------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file defines a driver for translating PNaCl bitcode into native code. | 10 // This file defines the entry point for translating PNaCl bitcode into |
| 11 // It can either directly parse the binary bitcode file, or use LLVM routines to | 11 // native code. |
| 12 // parse a textual bitcode file into LLVM IR and then convert LLVM IR into ICE. | |
| 13 // In either case, the high-level ICE is then compiled down to native code, as | |
| 14 // either an ELF object file or a textual asm file. | |
| 15 // | 12 // |
| 16 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 17 | 14 |
| 18 #include <fstream> | 15 #include "IceBrowserCompileServer.h" |
| 19 #include <iostream> | 16 #include "IceCompiler.h" |
| 20 | 17 #include "IceCompileServer.h" |
| 21 #include "llvm/ADT/STLExtras.h" | |
| 22 #include "llvm/IR/LLVMContext.h" | |
| 23 #include "llvm/IR/Module.h" | |
| 24 #include "llvm/IRReader/IRReader.h" | |
| 25 #include "llvm/Support/CommandLine.h" | |
| 26 #include "llvm/Support/FileSystem.h" | |
| 27 #include "llvm/Support/raw_os_ostream.h" | |
| 28 #include "llvm/Support/SourceMgr.h" | |
| 29 #include "llvm/Support/StreamingMemoryObject.h" | |
| 30 | |
| 31 #include "IceCfg.h" | |
| 32 #include "IceClFlags.h" | |
| 33 #include "IceConverter.h" | |
| 34 #include "IceELFObjectWriter.h" | |
| 35 #include "IceELFStreamer.h" | |
| 36 #include "PNaClTranslator.h" | |
| 37 | |
| 38 using namespace llvm; | |
| 39 | |
| 40 static cl::list<Ice::VerboseItem> VerboseList( | |
| 41 "verbose", cl::CommaSeparated, | |
| 42 cl::desc("Verbose options (can be comma-separated):"), | |
| 43 cl::values( | |
| 44 clEnumValN(Ice::IceV_Instructions, "inst", "Print basic instructions"), | |
| 45 clEnumValN(Ice::IceV_Deleted, "del", "Include deleted instructions"), | |
| 46 clEnumValN(Ice::IceV_InstNumbers, "instnum", | |
| 47 "Print instruction numbers"), | |
| 48 clEnumValN(Ice::IceV_Preds, "pred", "Show predecessors"), | |
| 49 clEnumValN(Ice::IceV_Succs, "succ", "Show successors"), | |
| 50 clEnumValN(Ice::IceV_Liveness, "live", "Liveness information"), | |
| 51 clEnumValN(Ice::IceV_RegOrigins, "orig", "Physical register origins"), | |
| 52 clEnumValN(Ice::IceV_LinearScan, "regalloc", "Linear scan details"), | |
| 53 clEnumValN(Ice::IceV_Frame, "frame", "Stack frame layout details"), | |
| 54 clEnumValN(Ice::IceV_AddrOpt, "addropt", "Address mode optimization"), | |
| 55 clEnumValN(Ice::IceV_Random, "random", "Randomization details"), | |
| 56 clEnumValN(Ice::IceV_All, "all", "Use all verbose options"), | |
| 57 clEnumValN(Ice::IceV_Most, "most", | |
| 58 "Use all verbose options except 'regalloc' and 'time'"), | |
| 59 clEnumValN(Ice::IceV_None, "none", "No verbosity"), clEnumValEnd)); | |
| 60 static cl::opt<Ice::TargetArch> TargetArch( | |
| 61 "target", cl::desc("Target architecture:"), cl::init(Ice::Target_X8632), | |
| 62 cl::values( | |
| 63 clEnumValN(Ice::Target_X8632, "x8632", "x86-32"), | |
| 64 clEnumValN(Ice::Target_X8632, "x86-32", "x86-32 (same as x8632)"), | |
| 65 clEnumValN(Ice::Target_X8632, "x86_32", "x86-32 (same as x8632)"), | |
| 66 clEnumValN(Ice::Target_X8664, "x8664", "x86-64"), | |
| 67 clEnumValN(Ice::Target_X8664, "x86-64", "x86-64 (same as x8664)"), | |
| 68 clEnumValN(Ice::Target_X8664, "x86_64", "x86-64 (same as x8664)"), | |
| 69 clEnumValN(Ice::Target_ARM32, "arm", "arm32"), | |
| 70 clEnumValN(Ice::Target_ARM32, "arm32", "arm32 (same as arm)"), | |
| 71 clEnumValN(Ice::Target_ARM64, "arm64", "arm64"), clEnumValEnd)); | |
| 72 | |
| 73 cl::opt<Ice::TargetInstructionSet> InstructionSet( | |
| 74 "mattr", cl::desc("Target architecture attributes"), | |
| 75 cl::init(Ice::X86InstructionSet_SSE2), | |
| 76 cl::values(clEnumValN(Ice::X86InstructionSet_SSE2, "sse2", | |
| 77 "Enable SSE2 instructions (default)"), | |
| 78 clEnumValN(Ice::X86InstructionSet_SSE4_1, "sse4.1", | |
| 79 "Enable SSE 4.1 instructions"), | |
| 80 clEnumValEnd)); | |
| 81 | |
| 82 static cl::opt<bool> UseSandboxing("sandbox", cl::desc("Use sandboxing")); | |
| 83 static cl::opt<bool> | |
| 84 FunctionSections("ffunction-sections", | |
| 85 cl::desc("Emit functions into separate sections")); | |
| 86 static cl::opt<bool> | |
| 87 DataSections("fdata-sections", | |
| 88 cl::desc("Emit (global) data into separate sections")); | |
| 89 static cl::opt<Ice::OptLevel> | |
| 90 OptLevel(cl::desc("Optimization level"), cl::init(Ice::Opt_m1), | |
| 91 cl::value_desc("level"), | |
| 92 cl::values(clEnumValN(Ice::Opt_m1, "Om1", "-1"), | |
| 93 clEnumValN(Ice::Opt_m1, "O-1", "-1"), | |
| 94 clEnumValN(Ice::Opt_0, "O0", "0"), | |
| 95 clEnumValN(Ice::Opt_1, "O1", "1"), | |
| 96 clEnumValN(Ice::Opt_2, "O2", "2"), clEnumValEnd)); | |
| 97 static cl::opt<std::string> IRFilename(cl::Positional, cl::desc("<IR file>"), | |
| 98 cl::init("-")); | |
| 99 static cl::opt<std::string> OutputFilename("o", | |
| 100 cl::desc("Override output filename"), | |
| 101 cl::init("-"), | |
| 102 cl::value_desc("filename")); | |
| 103 static cl::opt<std::string> LogFilename("log", cl::desc("Set log filename"), | |
| 104 cl::init("-"), | |
| 105 cl::value_desc("filename")); | |
| 106 static cl::opt<std::string> | |
| 107 TestPrefix("prefix", | |
| 108 cl::desc("Prepend a prefix to symbol names for testing"), | |
| 109 cl::init(""), cl::value_desc("prefix")); | |
| 110 static cl::opt<bool> DisableInternal("externalize", | |
| 111 cl::desc("Externalize all symbols")); | |
| 112 static cl::opt<bool> | |
| 113 DisableTranslation("notranslate", cl::desc("Disable Subzero translation")); | |
| 114 // Note: Modifiable only if ALLOW_DISABLE_IR_GEN. | |
| 115 static cl::opt<bool> | |
| 116 DisableIRGeneration("no-ir-gen", | |
| 117 cl::desc("Disable generating Subzero IR.")); | |
| 118 static cl::opt<std::string> | |
| 119 TranslateOnly("translate-only", | |
| 120 cl::desc("Translate only the given function"), cl::init("")); | |
| 121 | |
| 122 static cl::opt<bool> SubzeroTimingEnabled( | |
| 123 "timing", cl::desc("Enable breakdown timing of Subzero translation")); | |
| 124 | |
| 125 static cl::opt<bool> TimeEachFunction( | |
| 126 "timing-funcs", cl::desc("Print total translation time for each function")); | |
| 127 | |
| 128 static cl::opt<std::string> TimingFocusOn( | |
| 129 "timing-focus", | |
| 130 cl::desc("Break down timing for a specific function (use '*' for all)"), | |
| 131 cl::init("")); | |
| 132 | |
| 133 static cl::opt<std::string> VerboseFocusOn( | |
| 134 "verbose-focus", | |
| 135 cl::desc("Temporarily enable full verbosity for a specific function"), | |
| 136 cl::init("")); | |
| 137 | |
| 138 static cl::opt<bool> | |
| 139 EnablePhiEdgeSplit("phi-edge-split", | |
| 140 cl::desc("Enable edge splitting for Phi lowering"), | |
| 141 cl::init(true)); | |
| 142 | |
| 143 static cl::opt<bool> DecorateAsm( | |
| 144 "asm-verbose", | |
| 145 cl::desc("Decorate textual asm output with register liveness info")); | |
| 146 | |
| 147 static cl::opt<bool> | |
| 148 DumpStats("szstats", | |
| 149 cl::desc("Print statistics after translating each function")); | |
| 150 | |
| 151 // This is currently needed by crosstest.py. | |
| 152 static cl::opt<bool> AllowUninitializedGlobals( | |
| 153 "allow-uninitialized-globals", | |
| 154 cl::desc("Allow global variables to be uninitialized")); | |
| 155 | |
| 156 static cl::opt<NaClFileFormat> InputFileFormat( | |
| 157 "bitcode-format", cl::desc("Define format of input file:"), | |
| 158 cl::values(clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"), | |
| 159 clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"), | |
| 160 clEnumValEnd), | |
| 161 cl::init(LLVMFormat)); | |
| 162 | |
| 163 static cl::opt<std::string> | |
| 164 DefaultGlobalPrefix("default-global-prefix", | |
| 165 cl::desc("Define default global prefix for naming " | |
| 166 "unnamed globals"), | |
| 167 cl::init("Global")); | |
| 168 | |
| 169 static cl::opt<std::string> | |
| 170 DefaultFunctionPrefix("default-function-prefix", | |
| 171 cl::desc("Define default function prefix for naming " | |
| 172 "unnamed functions"), | |
| 173 cl::init("Function")); | |
| 174 | |
| 175 // Note: While this flag isn't used in the minimal build, we keep this | |
| 176 // flag so that tests can set this command-line flag without concern | |
| 177 // to the type of build. We double check that this flag at runtime | |
| 178 // to make sure the consistency is maintained. | |
| 179 static cl::opt<bool> | |
| 180 BuildOnRead("build-on-read", | |
| 181 cl::desc("Build ICE instructions when reading bitcode"), | |
| 182 cl::init(true)); | |
| 183 | |
| 184 static cl::opt<bool> AllowErrorRecovery( | |
| 185 "allow-pnacl-reader-error-recovery", | |
| 186 cl::desc("Allow error recovery when reading PNaCl bitcode."), | |
| 187 cl::init(false)); | |
| 188 | |
| 189 static cl::opt<bool> LLVMVerboseErrors( | |
| 190 "verbose-llvm-parse-errors", | |
| 191 cl::desc("Print out more descriptive PNaCl bitcode parse errors when " | |
| 192 "building LLVM IR first"), | |
| 193 cl::init(false)); | |
| 194 | |
| 195 static cl::opt<Ice::FileType> OutFileType( | |
| 196 "filetype", cl::desc("Output file type"), cl::init(Ice::FT_Iasm), | |
| 197 cl::values(clEnumValN(Ice::FT_Elf, "obj", "Native ELF object ('.o') file"), | |
| 198 clEnumValN(Ice::FT_Asm, "asm", "Assembly ('.s') file"), | |
| 199 clEnumValN(Ice::FT_Iasm, "iasm", | |
| 200 "Low-level integrated assembly ('.s') file"), | |
| 201 clEnumValEnd)); | |
| 202 | |
| 203 static cl::opt<bool> AlwaysExitSuccess( | |
| 204 "exit-success", cl::desc("Exit with success status, even if errors found"), | |
| 205 cl::init(false)); | |
| 206 | |
| 207 static cl::opt<bool> GenerateBuildAtts( | |
| 208 "build-atts", cl::desc("Generate list of build attributes associated with " | |
| 209 "this executable."), | |
| 210 cl::init(false)); | |
| 211 | |
| 212 // Number of translation threads (in addition to the parser thread and | |
| 213 // the emitter thread). The special case of 0 means purely | |
| 214 // sequential, i.e. parser, translator, and emitter all within the | |
| 215 // same single thread. (This may need a slight rework if we expand to | |
| 216 // multiple parser or emitter threads.) | |
| 217 static cl::opt<uint32_t> NumThreads( | |
| 218 "threads", | |
| 219 cl::desc("Number of translation threads (0 for purely sequential)"), | |
| 220 // TODO(stichnot): Settle on a good default. Consider | |
| 221 // something related to std::thread::hardware_concurrency(). | |
| 222 cl::init(2)); | |
| 223 | |
| 224 static cl::opt<bool> DoNopInsertion("nop-insertion", | |
| 225 cl::desc("Randomly insert NOPs"), | |
| 226 cl::init(false)); | |
| 227 | |
| 228 static cl::opt<int> MaxNopsPerInstruction( | |
| 229 "max-nops-per-instruction", | |
| 230 cl::desc("Max number of nops to insert per instruction"), cl::init(1)); | |
| 231 | |
| 232 static cl::opt<int> NopProbabilityAsPercentage( | |
| 233 "nop-insertion-percentage", | |
| 234 cl::desc("Nop insertion probability as percentage"), cl::init(10)); | |
| 235 | |
| 236 static cl::opt<bool> | |
| 237 RandomizeRegisterAllocation("randomize-regalloc", | |
| 238 cl::desc("Randomize register allocation"), | |
| 239 cl::init(false)); | |
| 240 | |
| 241 // TODO(stichnot): See if we can easily use LLVM's -rng-seed option | |
| 242 // and implementation. I expect the implementation is different and | |
| 243 // therefore the tests would need to be changed. | |
| 244 cl::opt<unsigned long long> | |
| 245 RandomSeed("sz-seed", cl::desc("Seed the random number generator"), | |
| 246 cl::init(time(0))); | |
| 247 | |
| 248 static int GetReturnValue(int Val) { | |
| 249 if (AlwaysExitSuccess) | |
| 250 return 0; | |
| 251 return Val; | |
| 252 } | |
| 253 | |
| 254 static struct { | |
| 255 const char *FlagName; | |
| 256 int FlagValue; | |
| 257 } ConditionalBuildAttributes[] = {{"dump", ALLOW_DUMP}, | |
| 258 {"disable_ir_gen", ALLOW_DISABLE_IR_GEN}, | |
| 259 {"llvm_cl", ALLOW_LLVM_CL}, | |
| 260 {"llvm_ir", ALLOW_LLVM_IR}, | |
| 261 {"llvm_ir_as_input", ALLOW_LLVM_IR_AS_INPUT}, | |
| 262 {"minimal_build", ALLOW_MINIMAL_BUILD}}; | |
| 263 | |
| 264 // Validates values of build attributes. Prints them to Stream if | |
| 265 // Stream is non-null. | |
| 266 static void ValidateAndGenerateBuildAttributes(Ice::Ostream *Stream) { | |
| 267 | |
| 268 if (Stream) | |
| 269 *Stream << TargetArch << "\n"; | |
| 270 | |
| 271 for (size_t i = 0; i < array_lengthof(ConditionalBuildAttributes); ++i) { | |
| 272 switch (ConditionalBuildAttributes[i].FlagValue) { | |
| 273 case 0: | |
| 274 if (Stream) | |
| 275 *Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n"; | |
| 276 break; | |
| 277 case 1: | |
| 278 if (Stream) | |
| 279 *Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n"; | |
| 280 break; | |
| 281 default: { | |
| 282 std::string Buffer; | |
| 283 raw_string_ostream StrBuf(Buffer); | |
| 284 StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName | |
| 285 << " must be defined as 0/1. Found: " | |
| 286 << ConditionalBuildAttributes[i].FlagValue; | |
| 287 report_fatal_error(StrBuf.str()); | |
| 288 } | |
| 289 } | |
| 290 } | |
| 291 } | |
| 292 | 18 |
| 293 int main(int argc, char **argv) { | 19 int main(int argc, char **argv) { |
| 294 | 20 // Start file server and "wait" for compile request. |
| 295 cl::ParseCommandLineOptions(argc, argv); | 21 Ice::Compiler Comp; |
| 296 | 22 // Can only compile the BrowserCompileServer w/ the NaCl compiler. |
| 297 if (DisableIRGeneration) | 23 #if PNACL_BROWSER_TRANSLATOR |
| 298 DisableTranslation = true; | 24 // There are no real commandline arguments in the browser case. |
| 299 | 25 // They are supplied via IPC. |
| 300 Ice::VerboseMask VMask = Ice::IceV_None; | 26 assert(argc == 1); |
| 301 // Don't generate verbose messages if routines | 27 (void)argv; |
| 302 // to dump messages are not available. | 28 Ice::BrowserCompileServer Server(Comp); |
| 303 if (ALLOW_DUMP) { | 29 Server.run(); |
| 304 for (unsigned i = 0; i != VerboseList.size(); ++i) | 30 return Server.getErrorCode().value(); |
| 305 VMask |= VerboseList[i]; | 31 #else // !PNACL_BROWSER_TRANSLATOR |
| 306 } | 32 Ice::CLCompileServer Server(Comp, argc, argv); |
| 307 | 33 Server.run(); |
| 308 std::ofstream Lfs; | 34 return Server.getErrorCode().value(); |
| 309 std::unique_ptr<Ice::Ostream> Ls; | 35 #endif // !PNACL_BROWSER_TRANSLATOR |
| 310 if (LogFilename != "-") { | |
| 311 Lfs.open(LogFilename.c_str(), std::ofstream::out); | |
| 312 Ls.reset(new raw_os_ostream(Lfs)); | |
| 313 } else { | |
| 314 Ls.reset(new raw_os_ostream(std::cout)); | |
| 315 } | |
| 316 Ls->SetUnbuffered(); | |
| 317 | |
| 318 ValidateAndGenerateBuildAttributes(GenerateBuildAtts ? Ls.get() : nullptr); | |
| 319 if (GenerateBuildAtts) | |
| 320 return GetReturnValue(Ice::EC_None); | |
| 321 | |
| 322 if (!ALLOW_DISABLE_IR_GEN && DisableIRGeneration) { | |
| 323 *Ls << "Error: Build doesn't allow --no-ir-gen when not " | |
| 324 << "ALLOW_DISABLE_IR_GEN!\n"; | |
| 325 return GetReturnValue(Ice::EC_Args); | |
| 326 } | |
| 327 | |
| 328 Ice::ClFlags Flags; | |
| 329 Flags.setAllowErrorRecovery(AllowErrorRecovery); | |
| 330 Flags.setAllowUninitializedGlobals(AllowUninitializedGlobals); | |
| 331 Flags.setDataSections(DataSections); | |
| 332 Flags.setDecorateAsm(DecorateAsm); | |
| 333 Flags.setDefaultFunctionPrefix(DefaultFunctionPrefix); | |
| 334 Flags.setDefaultGlobalPrefix(DefaultGlobalPrefix); | |
| 335 Flags.setDisableInternal(DisableInternal); | |
| 336 Flags.setDisableIRGeneration(DisableIRGeneration); | |
| 337 Flags.setDisableTranslation(DisableTranslation); | |
| 338 Flags.setDumpStats(DumpStats); | |
| 339 Flags.setFunctionSections(FunctionSections); | |
| 340 Flags.setNumTranslationThreads(NumThreads); | |
| 341 Flags.setOptLevel(OptLevel); | |
| 342 Flags.setPhiEdgeSplit(EnablePhiEdgeSplit); | |
| 343 Flags.setRandomSeed(RandomSeed); | |
| 344 Flags.setShouldDoNopInsertion(DoNopInsertion); | |
| 345 Flags.setShouldRandomizeRegAlloc(RandomizeRegisterAllocation); | |
| 346 Flags.setSubzeroTimingEnabled(SubzeroTimingEnabled); | |
| 347 Flags.setTargetArch(TargetArch); | |
| 348 Flags.setTargetInstructionSet(InstructionSet); | |
| 349 Flags.setTestPrefix(TestPrefix); | |
| 350 Flags.setTimeEachFunction(TimeEachFunction); | |
| 351 Flags.setTimingFocusOn(TimingFocusOn); | |
| 352 Flags.setTranslateOnly(TranslateOnly); | |
| 353 Flags.setUseSandboxing(UseSandboxing); | |
| 354 Flags.setVerboseFocusOn(VerboseFocusOn); | |
| 355 Flags.setOutFileType(OutFileType); | |
| 356 Flags.setMaxNopsPerInstruction(MaxNopsPerInstruction); | |
| 357 Flags.setNopProbabilityAsPercentage(NopProbabilityAsPercentage); | |
| 358 Flags.setVerbose(VMask); | |
| 359 | |
| 360 // Force -build-on-read=0 for .ll files. | |
| 361 const std::string LLSuffix = ".ll"; | |
| 362 if (IRFilename.length() >= LLSuffix.length() && | |
| 363 IRFilename.compare(IRFilename.length() - LLSuffix.length(), | |
| 364 LLSuffix.length(), LLSuffix) == 0) | |
| 365 BuildOnRead = false; | |
| 366 | |
| 367 // With the ELF writer, use a raw_fd_ostream to allow seeking. | |
| 368 // Also don't buffer, otherwise it gets pretty slow. | |
| 369 std::unique_ptr<Ice::Ostream> Os; | |
| 370 std::unique_ptr<Ice::ELFStreamer> ELFStr; | |
| 371 std::ofstream Ofs; | |
| 372 switch (OutFileType) { | |
| 373 case Ice::FT_Elf: { | |
| 374 if (OutputFilename == "-") { | |
| 375 *Ls << "Error: writing binary ELF to stdout is unsupported\n"; | |
| 376 return GetReturnValue(Ice::EC_Args); | |
| 377 } | |
| 378 std::error_code EC; | |
| 379 raw_fd_ostream *FdOs = | |
| 380 new raw_fd_ostream(OutputFilename, EC, sys::fs::F_None); | |
| 381 // NaCl sets st_blksize to 0, and LLVM uses that to pick the | |
| 382 // default preferred buffer size. Set to something non-zero. | |
| 383 FdOs->SetBufferSize(1 << 14); | |
| 384 Os.reset(FdOs); | |
| 385 if (EC) { | |
| 386 *Ls << "Failed to open output file: " << OutputFilename << ":\n" | |
| 387 << EC.message() << "\n"; | |
| 388 return GetReturnValue(Ice::EC_Args); | |
| 389 } | |
| 390 ELFStr.reset(new Ice::ELFStreamer(*FdOs)); | |
| 391 } break; | |
| 392 case Ice::FT_Asm: | |
| 393 case Ice::FT_Iasm: { | |
| 394 if (OutputFilename != "-") { | |
| 395 Ofs.open(OutputFilename.c_str(), std::ofstream::out); | |
| 396 Os.reset(new raw_os_ostream(Ofs)); | |
| 397 } else { | |
| 398 Os.reset(new raw_os_ostream(std::cout)); | |
| 399 } | |
| 400 Os->SetUnbuffered(); | |
| 401 } break; | |
| 402 } | |
| 403 | |
| 404 Ice::GlobalContext Ctx(Ls.get(), Os.get(), ELFStr.get(), Flags); | |
| 405 | |
| 406 Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx); | |
| 407 | |
| 408 if (OutFileType == Ice::FT_Elf) { | |
| 409 Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); | |
| 410 Ctx.getObjectWriter()->writeInitialELFHeader(); | |
| 411 } | |
| 412 | |
| 413 Ctx.startWorkerThreads(); | |
| 414 | |
| 415 std::unique_ptr<Ice::Translator> Translator; | |
| 416 if (BuildOnRead) { | |
| 417 std::unique_ptr<Ice::PNaClTranslator> PTranslator( | |
| 418 new Ice::PNaClTranslator(&Ctx)); | |
| 419 std::string StrError; | |
| 420 std::unique_ptr<DataStreamer> FileStreamer( | |
| 421 getDataFileStreamer(IRFilename, &StrError)); | |
| 422 if (!StrError.empty() || !FileStreamer) { | |
| 423 SMDiagnostic Err(IRFilename, SourceMgr::DK_Error, StrError); | |
| 424 Err.print(argv[0], errs()); | |
| 425 return GetReturnValue(Ice::EC_Bitcode); | |
| 426 } | |
| 427 std::unique_ptr<StreamingMemoryObject> MemObj( | |
| 428 new StreamingMemoryObjectImpl(FileStreamer.release())); | |
| 429 PTranslator->translate(IRFilename, std::move(MemObj)); | |
| 430 Translator.reset(PTranslator.release()); | |
| 431 } else if (ALLOW_LLVM_IR) { | |
| 432 // Parse the input LLVM IR file into a module. | |
| 433 SMDiagnostic Err; | |
| 434 Ice::TimerMarker T1(Ice::TimerStack::TT_parse, &Ctx); | |
| 435 raw_ostream *Verbose = LLVMVerboseErrors ? &errs() : nullptr; | |
| 436 std::unique_ptr<Module> Mod = NaClParseIRFile( | |
| 437 IRFilename, InputFileFormat, Err, Verbose, getGlobalContext()); | |
| 438 if (!Mod) { | |
| 439 Err.print(argv[0], errs()); | |
| 440 return GetReturnValue(Ice::EC_Bitcode); | |
| 441 } | |
| 442 | |
| 443 std::unique_ptr<Ice::Converter> Converter( | |
| 444 new Ice::Converter(Mod.get(), &Ctx)); | |
| 445 Converter->convertToIce(); | |
| 446 Translator.reset(Converter.release()); | |
| 447 } else { | |
| 448 *Ls << "Error: Build doesn't allow LLVM IR, " | |
| 449 << "--build-on-read=0 not allowed\n"; | |
| 450 return GetReturnValue(Ice::EC_Args); | |
| 451 } | |
| 452 | |
| 453 Ctx.waitForWorkerThreads(); | |
| 454 Translator->transferErrorCode(); | |
| 455 Translator->emitConstants(); | |
| 456 | |
| 457 if (OutFileType == Ice::FT_Elf) { | |
| 458 Ice::TimerMarker T1(Ice::TimerStack::TT_emit, &Ctx); | |
| 459 Ctx.getObjectWriter()->setUndefinedSyms(Ctx.getConstantExternSyms()); | |
| 460 Ctx.getObjectWriter()->writeNonUserSections(); | |
| 461 } | |
| 462 if (SubzeroTimingEnabled) | |
| 463 Ctx.dumpTimers(); | |
| 464 if (TimeEachFunction) { | |
| 465 const bool DumpCumulative = false; | |
| 466 Ctx.dumpTimers(Ice::GlobalContext::TSK_Funcs, DumpCumulative); | |
| 467 } | |
| 468 const bool FinalStats = true; | |
| 469 Ctx.dumpStats("_FINAL_", FinalStats); | |
| 470 return GetReturnValue(Ctx.getErrorStatus()->value()); | |
| 471 } | 36 } |
| OLD | NEW |