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

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

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: 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
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 Module* getModule(StringRef ProgramName, LLVMContext &Context,
321 StreamingMemoryObject *StreamingObject) {
322 std::unique_ptr<Module> M;
323 SMDiagnostic Err;
324 std::string VerboseBuffer;
325 raw_string_ostream VerboseStrm(VerboseBuffer);
326 if (LazyBitcode) {
327 std::string StrError;
328 switch (InputFileFormat) {
329 case PNaClFormat:
330 M.reset(getNaClStreamedBitcodeModule(
331 InputFilename,
332 new ThreadedStreamingCache(StreamingObject), Context, &VerboseStrm,
333 &StrError));
334 break;
335 case LLVMFormat:
336 M.reset(getStreamedBitcodeModule(
337 InputFilename,
338 new ThreadedStreamingCache(StreamingObject), Context, &StrError));
339 break;
340 case AutodetectFileFormat:
341 report_fatal_error("Command can't autodetect file format!");
342 }
343 if (!StrError.empty())
344 Err = SMDiagnostic(InputFilename, SourceMgr::DK_Error, StrError);
345 } else {
346 #if defined(PNACL_BROWSER_TRANSLATOR)
347 llvm_unreachable("native client SRPC only supports streaming");
348 #else
349 // Parses binary bitcode as well as textual assembly
350 // (so pulls in more code into pnacl-llc).
351 M = NaClParseIRFile(InputFilename, InputFileFormat, Err, &VerboseStrm,
352 Context);
353 #endif
354 }
355 if (!M) {
356 #if defined(PNACL_BROWSER_TRANSLATOR)
357 report_fatal_error(VerboseStrm.str() + Err.getMessage());
358 #else
359 // Err.print is prettier, so use it for the non-sandboxed translator.
360 Err.print(ProgramName.data(), errs());
361 errs() << VerboseStrm.str();
362 return nullptr;
363 #endif
364 }
365 return M.release();
366 }
367
368 static cl::opt<bool>
369 ExternalizeAll("externalize",
370 cl::desc("Externalize all symbols"),
371 cl::init(false));
372
373 static int runCompilePasses(Module *mod,
374 unsigned ModuleIndex,
375 ThreadedFunctionQueue *FuncQueue,
376 const Triple &TheTriple,
377 TargetMachine &Target,
378 StringRef ProgramName,
379 formatted_raw_ostream &FOS){
380 PNaClABIErrorReporter ABIErrorReporter;
381
382 if (SplitModuleCount > 1 || ExternalizeAll) {
383 // Add function and global names, and give them external linkage.
384 // This relies on LLVM's consistent auto-generation of names, we could
385 // maybe do our own in case something changes there.
386 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
387 if (!I->hasName())
388 I->setName("Function");
389 if (I->hasInternalLinkage())
390 I->setLinkage(GlobalValue::ExternalLinkage);
391 }
392 for (Module::global_iterator GI = mod->global_begin(),
393 GE = mod->global_end();
394 GI != GE; ++GI) {
395 if (!GI->hasName())
396 GI->setName("Global");
397 if (GI->hasInternalLinkage())
398 GI->setLinkage(GlobalValue::ExternalLinkage);
399 }
400 if (ModuleIndex > 0) {
401 // Remove the initializers for all global variables, turning them into
402 // declarations.
403 for (Module::global_iterator GI = mod->global_begin(),
404 GE = mod->global_end();
405 GI != GE; ++GI) {
406 assert(GI->hasInitializer() && "Global variable missing initializer");
407 Constant *Init = GI->getInitializer();
408 GI->setInitializer(nullptr);
409 if (Init->getNumUses() == 0)
410 Init->destroyConstant();
411 }
412 }
413 }
414
415 // Make all non-weak symbols hidden for better code. We cannot do
416 // this for weak symbols. The linker complains when some weak
417 // symbols are not resolved.
418 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
419 if (!I->isWeakForLinker() && !I->hasLocalLinkage())
420 I->setVisibility(GlobalValue::HiddenVisibility);
421 }
422 for (Module::global_iterator GI = mod->global_begin(),
423 GE = mod->global_end();
424 GI != GE; ++GI) {
425 if (!GI->isWeakForLinker() && !GI->hasLocalLinkage())
426 GI->setVisibility(GlobalValue::HiddenVisibility);
427 }
428
429 // Build up all of the passes that we want to do to the module.
430 std::unique_ptr<PassManagerBase> PM;
431 if (LazyBitcode)
432 PM.reset(new FunctionPassManager(mod));
433 else
434 PM.reset(new PassManager());
435
436 // Add the target data from the target machine, if it exists, or the module.
437 if (const DataLayout *DL = Target.getSubtargetImpl()->getDataLayout())
438 mod->setDataLayout(DL);
439 PM->add(new DataLayoutPass());
440
441 // For conformance with llc, we let the user disable LLVM IR verification with
442 // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only
443 // run it once, before PNaCl ABI verification.
444 if (!NoVerify)
445 PM->add(createVerifierPass());
446
447 // Add the ABI verifier pass before the analysis and code emission passes.
448 if (PNaClABIVerify)
449 PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter));
450
451 // Add the intrinsic resolution pass. It assumes ABI-conformant code.
452 PM->add(createResolvePNaClIntrinsicsPass());
453
454 // Add an appropriate TargetLibraryInfo pass for the module's triple.
455 TargetLibraryInfo *TLI = new TargetLibraryInfo(TheTriple);
456 if (DisableSimplifyLibCalls)
457 TLI->disableAllFunctions();
458 PM->add(TLI);
459
460 // Allow subsequent passes and the backend to better optimize instructions
461 // that were simplified for PNaCl's ABI. This pass uses the TargetLibraryInfo
462 // above.
463 PM->add(createBackendCanonicalizePass());
464
465 // Add internal analysis passes from the target machine.
466 Target.addAnalysisPasses(*PM);
467
468 // Ask the target to add backend passes as necessary. We explicitly ask it
469 // not to add the verifier pass because we added it earlier.
470 if (Target.addPassesToEmitFile(*PM, FOS, FileType,
471 /* DisableVerify */ true)) {
472 errs() << ProgramName
473 << ": target does not support generation of this file type!\n";
474 return 1;
475 }
476
477 if (LazyBitcode) {
478 auto FPM = static_cast<FunctionPassManager *>(PM.get());
479 FPM->doInitialization();
480 unsigned FuncIndex = 0;
481 switch (SplitModuleSched) {
482 case SplitModuleStatic:
483 for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
484 if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) {
485 FPM->run(*I);
486 CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
487 I->Dematerialize();
488 }
489 ++FuncIndex;
490 }
491 break;
492 case SplitModuleDynamic:
493 unsigned ChunkSize = 0;
494 unsigned NumFunctions = FuncQueue->Size();
495 Module::iterator I = mod->begin();
496 while (FuncIndex < NumFunctions) {
497 ChunkSize = FuncQueue->RecommendedChunkSize();
498 unsigned NextIndex;
499 bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize,
500 NextIndex);
501 if (grabbed) {
502 while (FuncIndex < NextIndex) {
503 if (!I->isMaterializable() && I->isDeclaration()) {
504 ++I;
505 continue;
506 }
507 FPM->run(*I);
508 CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
509 I->Dematerialize();
510 ++FuncIndex;
511 ++I;
512 }
513 } else {
514 while (FuncIndex < NextIndex) {
515 if (!I->isMaterializable() && I->isDeclaration()) {
516 ++I;
517 continue;
518 }
519 ++FuncIndex;
520 ++I;
521 }
522 }
523 }
524 break;
525 }
526 FPM->doFinalization();
527 } else
528 static_cast<PassManager *>(PM.get())->run(*mod);
529
530 return 0;
531 }
532
533 static int compileSplitModule(const TargetOptions &Options,
534 const Triple &TheTriple,
535 const Target *TheTarget,
536 const std::string &FeaturesStr,
537 CodeGenOpt::Level OLvl,
538 const StringRef &ProgramName,
539 Module *GlobalModule,
540 StreamingMemoryObject *StreamingObject,
541 unsigned ModuleIndex,
542 ThreadedFunctionQueue *FuncQueue) {
543 std::auto_ptr<TargetMachine>
544 target(TheTarget->createTargetMachine(TheTriple.getTriple(),
545 MCPU, FeaturesStr, Options,
546 RelocModel, CMModel, OLvl));
547 assert(target.get() && "Could not allocate target machine!");
548 TargetMachine &Target = *target.get();
549 // Override default to generate verbose assembly.
550 Target.setAsmVerbosityDefault(true);
551 if (RelaxAll.getNumOccurrences() > 0 &&
552 FileType != TargetMachine::CGFT_ObjectFile)
553 errs() << ProgramName
554 << ": warning: ignoring -mc-relax-all because filetype != obj";
555 // The OwningPtrs are only used if we are not the primary module.
556 std::unique_ptr<LLVMContext> C;
557 std::unique_ptr<Module> M;
558 Module *mod(nullptr);
559
560 if (ModuleIndex == 0) {
561 mod = GlobalModule;
562 } else {
563 C.reset(new LLVMContext());
564 mod = getModule(ProgramName, *C, StreamingObject);
565 if (!mod)
566 return 1;
567 M.reset(mod);
568
569 // Add declarations for external functions required by PNaCl. The
570 // ResolvePNaClIntrinsics function pass running during streaming
571 // depends on these declarations being in the module.
572 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass(
573 createAddPNaClExternalDeclsPass());
574 AddPNaClExternalDeclsPass->runOnModule(*M);
575 AddPNaClExternalDeclsPass.reset();
576 }
577
578 mod->setTargetTriple(Triple::normalize(UserDefinedTriple));
579
580 {
581 #if !defined(PNACL_BROWSER_TRANSLATOR)
582 // Figure out where we are going to send the output.
583 std::string N(OutputFilename);
584 raw_string_ostream OutFileName(N);
585 if (ModuleIndex > 0)
586 OutFileName << ".module" << ModuleIndex;
587 std::unique_ptr<tool_output_file> Out
588 (GetOutputStream(TheTarget->getName(), TheTriple.getOS(),
589 OutFileName.str()));
590 if (!Out) return 1;
591 formatted_raw_ostream FOS(Out->os());
592 #else
593 raw_fd_ostream ROS(getObjectFileFD(ModuleIndex), /* ShouldClose */ true);
594 ROS.SetBufferSize(1 << 20);
595 formatted_raw_ostream FOS(ROS);
596 #endif
597 int ret = runCompilePasses(mod, ModuleIndex, FuncQueue,
598 TheTriple, Target, ProgramName,
599 FOS);
600 if (ret)
601 return ret;
602 #if defined(PNACL_BROWSER_TRANSLATOR)
603 FOS.flush();
604 ROS.flush();
605 #else
606 // Declare success.
607 Out->keep();
608 #endif // PNACL_BROWSER_TRANSLATOR
609 }
610 return 0;
611 }
612
613 struct ThreadData {
614 const TargetOptions *Options;
615 const Triple *TheTriple;
616 const Target *TheTarget;
617 std::string FeaturesStr;
618 CodeGenOpt::Level OLvl;
619 std::string ProgramName;
620 Module *GlobalModule;
621 StreamingMemoryObject *StreamingObject;
622 unsigned ModuleIndex;
623 ThreadedFunctionQueue *FuncQueue;
624 };
625
626
627 static void *runCompileThread(void *arg) {
628 struct ThreadData *Data = static_cast<ThreadData *>(arg);
629 int ret = compileSplitModule(*Data->Options,
630 *Data->TheTriple,
631 Data->TheTarget,
632 Data->FeaturesStr,
633 Data->OLvl,
634 Data->ProgramName,
635 Data->GlobalModule,
636 Data->StreamingObject,
637 Data->ModuleIndex,
638 Data->FuncQueue);
639 return reinterpret_cast<void *>(static_cast<intptr_t>(ret));
640 }
641
642 static int compileModule(StringRef ProgramName) {
643 // Use a new context instead of the global context for the main module. It mus t
644 // outlive the module object, declared below. We do this because
645 // lib/CodeGen/PseudoSourceValue.cpp gets a type from the global context and
646 // races with any other use of the context. Rather than doing an invasive
647 // plumbing change to fix it, we work around it by using a new context here
648 // and leaving PseudoSourceValue as the only user of the global context.
649 std::unique_ptr<LLVMContext> MainContext(new LLVMContext());
650 std::unique_ptr<Module> mod;
651 Triple TheTriple;
652 PNaClABIErrorReporter ABIErrorReporter;
653 std::unique_ptr<StreamingMemoryObject> StreamingObject;
654
655 if (!MainContext) return 1;
656
657 #if defined(PNACL_BROWSER_TRANSLATOR)
658 StreamingObject.reset(
659 new StreamingMemoryObjectImpl(getNaClBitcodeStreamer()));
660 #else
661 if (LazyBitcode) {
662 std::string StrError;
663 DataStreamer* FileStreamer(getDataFileStreamer(InputFilename, &StrError));
664 if (!StrError.empty()) {
665 SMDiagnostic Err(InputFilename, SourceMgr::DK_Error, StrError);
666 Err.print(ProgramName.data(), errs());
667 }
668 if (!FileStreamer)
669 return 1;
670 StreamingObject.reset(new StreamingMemoryObjectImpl(FileStreamer));
671 }
672 #endif
673 mod.reset(getModule(ProgramName, *MainContext.get(), StreamingObject.get()));
674
675 if (!mod) return 1;
676
677 if (PNaClABIVerify) {
678 // Verify the module (but not the functions yet)
679 std::unique_ptr<ModulePass> VerifyPass(
680 createPNaClABIVerifyModulePass(&ABIErrorReporter, LazyBitcode));
681 VerifyPass->runOnModule(*mod);
682 CheckABIVerifyErrors(ABIErrorReporter, "Module");
683 VerifyPass.reset();
684 }
685
686 // Add declarations for external functions required by PNaCl. The
687 // ResolvePNaClIntrinsics function pass running during streaming
688 // depends on these declarations being in the module.
689 std::unique_ptr<ModulePass> AddPNaClExternalDeclsPass(
690 createAddPNaClExternalDeclsPass());
691 AddPNaClExternalDeclsPass->runOnModule(*mod);
692 AddPNaClExternalDeclsPass.reset();
693
694 if (UserDefinedTriple.empty()) {
695 report_fatal_error("-mtriple must be set to a target triple for pnacl-llc");
696 } else {
697 mod->setTargetTriple(Triple::normalize(UserDefinedTriple));
698 TheTriple = Triple(mod->getTargetTriple());
699 }
700
701 // Get the target specific parser.
702 std::string Error;
703 const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
704 Error);
705 if (!TheTarget) {
706 errs() << ProgramName << ": " << Error;
707 return 1;
708 }
709
710 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
711 Options.DisableIntegratedAS = NoIntegratedAssembler;
712
713 if (GenerateSoftFloatCalls)
714 FloatABIForCalls = FloatABI::Soft;
715
716 // Package up features to be passed to target/subtarget
717 std::string FeaturesStr;
718 if (MAttrs.size()) {
719 SubtargetFeatures Features;
720 for (unsigned i = 0; i != MAttrs.size(); ++i)
721 Features.AddFeature(MAttrs[i]);
722 FeaturesStr = Features.getString();
723 }
724
725 CodeGenOpt::Level OLvl = CodeGenOpt::Default;
726 switch (OptLevel) {
727 default:
728 errs() << ProgramName << ": invalid optimization level.\n";
729 return 1;
730 case ' ': break;
731 case '0': OLvl = CodeGenOpt::None; break;
732 case '1': OLvl = CodeGenOpt::Less; break;
733 case '2': OLvl = CodeGenOpt::Default; break;
734 case '3': OLvl = CodeGenOpt::Aggressive; break;
735 }
736
737 SmallVector<pthread_t, 4> Pthreads(SplitModuleCount);
738 SmallVector<ThreadData, 4> ThreadDatas(SplitModuleCount);
739 ThreadedFunctionQueue FuncQueue(mod.get(), SplitModuleCount);
740
741 if (SplitModuleCount == 1) {
742 // No need for dynamic scheduling with one thread.
743 SplitModuleSched = SplitModuleStatic;
744 return compileSplitModule(Options, TheTriple, TheTarget, FeaturesStr,
745 OLvl, ProgramName, mod.get(), nullptr, 0,
746 &FuncQueue);
747 }
748
749 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) {
750 ThreadDatas[ModuleIndex].Options = &Options;
751 ThreadDatas[ModuleIndex].TheTriple = &TheTriple;
752 ThreadDatas[ModuleIndex].TheTarget = TheTarget;
753 ThreadDatas[ModuleIndex].FeaturesStr = FeaturesStr;
754 ThreadDatas[ModuleIndex].OLvl = OLvl;
755 ThreadDatas[ModuleIndex].ProgramName = ProgramName.str();
756 ThreadDatas[ModuleIndex].GlobalModule = mod.get();
757 ThreadDatas[ModuleIndex].StreamingObject = StreamingObject.get();
758 ThreadDatas[ModuleIndex].ModuleIndex = ModuleIndex;
759 ThreadDatas[ModuleIndex].FuncQueue = &FuncQueue;
760 if (pthread_create(&Pthreads[ModuleIndex], nullptr, runCompileThread,
761 &ThreadDatas[ModuleIndex])) {
762 report_fatal_error("Failed to create thread");
763 }
764 }
765 for(unsigned ModuleIndex = 0; ModuleIndex < SplitModuleCount; ++ModuleIndex) {
766 void *retval;
767 if (pthread_join(Pthreads[ModuleIndex], &retval))
768 report_fatal_error("Failed to join thread");
769 intptr_t ret = reinterpret_cast<intptr_t>(retval);
770 if (ret != 0)
771 report_fatal_error("Thread returned nonzero");
772 }
773 return 0;
774 }
775
776 int main(int argc, char **argv) {
777 #if defined(PNACL_BROWSER_TRANSLATOR)
778 return srpc_main(argc, argv);
779 #else
780 return llc_main(argc, argv);
781 #endif // PNACL_BROWSER_TRANSLATOR
782 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698