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 |