Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: tools/pnacl-llc/pnacl-llc.cpp

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/pnacl-llc/ThreadedStreamingCache.cpp ('k') | tools/pnacl-llc/srpc_main.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 //===-- pnacl-llc.cpp - PNaCl-specific llc: pexe ---> nexe ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // pnacl-llc: the core of the PNaCl translator, compiling a pexe into a nexe.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/Triple.h"
15 #include "llvm/Analysis/NaCl.h"
16 #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
17 #include "llvm/Bitcode/ReaderWriter.h"
18 #include "llvm/CodeGen/CommandFlags.h"
19 #include "llvm/CodeGen/LinkAllCodegenComponents.h"
20 #include "llvm/IR/DataLayout.h"
21 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/Verifier.h"
24 #include "llvm/IRReader/IRReader.h"
25 #include "llvm/MC/SubtargetFeature.h"
26 #include "llvm/Pass.h"
27 #include "llvm/PassManager.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/DataStream.h"
30 #include "llvm/Support/Debug.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/FileSystem.h"
33 #include "llvm/Support/FormattedStream.h"
34 #include "llvm/Support/Host.h"
35 #include "llvm/Support/ManagedStatic.h"
36 #include "llvm/Support/PrettyStackTrace.h"
37 #include "llvm/Support/Signals.h"
38 #include "llvm/Support/SourceMgr.h"
39 #include "llvm/Support/StreamingMemoryObject.h"
40 #include "llvm/Support/TargetRegistry.h"
41 #include "llvm/Support/TargetSelect.h"
42 #include "llvm/Support/ToolOutputFile.h"
43 #include "llvm/Target/TargetLibraryInfo.h"
44 #include "llvm/Target/TargetMachine.h"
45 #include "llvm/Target/TargetSubtargetInfo.h"
46 #include "llvm/Transforms/NaCl.h"
47
48 #include "ThreadedFunctionQueue.h"
49 #include "ThreadedStreamingCache.h"
50
51 #include <pthread.h>
52 #include <memory>
53
54 using namespace llvm;
55
56 // NOTE: When PNACL_BROWSER_TRANSLATOR is defined it means pnacl-llc is built
57 // as a sandboxed translator (from pnacl-llc.pexe to pnacl-llc.nexe). In this
58 // mode it uses SRPC operations instead of direct OS intefaces.
59 #if defined(PNACL_BROWSER_TRANSLATOR)
60 int srpc_main(int argc, char **argv);
61 int getObjectFileFD(unsigned index);
62 DataStreamer *getNaClBitcodeStreamer();
63
64 fatal_error_handler_t getSRPCErrorHandler();
65 #endif
66
67 cl::opt<NaClFileFormat>
68 InputFileFormat(
69 "bitcode-format",
70 cl::desc("Define format of input file:"),
71 cl::values(
72 clEnumValN(LLVMFormat, "llvm", "LLVM file (default)"),
73 clEnumValN(PNaClFormat, "pnacl", "PNaCl bitcode file"),
74 clEnumValEnd),
75 #if defined(PNACL_BROWSER_TRANSLATOR)
76 cl::init(PNaClFormat)
77 #else
78 cl::init(LLVMFormat)
79 #endif
80 );
81
82 // General options for llc. Other pass-specific options are specified
83 // within the corresponding llc passes, and target-specific options
84 // and back-end code generation options are specified with the target machine.
85 //
86 static cl::opt<std::string>
87 InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
88
89 static cl::opt<std::string>
90 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
91
92 // Using bitcode streaming allows compilation of one function at a time. This
93 // allows earlier functions to be compiled before later functions are read from
94 // the bitcode but of course means no whole-module optimizations. This means
95 // that Module passes that run should only touch globals/function declarations
96 // and not function bodies, otherwise the streaming and non-streaming code
97 // pathes wouldn't emit the same code for each function. For now, streaming is
98 // only supported for files and stdin.
99 static cl::opt<bool>
100 LazyBitcode("streaming-bitcode",
101 cl::desc("Use lazy bitcode streaming for file inputs"),
102 cl::init(false));
103
104 static cl::opt<bool>
105 PNaClABIVerify("pnaclabi-verify",
106 cl::desc("Verify PNaCl bitcode ABI before translating"),
107 cl::init(false));
108 static cl::opt<bool>
109 PNaClABIVerifyFatalErrors("pnaclabi-verify-fatal-errors",
110 cl::desc("PNaCl ABI verification errors are fatal"),
111 cl::init(false));
112
113
114 static cl::opt<bool>
115 NoIntegratedAssembler("no-integrated-as", cl::Hidden,
116 cl::desc("Disable integrated assembler"));
117
118 // Determine optimization level.
119 static cl::opt<char>
120 OptLevel("O",
121 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
122 "(default = '-O2')"),
123 cl::Prefix,
124 cl::ZeroOrMore,
125 cl::init(' '));
126
127 static cl::opt<std::string>
128 UserDefinedTriple("mtriple", cl::desc("Set target triple"));
129
130 static cl::opt<bool> NoVerify("disable-verify", cl::Hidden,
131 cl::desc("Do not verify input module"));
132
133 static cl::opt<bool>
134 DisableSimplifyLibCalls("disable-simplify-libcalls",
135 cl::desc("Disable simplify-libcalls"));
136
137 static cl::opt<unsigned>
138 SplitModuleCount("split-module",
139 cl::desc("Split PNaCl module"), cl::init(1U));
140
141 enum SplitModuleSchedulerKind {
142 SplitModuleDynamic,
143 SplitModuleStatic
144 };
145
146 static cl::opt<SplitModuleSchedulerKind>
147 SplitModuleSched(
148 "split-module-sched",
149 cl::desc("Choose thread scheduler for split module compilation."),
150 cl::values(
151 clEnumValN(SplitModuleDynamic, "dynamic",
152 "Dynamic thread scheduling (default)"),
153 clEnumValN(SplitModuleStatic, "static",
154 "Static thread scheduling"),
155 clEnumValEnd),
156 cl::init(SplitModuleDynamic));
157
158 /// Compile the module provided to pnacl-llc. The file name for reading the
159 /// module and other options are taken from globals populated by command-line
160 /// option parsing.
161 static int compileModule(StringRef ProgramName);
162
163 #if !defined(PNACL_BROWSER_TRANSLATOR)
164 // GetFileNameRoot - Helper function to get the basename of a filename.
165 static std::string
166 GetFileNameRoot(StringRef InputFilename) {
167 std::string IFN = InputFilename;
168 std::string outputFilename;
169 int Len = IFN.length();
170 if ((Len > 2) &&
171 IFN[Len-3] == '.' &&
172 ((IFN[Len-2] == 'b' && IFN[Len-1] == 'c') ||
173 (IFN[Len-2] == 'l' && IFN[Len-1] == 'l'))) {
174 outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
175 } else {
176 outputFilename = IFN;
177 }
178 return outputFilename;
179 }
180
181 static tool_output_file *GetOutputStream(const char *TargetName,
182 Triple::OSType OS,
183 std::string Filename) {
184 // If we don't yet have an output filename, make one.
185 if (Filename.empty()) {
186 if (InputFilename == "-")
187 Filename = "-";
188 else {
189 Filename = GetFileNameRoot(InputFilename);
190
191 switch (FileType) {
192 case TargetMachine::CGFT_AssemblyFile:
193 if (TargetName[0] == 'c') {
194 if (TargetName[1] == 0)
195 Filename += ".cbe.c";
196 else if (TargetName[1] == 'p' && TargetName[2] == 'p')
197 Filename += ".cpp";
198 else
199 Filename += ".s";
200 } else
201 Filename += ".s";
202 break;
203 case TargetMachine::CGFT_ObjectFile:
204 if (OS == Triple::Win32)
205 Filename += ".obj";
206 else
207 Filename += ".o";
208 break;
209 case TargetMachine::CGFT_Null:
210 Filename += ".null";
211 break;
212 }
213 }
214 }
215
216 // Decide if we need "binary" output.
217 bool Binary = false;
218 switch (FileType) {
219 case TargetMachine::CGFT_AssemblyFile:
220 break;
221 case TargetMachine::CGFT_ObjectFile:
222 case TargetMachine::CGFT_Null:
223 Binary = true;
224 break;
225 }
226
227 // Open the file.
228 std::error_code EC;
229 sys::fs::OpenFlags OpenFlags = sys::fs::F_None;
230 if (!Binary)
231 OpenFlags |= sys::fs::F_Text;
232 tool_output_file *FDOut = new tool_output_file(Filename, EC, OpenFlags);
233 if (EC) {
234 errs() << EC.message() << '\n';
235 delete FDOut;
236 return nullptr;
237 }
238
239 return FDOut;
240 }
241 #endif // !defined(PNACL_BROWSER_TRANSLATOR)
242
243 // main - Entry point for the llc compiler.
244 //
245 int llc_main(int argc, char **argv) {
246 sys::PrintStackTraceOnErrorSignal();
247 PrettyStackTraceProgram X(argc, argv);
248
249 // Enable debug stream buffering.
250 EnableDebugBuffering = true;
251
252 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
253
254 #if defined(PNACL_BROWSER_TRANSLATOR)
255 install_fatal_error_handler(getSRPCErrorHandler(), nullptr);
256 #endif
257
258 // Initialize targets first, so that --version shows registered targets.
259 InitializeAllTargets();
260 InitializeAllTargetMCs();
261 InitializeAllAsmPrinters();
262 #if !defined(PNACL_BROWSER_TRANSLATOR)
263 // Prune asm parsing from sandboxed translator.
264 // Do not prune "AsmPrinters" because that includes
265 // the direct object emission.
266 InitializeAllAsmParsers();
267 #endif
268
269 // Initialize codegen and IR passes used by pnacl-llc so that the -print-after ,
270 // -print-before, and -stop-after options work.
271 PassRegistry *Registry = PassRegistry::getPassRegistry();
272 initializeCore(*Registry);
273 initializeCodeGen(*Registry);
274 initializeLoopStrengthReducePass(*Registry);
275 initializeLowerIntrinsicsPass(*Registry);
276 initializeUnreachableBlockElimPass(*Registry);
277
278 // Register the target printer for --version.
279 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
280
281 // Enable the PNaCl ABI verifier by default in sandboxed mode.
282 #if defined(PNACL_BROWSER_TRANSLATOR)
283 PNaClABIVerify = true;
284 PNaClABIVerifyFatalErrors = true;
285 #endif
286
287 cl::ParseCommandLineOptions(argc, argv, "pnacl-llc\n");
288
289 #if defined(PNACL_BROWSER_TRANSLATOR)
290 // If the user explicitly requests LLVM format in sandboxed mode
291 // (where the default is PNaCl format), they probably want debug
292 // metadata enabled.
293 if (InputFileFormat == LLVMFormat) {
294 PNaClABIAllowDebugMetadata = true;
295 }
296 #endif
297
298 if (SplitModuleCount > 1)
299 LLVMStartMultithreaded();
300
301 return compileModule(argv[0]);
302 }
303
304 static void CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter,
305 const Twine &Name) {
306 if (PNaClABIVerify && Reporter.getErrorCount() > 0) {
307 std::string errors;
308 raw_string_ostream os(errors);
309 os << (PNaClABIVerifyFatalErrors ? "ERROR: " : "WARNING: ");
310 os << Name << " is not valid PNaCl bitcode:\n";
311 Reporter.printErrors(os);
312 if (PNaClABIVerifyFatalErrors) {
313 report_fatal_error(os.str());
314 }
315 errs() << os.str();
316 }
317 Reporter.reset();
318 }
319
320 static std::unique_ptr<Module> getModule(
321 StringRef ProgramName, LLVMContext &Context,
322 StreamingMemoryObject *StreamingObject) {
323 std::unique_ptr<Module> M;
324 SMDiagnostic Err;
325 std::string VerboseBuffer;
326 raw_string_ostream VerboseStrm(VerboseBuffer);
327 if (LazyBitcode) {
328 std::string StrError;
329 switch (InputFileFormat) {
330 case PNaClFormat:
331 M.reset(getNaClStreamedBitcodeModule(
332 InputFilename,
333 new ThreadedStreamingCache(StreamingObject), Context, &VerboseStrm,
334 &StrError));
335 break;
336 case LLVMFormat:
337 M.reset(getStreamedBitcodeModule(
338 InputFilename,
339 new ThreadedStreamingCache(StreamingObject), Context, &StrError));
340 break;
341 case AutodetectFileFormat:
342 report_fatal_error("Command can't autodetect file format!");
343 }
344 if (!StrError.empty())
345 Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError);
346 } else {
347 #if defined(PNACL_BROWSER_TRANSLATOR)
348 llvm_unreachable("native client SRPC only supports streaming");
349 #else
350 // Parses binary bitcode as well as textual assembly
351 // (so pulls in more code into pnacl-llc).
352 M = NaClParseIRFile(InputFilename, InputFileFormat, Err, &VerboseStrm,
353 Context);
354 #endif
355 }
356 if (!M) {
357 #if defined(PNACL_BROWSER_TRANSLATOR)
358 report_fatal_error(VerboseStrm.str() + Err.getMessage());
359 #else
360 // Err.print is prettier, so use it for the non-sandboxed translator.
361 Err.print(ProgramName.data(), errs());
362 errs() << VerboseStrm.str();
363 return nullptr;
364 #endif
365 }
366 return std::move(M);
367 }
368
369 static cl::opt<bool>
370 ExternalizeAll("externalize",
371 cl::desc("Externalize all symbols"),
372 cl::init(false));
373
374 static int runCompilePasses(Module *ModuleRef,
375 unsigned ModuleIndex,
376 ThreadedFunctionQueue *FuncQueue,
377 const Triple &TheTriple,
378 TargetMachine &Target,
379 StringRef ProgramName,
380 formatted_raw_ostream &FOS){
381 PNaClABIErrorReporter ABIErrorReporter;
382
383 if (SplitModuleCount > 1 || ExternalizeAll) {
384 // Add function and global names, and give them external linkage.
385 // This relies on LLVM's consistent auto-generation of names, we could
386 // maybe do our own in case something changes there.
387 for (Function &F : *ModuleRef) {
388 if (!F.hasName())
389 F.setName("Function");
390 if (F.hasInternalLinkage())
391 F.setLinkage(GlobalValue::ExternalLinkage);
392 }
393 for (Module::global_iterator GI = ModuleRef->global_begin(),
394 GE = ModuleRef->global_end();
395 GI != GE; ++GI) {
396 if (!GI->hasName())
397 GI->setName("Global");
398 if (GI->hasInternalLinkage())
399 GI->setLinkage(GlobalValue::ExternalLinkage);
400 }
401 if (ModuleIndex > 0) {
402 // Remove the initializers for all global variables, turning them into
403 // declarations.
404 for (Module::global_iterator GI = ModuleRef->global_begin(),
405 GE = ModuleRef->global_end();
406 GI != GE; ++GI) {
407 assert(GI->hasInitializer() && "Global variable missing initializer");
408 Constant *Init = GI->getInitializer();
409 GI->setInitializer(nullptr);
410 if (Init->getNumUses() == 0)
411 Init->destroyConstant();
412 }
413 }
414 }
415
416 // Make all non-weak symbols hidden for better code. We cannot do
417 // this for weak symbols. The linker complains when some weak
418 // symbols are not resolved.
419 for (Function &F : *ModuleRef) {
420 if (!F.isWeakForLinker() && !F.hasLocalLinkage())
421 F.setVisibility(GlobalValue::HiddenVisibility);
422 }
423 for (Module::global_iterator GI = ModuleRef->global_begin(),
424 GE = ModuleRef->global_end();
425 GI != GE; ++GI) {
426 if (!GI->isWeakForLinker() && !GI->hasLocalLinkage())
427 GI->setVisibility(GlobalValue::HiddenVisibility);
428 }
429
430 // Build up all of the passes that we want to do to the module.
431 std::unique_ptr<PassManagerBase> PM;
432 if (LazyBitcode)
433 PM.reset(new FunctionPassManager(ModuleRef));
434 else
435 PM.reset(new PassManager());
436
437 // Add the target data from the target machine, if it exists, or the module.
438 if (const DataLayout *DL = Target.getSubtargetImpl()->getDataLayout())
439 ModuleRef->setDataLayout(DL);
440 PM->add(new DataLayoutPass());
441
442 // For conformance with llc, we let the user disable LLVM IR verification with
443 // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only
444 // run it once, before PNaCl ABI verification.
445 if (!NoVerify)
446 PM->add(createVerifierPass());
447
448 // Add the ABI verifier pass before the analysis and code emission passes.
449 if (PNaClABIVerify)
450 PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter));
451
452 // Add the intrinsic resolution pass. It assumes ABI-conformant code.
453 PM->add(createResolvePNaClIntrinsicsPass());
454
455 // Add an appropriate TargetLibraryInfo pass for the module's triple.
456 TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple);
457 if (DisableSimplifyLibCalls)
458 TLI->disableAllFunctions();
459 PM->add(TLI);
460
461 // Allow subsequent passes and the backend to better optimize instructions
462 // that were simplified for PNaCl's ABI. This pass uses the TargetLibraryInfo
463 // above.
464 PM->add(createBackendCanonicalizePass());
465
466 // Add internal analysis passes from the target machine.
467 Target.addAnalysisPasses(*PM);
468
469 // Ask the target to add backend passes as necessary. We explicitly ask it
470 // not to add the verifier pass because we added it earlier.
471 if (Target.addPassesToEmitFile(*PM, FOS, FileType,
472 /* DisableVerify */ true)) {
473 errs() << ProgramName
474 << ": target does not support generation of this file type!\n";
475 return 1;
476 }
477
478 if (LazyBitcode) {
479 auto FPM = static_cast<FunctionPassManager *>(PM.get());
480 FPM->doInitialization();
481 unsigned FuncIndex = 0;
482 switch (SplitModuleSched) {
483 case SplitModuleStatic:
484 for (Function &F : *ModuleRef) {
485 if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) {
486 FPM->run(F);
487 CheckABIVerifyErrors(ABIErrorReporter, "Function " + F.getName());
488 F.Dematerialize();
489 }
490 ++FuncIndex;
491 }
492 break;
493 case SplitModuleDynamic:
494 unsigned ChunkSize = 0;
495 unsigned NumFunctions = FuncQueue->Size();
496 Module::iterator I = ModuleRef->begin();
497 while (FuncIndex < NumFunctions) {
498 ChunkSize = FuncQueue->RecommendedChunkSize();
499 unsigned NextIndex;
500 bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize,
501 NextIndex);
502 if (grabbed) {
503 while (FuncIndex < NextIndex) {
504 if (!I->isMaterializable() && I->isDeclaration()) {
505 ++I;
506 continue;
507 }
508 FPM->run(*I);
509 CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
510 I->Dematerialize();
511 ++FuncIndex;
512 ++I;
513 }
514 } else {
515 while (FuncIndex < NextIndex) {
516 if (!I->isMaterializable() && I->isDeclaration()) {
517 ++I;
518 continue;
519 }
520 ++FuncIndex;
521 ++I;
522 }
523 }
524 }
525 break;
526 }
527 FPM->doFinalization();
528 } else
529 static_cast<PassManager *>(PM.get())->run(*ModuleRef);
530
531 return 0;
532 }
533
534 static int compileSplitModule(const TargetOptions &Options,
535 const Triple &TheTriple,
536 const Target *TheTarget,
537 const std::string &FeaturesStr,
538 CodeGenOpt::Level OLvl,
539 const StringRef &ProgramName,
540 Module *GlobalModuleRef,
541 StreamingMemoryObject *StreamingObject,
542 unsigned ModuleIndex,
543 ThreadedFunctionQueue *FuncQueue) {
544 std::auto_ptr<TargetMachine>
545 target(TheTarget->createTargetMachine(TheTriple.getTriple(),
546 MCPU, FeaturesStr, Options,
547 RelocModel, CMModel, OLvl));
548 assert(target.get() && "Could not allocate target machine!");
549 TargetMachine &Target = *target.get();
550 // Override default to generate verbose assembly.
551 Target.setAsmVerbosityDefault(true);
552 if (RelaxAll.getNumOccurrences() > 0 &&
553 FileType != TargetMachine::CGFT_ObjectFile)
554 errs() << ProgramName
555 << ": warning: ignoring -mc-relax-all because filetype != obj";
556 // The OwningPtrs are only used if we are not the primary module.
557 std::unique_ptr<LLVMContext> C;
558 std::unique_ptr<Module> M;
559 Module *ModuleRef = nullptr;
560
561 if (ModuleIndex == 0) {
562 ModuleRef = GlobalModuleRef;
563 } else {
564 C.reset(new LLVMContext());
565 M = getModule(ProgramName, *C, StreamingObject);
566 if (!M)
567 return 1;
568 // M owns the temporary module, but use a reference through ModuleRef
569 // to also work in the case we are using GlobalModuleRef.
570 ModuleRef = M.get();
571
572 // Add declarations for external functions required by PNaCl. The
573 // ResolvePNaClIntrinsics function pass running during streaming
574 // depends on these declarations being in the module.
575 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass(
576 createAddPNaClExternalDeclsPass());
577 AddPNaClExternalDeclsPass->runOnModule(*ModuleRef);
578 AddPNaClExternalDeclsPass.reset();
579 }
580
581 ModuleRef->setTargetTriple(Triple::normalize(UserDefinedTriple));
582
583 {
584 #if !defined(PNACL_BROWSER_TRANSLATOR)
585 // Figure out where we are going to send the output.
586 std::string N(OutputFilename);
587 raw_string_ostream OutFileName(N);
588 if (ModuleIndex > 0)
589 OutFileName << ".module" << ModuleIndex;
590 std::unique_ptr<tool_output_file> Out
591 (GetOutputStream(TheTarget->getName(), TheTriple.getOS(),
592 OutFileName.str()));
593 if (!Out) return 1;
594 formatted_raw_ostream FOS(Out->os());
595 #else
596 raw_fd_ostream ROS(getObjectFileFD(ModuleIndex), /* ShouldClose */ true);
597 ROS.SetBufferSize(1 << 20);
598 formatted_raw_ostream FOS(ROS);
599 #endif
600 int ret = runCompilePasses(ModuleRef, ModuleIndex, FuncQueue,
601 TheTriple, Target, ProgramName,
602 FOS);
603 if (ret)
604 return ret;
605 #if defined(PNACL_BROWSER_TRANSLATOR)
606 FOS.flush();
607 ROS.flush();
608 #else
609 // Declare success.
610 Out->keep();
611 #endif // PNACL_BROWSER_TRANSLATOR
612 }
613 return 0;
614 }
615
616 struct ThreadData {
617 const TargetOptions *Options;
618 const Triple *TheTriple;
619 const Target *TheTarget;
620 std::string FeaturesStr;
621 CodeGenOpt::Level OLvl;
622 std::string ProgramName;
623 Module *GlobalModuleRef;
624 StreamingMemoryObject *StreamingObject;
625 unsigned ModuleIndex;
626 ThreadedFunctionQueue *FuncQueue;
627 };
628
629
630 static void *runCompileThread(void *arg) {
631 struct ThreadData *Data = static_cast<ThreadData *>(arg);
632 int ret = compileSplitModule(*Data->Options,
633 *Data->TheTriple,
634 Data->TheTarget,
635 Data->FeaturesStr,
636 Data->OLvl,
637 Data->ProgramName,
638 Data->GlobalModuleRef,
639 Data->StreamingObject,
640 Data->ModuleIndex,
641 Data->FuncQueue);
642 return reinterpret_cast<void *>(static_cast<intptr_t>(ret));
643 }
644
645 static int compileModule(StringRef ProgramName) {
646 // Use a new context instead of the global context for the main module. It mus t
647 // outlive the module object, declared below. We do this because
648 // lib/CodeGen/PseudoSourceValue.cpp gets a type from the global context and
649 // races with any other use of the context. Rather than doing an invasive
650 // plumbing change to fix it, we work around it by using a new context here
651 // and leaving PseudoSourceValue as the only user of the global context.
652 std::unique_ptr<LLVMContext> MainContext(new LLVMContext());
653 std::unique_ptr<Module> MainMod;
654 Triple TheTriple;
655 PNaClABIErrorReporter ABIErrorReporter;
656 std::unique_ptr<StreamingMemoryObject> StreamingObject;
657
658 if (!MainContext) return 1;
659
660 #if defined(PNACL_BROWSER_TRANSLATOR)
661 StreamingObject.reset(
662 new StreamingMemoryObjectImpl(getNaClBitcodeStreamer()));
663 #else
664 if (LazyBitcode) {
665 std::string StrError;
666 DataStreamer* FileStreamer(getDataFileStreamer(InputFilename, &StrError));
667 if (!StrError.empty()) {
668 SMDiagnostic Err(InputFilename, SourceMgr::DK_Error, StrError);
669 Err.print(ProgramName.data(), errs());
670 }
671 if (!FileStreamer)
672 return 1;
673 StreamingObject.reset(new StreamingMemoryObjectImpl(FileStreamer));
674 }
675 #endif
676 MainMod = getModule(ProgramName, *MainContext.get(), StreamingObject.get());
677
678 if (!MainMod) return 1;
679
680 if (PNaClABIVerify) {
681 // Verify the module (but not the functions yet)
682 std::unique_ptr<ModulePass> VerifyPass(
683 createPNaClABIVerifyModulePass(&ABIErrorReporter, LazyBitcode));
684 VerifyPass->runOnModule(*MainMod);
685 CheckABIVerifyErrors(ABIErrorReporter, "Module");
686 VerifyPass.reset();
687 }
688
689 // Add declarations for external functions required by PNaCl. The
690 // ResolvePNaClIntrinsics function pass running during streaming
691 // depends on these declarations being in the module.
692 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass(
693 createAddPNaClExternalDeclsPass());
694 AddPNaClExternalDeclsPass->runOnModule(*MainMod);
695 AddPNaClExternalDeclsPass.reset();
696
697 if (UserDefinedTriple.empty()) {
698 report_fatal_error("-mtriple must be set to a target triple for pnacl-llc");
699 } else {
700 MainMod->setTargetTriple(Triple::normalize(UserDefinedTriple));
701 TheTriple = Triple(MainMod->getTargetTriple());
702 }
703
704 // Get the target specific parser.
705 std::string Error;
706 const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
707 Error);
708 if (!TheTarget) {
709 errs() << ProgramName << ": " << Error;
710 return 1;
711 }
712
713 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
714 Options.DisableIntegratedAS = NoIntegratedAssembler;
715
716 if (GenerateSoftFloatCalls)
717 FloatABIForCalls = FloatABI::Soft;
718
719 // Package up features to be passed to target/subtarget
720 std::string FeaturesStr;
721 if (MAttrs.size()) {
722 SubtargetFeatures Features;
723 for (unsigned i = 0; i != MAttrs.size(); ++i)
724 Features.AddFeature(MAttrs[i]);
725 FeaturesStr = Features.getString();
726 }
727
728 CodeGenOpt::Level OLvl = CodeGenOpt::Default;
729 switch (OptLevel) {
730 default:
731 errs() << ProgramName << ": invalid optimization level.\n";
732 return 1;
733 case ' ': break;
734 case '0': OLvl = CodeGenOpt::None; break;
735 case '1': OLvl = CodeGenOpt::Less; break;
736 case '2': OLvl = CodeGenOpt::Default; break;
737 case '3': OLvl = CodeGenOpt::Aggressive; break;
738 }
739
740 SmallVector<pthread_t, 4> Pthreads(SplitModuleCount);
741 SmallVector<ThreadData, 4> ThreadDatas(SplitModuleCount);
742 ThreadedFunctionQueue FuncQueue(MainMod.get(), SplitModuleCount);
743
744 if (SplitModuleCount == 1) {
745 // No need for dynamic scheduling with one thread.
746 SplitModuleSched = SplitModuleStatic;
747 return compileSplitModule(Options, TheTriple, TheTarget, FeaturesStr,
748 OLvl, ProgramName, MainMod.get(), nullptr, 0,
749 &FuncQueue);
750 }
751
752 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) {
753 ThreadDatas[ModuleIndex].Options = &Options;
754 ThreadDatas[ModuleIndex].TheTriple = &TheTriple;
755 ThreadDatas[ModuleIndex].TheTarget = TheTarget;
756 ThreadDatas[ModuleIndex].FeaturesStr = FeaturesStr;
757 ThreadDatas[ModuleIndex].OLvl = OLvl;
758 ThreadDatas[ModuleIndex].ProgramName = ProgramName.str();
759 ThreadDatas[ModuleIndex].GlobalModuleRef = MainMod.get();
760 ThreadDatas[ModuleIndex].StreamingObject = StreamingObject.get();
761 ThreadDatas[ModuleIndex].ModuleIndex = ModuleIndex;
762 ThreadDatas[ModuleIndex].FuncQueue = &FuncQueue;
763 if (pthread_create(&Pthreads[ModuleIndex], nullptr, runCompileThread,
764 &ThreadDatas[ModuleIndex])) {
765 report_fatal_error("Failed to create thread");
766 }
767 }
768 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) {
769 void *retval;
770 if (pthread_join(Pthreads[ModuleIndex], &retval))
771 report_fatal_error("Failed to join thread");
772 intptr_t ret = reinterpret_cast<intptr_t>(retval);
773 if (ret != 0)
774 report_fatal_error("Thread returned nonzero");
775 }
776 return 0;
777 }
778
779 int main(int argc, char **argv) {
780 #if defined(PNACL_BROWSER_TRANSLATOR)
781 return srpc_main(argc, argv);
782 #else
783 return llc_main(argc, argv);
784 #endif // PNACL_BROWSER_TRANSLATOR
785 }
OLDNEW
« no previous file with comments | « tools/pnacl-llc/ThreadedStreamingCache.cpp ('k') | tools/pnacl-llc/srpc_main.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698