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