int main(int argc, char **argv) { PROGRAM_START(argc, argv); INITIALIZE_LLVM(); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n"); if (PrintStats) llvm::EnableStatistics(); CompilerInvocation Invocation; Invocation.setMainExecutablePath( llvm::sys::fs::getMainExecutable(argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable))); // Give the context the list of search paths to use for modules. Invocation.setImportSearchPaths(ImportPaths); std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths; for (const auto &path : FrameworkPaths) { FramePaths.push_back({path, /*isSystem=*/false}); } Invocation.setFrameworkSearchPaths(FramePaths); // Set the SDK path and target if given. if (SDKPath.getNumOccurrences() == 0) { const char *SDKROOT = getenv("SDKROOT"); if (SDKROOT) SDKPath = SDKROOT; } if (!SDKPath.empty()) Invocation.setSDKPath(SDKPath); if (!Target.empty()) Invocation.setTargetTriple(Target); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); Invocation.getFrontendOptions().EnableResilience = EnableResilience; // Set the module cache path. If not passed in we use the default swift module // cache. Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); Invocation.getLangOptions().DisableAvailabilityChecking = true; Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; Invocation.getLangOptions().EnableObjCInterop = EnableObjCInterop ? true : DisableObjCInterop ? false : llvm::Triple(Target).isOSDarwin(); Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues; Invocation.getLangOptions().OptimizationRemarkPassedPattern = createOptRemarkRegex(PassRemarksPassed); Invocation.getLangOptions().OptimizationRemarkMissedPattern = createOptRemarkRegex(PassRemarksMissed); // Setup the SIL Options. SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.InlineThreshold = SILInlineThreshold; SILOpts.VerifyAll = EnableSILVerifyAll; SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts; SILOpts.AssertConfig = AssertConfId; if (OptimizationGroup != OptGroup::Diagnostics) SILOpts.OptMode = OptimizationMode::ForSpeed; SILOpts.EnableSILOwnership = EnableSILOwnershipOpt; SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; SILOpts.VerifyExclusivity = VerifyExclusivity; if (EnforceExclusivity.getNumOccurrences() != 0) { switch (EnforceExclusivity) { case EnforceExclusivityMode::Unchecked: // This option is analogous to the -Ounchecked optimization setting. // It will disable dynamic checking but still diagnose statically. SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = false; break; case EnforceExclusivityMode::Checked: SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::DynamicOnly: // This option is intended for staging purposes. The intent is that // it will eventually be removed. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::None: // This option is for staging purposes. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = false; break; } } serialization::ExtendedValidationInfo extendedInfo; llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = Invocation.setUpInputForSILTool(InputFilename, ModuleName, /*alwaysSetModuleToMain*/ false, /*bePrimary*/ !PerformWMO, extendedInfo); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (CI.setup(Invocation)) return 1; CI.performSema(); // If parsing produced an error, don't run any passes. if (CI.getASTContext().hadError()) return 1; // Load the SIL if we have a module. We have to do this after SILParse // creating the unfortunate double if statement. if (Invocation.hasSerializedAST()) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule(SILModule::createEmptyModule( CI.getMainModule(), CI.getSILOptions(), PerformWMO)); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB() || DisableSILLinking) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } // If we're in verify mode, install a custom diagnostic handling for // SourceMgr. if (VerifyMode) enableDiagnosticVerifier(CI.getSourceMgr()); if (CI.getSILModule()) CI.getSILModule()->setSerializeSILAction([]{}); std::unique_ptr<llvm::raw_fd_ostream> OptRecordFile; if (RemarksFilename != "") { std::error_code EC; OptRecordFile = llvm::make_unique<llvm::raw_fd_ostream>( RemarksFilename, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << EC.message() << '\n'; return 1; } CI.getSILModule()->setOptRecordStream( llvm::make_unique<llvm::yaml::Output>(*OptRecordFile, &CI.getSourceMgr()), std::move(OptRecordFile)); } if (OptimizationGroup == OptGroup::Diagnostics) { runSILDiagnosticPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Performance) { runSILOptPreparePasses(*CI.getSILModule()); runSILOptimizationPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Lowering) { runSILLoweringPasses(*CI.getSILModule()); } else { auto *SILMod = CI.getSILModule(); { auto T = irgen::createIRGenModule( SILMod, Invocation.getOutputFilenameForAtMostOnePrimary(), Invocation.getMainInputFilenameForDebugInfoForAtMostOnePrimary(), getGlobalLLVMContext()); runCommandLineSelectedPasses(SILMod, T.second); irgen::deleteIRGenModule(T); } } if (EmitSIB) { llvm::SmallString<128> OutputFile; if (OutputFilename.size()) { OutputFile = OutputFilename; } else if (ModuleName.size()) { OutputFile = ModuleName; llvm::sys::path::replace_extension( OutputFile, file_types::getExtension(file_types::TY_SIB)); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension( OutputFile, file_types::getExtension(file_types::TY_SIB)); } SerializationOptions serializationOpts; serializationOpts.OutputPath = OutputFile.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(CI.getMainModule(), serializationOpts, CI.getSILModule()); } else { const StringRef OutputFile = OutputFilename.size() ? StringRef(OutputFilename) : "-"; if (OutputFile == "-") { CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "while opening '" << OutputFile << "': " << EC.message() << '\n'; return 1; } CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } } bool HadError = CI.getASTContext().hadError(); // If we're in -verify mode, we've buffered up all of the generated // diagnostics. Check now to ensure that they meet our expectations. if (VerifyMode) { HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs(), /*autoApplyFixes*/false, /*ignoreUnknown*/false); DiagnosticEngine &diags = CI.getDiags(); if (diags.hasFatalErrorOccurred() && !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) { diags.resetHadAnyError(); diags.diagnose(SourceLoc(), diag::verify_encountered_fatal); HadError = true; } } return HadError; }