OLD | NEW |
(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 } |
OLD | NEW |