bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args(OrigArgs.begin(), OrigArgs.end()); Args.push_back("-resource-dir"); Args.push_back(Impl.RuntimeResourcePath.c_str()); if (auto driverInvocation = driver::createCompilerInvocation(Args, Diags)) { Invocation = *driverInvocation; } else { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return true; } Invocation.getFrontendOptions().InputsAndOutputs = resolveSymbolicLinksInInputs( Invocation.getFrontendOptions().InputsAndOutputs, UnresolvedPrimaryFile, Error); if (!Error.empty()) return true; ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; assert(!Invocation.getModuleName().empty()); Invocation.getLangOptions().AttachCommentsToDecls = true; Invocation.getLangOptions().DiagnosticsEditorMode = true; Invocation.getLangOptions().CollectParsedToken = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } // Disable the index-store functionality for the sourcekitd requests. FrontendOpts.IndexStorePath.clear(); ImporterOpts.IndexStorePath.clear(); // Force the action type to be -typecheck. This affects importing the // SwiftONoneSupport module. FrontendOpts.RequestedAction = FrontendOptions::ActionType::Typecheck; // We don't care about LLVMArgs FrontendOpts.LLVMArgs.clear(); // Disable expensive SIL options to reduce time spent in SILGen. disableExpensiveSILOptions(Invocation.getSILOptions()); return false; }
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args; sanitizeCompilerArgs(OrigArgs, Args); Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath); bool Err = Invocation.parseArgs(Args, Diags); if (Err) { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return Err; } // FIXME: The frontend should be dealing with symlinks, maybe similar to // clang's FileManager ? std::string PrimaryFile = SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile); for (auto &InputFile : Invocation.getFrontendOptions().InputFilenames) { InputFile = SwiftLangSupport::resolvePathSymlinks(InputFile); } ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; setModuleName(Invocation); Invocation.setSerializedDiagnosticsPath(StringRef()); Invocation.getLangOptions().AttachCommentsToDecls = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } if (!PrimaryFile.empty()) { Optional<unsigned> PrimaryIndex; for (auto i : indices(Invocation.getFrontendOptions().InputFilenames)) { auto &CurFile = Invocation.getFrontendOptions().InputFilenames[i]; if (PrimaryFile == CurFile) { PrimaryIndex = i; break; } } if (!PrimaryIndex) { llvm::SmallString<64> Err; llvm::raw_svector_ostream OS(Err); OS << "'" << PrimaryFile << "' is not part of the input files"; Error = OS.str(); return true; } Invocation.getFrontendOptions().PrimaryInput = SelectedInput(*PrimaryIndex); } return Err; }
void updateCode(std::unique_ptr<llvm::MemoryBuffer> Buffer) { BufferID = SM.addNewSourceBuffer(std::move(Buffer)); Parser.reset(new ParserUnit(SM, BufferID, CompInv.getLangOptions(), CompInv.getModuleName())); Parser->getDiagnosticEngine().addConsumer(DiagConsumer); auto &P = Parser->getParser(); for (bool Done = false; !Done; Done = P.Tok.is(tok::eof)) { P.parseTopLevel(); } }
bool migrator::updateCodeAndEmitRemap(CompilerInstance *Instance, const CompilerInvocation &Invocation) { // Delete the remap file, in case someone is re-running the Migrator. If the // file fails to compile and we don't get a chance to overwrite it, the old // changes may get picked up. llvm::sys::fs::remove(Invocation.getMigratorOptions().EmitRemapFilePath); Migrator M { Instance, Invocation }; // Provide inputs and configuration // Phase 1: Pre Fix-it passes // These uses the initial frontend invocation to apply any obvious fix-its // to see if we can get an error-free AST to get to Phase 2. std::unique_ptr<swift::CompilerInstance> PreFixItInstance; if (Instance->getASTContext().hadError()) { PreFixItInstance = M.repeatFixitMigrations(2, Invocation.getLangOptions().EffectiveLanguageVersion); // If we still couldn't fix all of the errors, give up. if (PreFixItInstance == nullptr || !PreFixItInstance->hasASTContext() || PreFixItInstance->getASTContext().hadError()) { return true; } M.StartInstance = PreFixItInstance.get(); } // Phase 2: Syntactic Transformations auto FailedSyntacticPasses = M.performSyntacticPasses(); if (FailedSyntacticPasses) { return true; } // Phase 3: Post Fix-it Passes // Perform fix-it based migrations on the compiler, some number of times in // order to give the compiler an opportunity to // take its time reaching a fixed point. // This is the end of the pipeline, so we throw away the compiler instance(s) // we used in these fix-it runs. if (M.getMigratorOptions().EnableMigratorFixits) { M.repeatFixitMigrations(Migrator::MaxCompilerFixitPassIterations, {4, 0, 0}); } // OK, we have a final resulting text. Now we compare against the input // to calculate a replacement map describing the changes to the input // necessary to get the output. // TODO: Document replacement map format. auto EmitRemapFailed = M.emitRemap(); auto EmitMigratedFailed = M.emitMigratedFile(); auto DumpMigrationStatesFailed = M.dumpStates(); return EmitRemapFailed || EmitMigratedFailed || DumpMigrationStatesFailed; }
bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation, ArrayRef<const char *> OrigArgs, DiagnosticEngine &Diags, StringRef UnresolvedPrimaryFile, std::string &Error) { SmallVector<const char *, 16> Args; sanitizeCompilerArgs(OrigArgs, Args); Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath); if (Invocation.parseArgs(Args, Diags)) { // FIXME: Get the actual diagnostic. Error = "error when parsing the compiler arguments"; return true; } Invocation.getFrontendOptions().Inputs = resolveSymbolicLinksInInputs( Invocation.getFrontendOptions().Inputs, UnresolvedPrimaryFile, Error); if (!Error.empty()) return true; ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions(); ImporterOpts.DetailedPreprocessingRecord = true; setModuleName(Invocation); Invocation.setSerializedDiagnosticsPath(StringRef()); Invocation.getLangOptions().AttachCommentsToDecls = true; Invocation.getLangOptions().DiagnosticsEditorMode = true; Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true; auto &FrontendOpts = Invocation.getFrontendOptions(); if (FrontendOpts.PlaygroundTransform) { // The playground instrumenter changes the AST in ways that disrupt the // SourceKit functionality. Since we don't need the instrumenter, and all we // actually need is the playground semantics visible to the user, like // silencing the "expression resolves to an unused l-value" error, disable it. FrontendOpts.PlaygroundTransform = false; } // Disable the index-store functionality for the sourcekitd requests. FrontendOpts.IndexStorePath.clear(); ImporterOpts.IndexStorePath.clear(); return false; }
void SwiftLangSupport::editorOpenHeaderInterface(EditorConsumer &Consumer, StringRef Name, StringRef HeaderName, ArrayRef<const char *> Args, bool UsingSwiftArgs, bool SynthesizedExtensions, StringRef swiftVersion) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; ArrayRef<const char *> SwiftArgs = UsingSwiftArgs ? Args : llvm::None; if (getASTManager().initCompilerInvocationNoInputs(Invocation, SwiftArgs, CI.getDiags(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } if (!UsingSwiftArgs && initInvocationByClangArguments(Args, Invocation, Error)) { Consumer.handleRequestError(Error.c_str()); return; } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; if (!swiftVersion.empty()) { auto swiftVer = version::Version::parseVersionString(swiftVersion, SourceLoc(), nullptr); if (swiftVer.hasValue()) Invocation.getLangOptions().EffectiveLanguageVersion = swiftVer.getValue(); } auto IFaceGenRef = SwiftInterfaceGenContext::create(Name, /*IsModule=*/false, HeaderName, None, Invocation, Error, SynthesizedExtensions, None); if (!IFaceGenRef) { Consumer.handleRequestError(Error.c_str()); return; } IFaceGenRef->reportEditorInfo(Consumer); // reportEditorInfo requires exclusive access to the AST, so don't add this // to the service cache until it has returned. IFaceGenContexts.set(Name, IFaceGenRef); }
int doFormat(ArrayRef<StringRef> InputFiles) { for (auto InputFilename : InputFiles) { CompilerInvocation Invocation; Invocation.addInputFilename(InputFilename); Invocation.setModuleName("Format"); CompilerInstance Instance; auto &SourceMgr = Instance.getSourceMgr(); auto &Diags = Instance.getDiags(); PrintingDiagnosticConsumer DiagPrinter; Instance.addDiagnosticConsumer(&DiagPrinter); if (Instance.setup(Invocation)) { return EXIT_FAILURE; } // First, parse the file normally and get the regular old AST. Instance.performParseOnly(); auto BufferID = Instance.getInputBufferIDs().back(); auto &SF = Instance.getMainModule() ->getMainSourceFile(SourceFileKind::Main); auto Buffer = llvm::MemoryBuffer::getFile(InputFilename); if (!Buffer) { Diags.diagnose(SourceLoc(), diag::cannot_open_file, InputFilename, Buffer.getError().message()); return EXIT_FAILURE; } auto Tokens = tokenizeWithTrivia(Invocation.getLangOptions(), SourceMgr, BufferID); SmallVector<Decl *, 256> FileDecls; SF.getTopLevelDecls(FileDecls); sema::Semantics Sema; for (auto *Decl : FileDecls) { if (Decl->escapedFromIfConfig()) { continue; } auto NewNode = transformAST(ASTNode(Decl), Sema, SourceMgr, BufferID, Tokens); if (NewNode.hasValue()) { auto Reformatted = format(NewNode.getValue()); Reformatted.print(llvm::outs()); } } } return EXIT_SUCCESS; }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); 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 = llvm::Triple(Target).isOSDarwin(); Invocation.getLangOptions().ASTVerifierProcessCount = ASTVerifierProcessCount; Invocation.getLangOptions().ASTVerifierProcessId = ASTVerifierProcessId; Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues; // 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.Optimization = SILOptions::SILOptMode::Optimize; SILOpts.EnableSILOwnership = EnableSILOwnershipOpt; SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; 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; } // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main"; Invocation.setModuleName(Name); Invocation.setInputKind(InputFileKind::IFK_SIL); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (!PerformWMO) { auto &FrontendOpts = Invocation.getFrontendOptions(); if (!InputFilename.empty() && InputFilename != "-") { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputFilenames.size()); } else { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer); } } 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 (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 (OptimizationGroup == OptGroup::Diagnostics) { runSILDiagnosticPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Performance) { runSILOptimizationPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Lowering) { runSILLoweringPasses(*CI.getSILModule()); } else { auto *SILMod = CI.getSILModule(); { auto T = irgen::createIRGenModule(SILMod, 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, SIB_EXTENSION); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } 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; }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift LLVM IR Generator\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); Invocation.setFrameworkSearchPaths(FrameworkPaths); // 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); // Set the module cache path. If not passed in we use the default swift module // cache. Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); // Setup the language options auto &LangOpts = Invocation.getLangOptions(); LangOpts.DisableAvailabilityChecking = true; LangOpts.EnableAccessControl = false; LangOpts.EnableObjCAttrRequiresFoundation = false; LangOpts.EnableObjCInterop = LangOpts.Target.isOSDarwin(); // Setup the SIL Options. SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; // Setup the IRGen Options. IRGenOptions &Opts = Invocation.getIRGenOptions(); Opts.MainInputFilename = InputFilename; Opts.OutputFilenames.push_back(OutputFilename); Opts.OutputKind = OutputKind; // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main"; Invocation.setModuleName(Name); Invocation.setInputKind(InputFileKind::IFK_SIL); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (!PerformWMO) { auto &FrontendOpts = Invocation.getFrontendOptions(); if (!InputFilename.empty() && InputFilename != "-") { FrontendOpts.PrimaryInput = SelectedInput(FrontendOpts.InputFilenames.size()); } else { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer); } } 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 (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()) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } std::unique_ptr<llvm::Module> Mod = performIRGeneration( Opts, CI.getMainModule(), CI.takeSILModule(), CI.getMainModule()->getName().str(), getGlobalLLVMContext()); return CI.getASTContext().hadError(); }
int swift::performFrontend(ArrayRef<const char *> Args, const char *Argv0, void *MainAddr, FrontendObserver *observer) { llvm::InitializeAllTargets(); llvm::InitializeAllTargetMCs(); llvm::InitializeAllAsmPrinters(); llvm::InitializeAllAsmParsers(); CompilerInstance Instance; PrintingDiagnosticConsumer PDC; Instance.addDiagnosticConsumer(&PDC); if (Args.empty()) { Instance.getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args); return 1; } CompilerInvocation Invocation; std::string MainExecutablePath = llvm::sys::fs::getMainExecutable(Argv0, MainAddr); Invocation.setMainExecutablePath(MainExecutablePath); SmallString<128> workingDirectory; llvm::sys::fs::current_path(workingDirectory); // Parse arguments. if (Invocation.parseArgs(Args, Instance.getDiags(), workingDirectory)) { return 1; } // Setting DWARF Version depend on platform IRGenOptions &IRGenOpts = Invocation.getIRGenOptions(); IRGenOpts.DWARFVersion = swift::GenericDWARFVersion; if (Invocation.getLangOptions().Target.isWindowsCygwinEnvironment()) IRGenOpts.DWARFVersion = swift::CygwinDWARFVersion; // The compiler invocation is now fully configured; notify our observer. if (observer) { observer->parsedArgs(Invocation); } if (Invocation.getFrontendOptions().PrintHelp || Invocation.getFrontendOptions().PrintHelpHidden) { unsigned IncludedFlagsBitmask = options::FrontendOption; unsigned ExcludedFlagsBitmask = Invocation.getFrontendOptions().PrintHelpHidden ? 0 : llvm::opt::HelpHidden; std::unique_ptr<llvm::opt::OptTable> Options(createSwiftOptTable()); Options->PrintHelp(llvm::outs(), displayName(MainExecutablePath).c_str(), "Swift frontend", IncludedFlagsBitmask, ExcludedFlagsBitmask); return 0; } if (Invocation.getFrontendOptions().RequestedAction == FrontendOptions::NoneAction) { Instance.getDiags().diagnose(SourceLoc(), diag::error_missing_frontend_action); return 1; } // TODO: reorder, if possible, so that diagnostics emitted during // CompilerInvocation::parseArgs are included in the serialized file. std::unique_ptr<DiagnosticConsumer> SerializedConsumer; { const std::string &SerializedDiagnosticsPath = Invocation.getFrontendOptions().SerializedDiagnosticsPath; if (!SerializedDiagnosticsPath.empty()) { std::error_code EC; std::unique_ptr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(SerializedDiagnosticsPath, EC, llvm::sys::fs::F_None)); if (EC) { Instance.getDiags().diagnose(SourceLoc(), diag::cannot_open_serialized_file, SerializedDiagnosticsPath, EC.message()); return 1; } SerializedConsumer.reset( serialized_diagnostics::createConsumer(std::move(OS))); Instance.addDiagnosticConsumer(SerializedConsumer.get()); } } std::unique_ptr<DiagnosticConsumer> FixitsConsumer; { const std::string &FixitsOutputPath = Invocation.getFrontendOptions().FixitsOutputPath; if (!FixitsOutputPath.empty()) { std::error_code EC; std::unique_ptr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(FixitsOutputPath, EC, llvm::sys::fs::F_None)); if (EC) { Instance.getDiags().diagnose(SourceLoc(), diag::cannot_open_file, FixitsOutputPath, EC.message()); return 1; } FixitsConsumer.reset(new JSONFixitWriter(std::move(OS), Invocation.getDiagnosticOptions())); Instance.addDiagnosticConsumer(FixitsConsumer.get()); } } if (Invocation.getDiagnosticOptions().UseColor) PDC.forceColors(); if (Invocation.getFrontendOptions().DebugTimeCompilation) SharedTimer::enableCompilationTimers(); if (Invocation.getFrontendOptions().PrintStats) { llvm::EnableStatistics(); } if (Invocation.getDiagnosticOptions().VerifyDiagnostics) { enableDiagnosticVerifier(Instance.getSourceMgr()); } DependencyTracker depTracker; if (!Invocation.getFrontendOptions().DependenciesFilePath.empty() || !Invocation.getFrontendOptions().ReferenceDependenciesFilePath.empty()) { Instance.setDependencyTracker(&depTracker); } if (Instance.setup(Invocation)) { return 1; } // The compiler instance has been configured; notify our observer. if (observer) { observer->configuredCompiler(Instance); } int ReturnValue = 0; bool HadError = performCompile(Instance, Invocation, Args, ReturnValue, observer) || Instance.getASTContext().hadError(); if (!HadError && !Invocation.getFrontendOptions().DumpAPIPath.empty()) { HadError = dumpAPI(Instance.getMainModule(), Invocation.getFrontendOptions().DumpAPIPath); } if (Invocation.getDiagnosticOptions().VerifyDiagnostics) { HadError = verifyDiagnostics(Instance.getSourceMgr(), Instance.getInputBufferIDs()); DiagnosticEngine &diags = Instance.getDiags(); if (diags.hasFatalErrorOccurred() && !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) { diags.resetHadAnyError(); diags.diagnose(SourceLoc(), diag::verify_encountered_fatal); HadError = true; } } return (HadError ? 1 : ReturnValue); }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL Extractor\n"); 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); // 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 (!Triple.empty()) Invocation.setTargetTriple(Triple); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); Invocation.getLangOptions().DisableAvailabilityChecking = true; Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { Invocation.setModuleName("main"); Invocation.setInputKind(InputFileKind::IFK_SIL); } SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; 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 (HasSerializedAST) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule( SILModule::createEmptyModule(CI.getMainModule(), CI.getSILOptions())); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB()) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } if (CommandLineFunctionNames.empty() && FunctionNameFile.empty()) return CI.getASTContext().hadError(); // For efficient usage, we separate our names into two separate sorted // lists, one of managled names, and one of unmangled names. std::vector<std::string> Names; getFunctionNames(Names); // First partition our function names into mangled/demangled arrays. auto FirstDemangledName = std::partition( Names.begin(), Names.end(), [](const std::string &Name) -> bool { StringRef NameRef(Name); return NameRef.startswith("_T") || NameRef.startswith(MANGLING_PREFIX_STR); }); // Then grab offsets to avoid any issues with iterator invalidation when we // sort. unsigned NumMangled = std::distance(Names.begin(), FirstDemangledName); unsigned NumNames = Names.size(); // Then sort the two partitioned arrays. std::sort(Names.begin(), FirstDemangledName); std::sort(FirstDemangledName, Names.end()); // Finally construct our ArrayRefs into the sorted std::vector for our // mangled and demangled names. ArrayRef<std::string> MangledNames(&*Names.begin(), NumMangled); ArrayRef<std::string> DemangledNames(&*std::next(Names.begin(), NumMangled), NumNames - NumMangled); DEBUG(llvm::errs() << "MangledNames to keep:\n"; std::for_each(MangledNames.begin(), MangledNames.end(), [](const std::string &str) { llvm::errs() << " " << str << '\n'; })); DEBUG(llvm::errs() << "DemangledNames to keep:\n"; std::for_each(DemangledNames.begin(), DemangledNames.end(), [](const std::string &str) { llvm::errs() << " " << str << '\n'; })); removeUnwantedFunctions(CI.getSILModule(), MangledNames, DemangledNames); if (EmitSIB) { llvm::SmallString<128> OutputFile; if (OutputFilename.size()) { OutputFile = OutputFilename; } else if (ModuleName.size()) { OutputFile = ModuleName; llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } 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); } } }
int getSyntaxTree(const char *MainExecutablePath, const StringRef InputFilename, CompilerInstance &Instance, llvm::SmallVectorImpl<syntax::Syntax> &TopLevelDecls, std::vector<std::pair<RC<syntax::TokenSyntax>, syntax::AbsolutePosition>> &Tokens) { CompilerInvocation Invocation; Invocation.addInputFilename(InputFilename); Invocation.setMainExecutablePath( llvm::sys::fs::getMainExecutable(MainExecutablePath, reinterpret_cast<void *>(&anchorForGetMainExecutable))); Invocation.setModuleName("Test"); auto &SourceMgr = Instance.getSourceMgr(); PrintingDiagnosticConsumer DiagPrinter; Instance.addDiagnosticConsumer(&DiagPrinter); if (Instance.setup(Invocation)) { return EXIT_FAILURE; } // First, parse the file normally and get the regular old AST. Instance.performParseOnly(); if (Instance.getDiags().hadAnyError()) { return EXIT_FAILURE; } auto BufferID = Instance.getInputBufferIDs().back(); SourceFile *SF = nullptr; for (auto Unit : Instance.getMainModule()->getFiles()) { SF = dyn_cast<SourceFile>(Unit); if (SF != nullptr) { break; } } assert(SF && "No source file"); // Retokenize the buffer with full fidelity if (getTokensFromFile(BufferID, Invocation.getLangOptions(), SourceMgr, Instance.getDiags(), Tokens) == EXIT_FAILURE) { return EXIT_FAILURE; } SmallVector<Decl *, 256> FileDecls; SF->getTopLevelDecls(FileDecls); sema::Semantics Sema; // Convert the old ASTs to the new full-fidelity syntax tree and print // them out. for (auto *Decl : FileDecls) { if (Decl->escapedFromIfConfig()) { continue; } auto NewNode = transformAST(ASTNode(Decl), Sema, SourceMgr, BufferID, Tokens); if (NewNode.hasValue()) { TopLevelDecls.push_back(NewNode.getValue()); } } return EXIT_SUCCESS; }
void SwiftLangSupport::editorOpenHeaderInterface(EditorConsumer &Consumer, StringRef Name, StringRef HeaderName, ArrayRef<const char *> Args, bool UsingSwiftArgs, bool SynthesizedExtensions, Optional<unsigned> swiftVersion) { CompilerInstance CI; // Display diagnostics to stderr. PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); CompilerInvocation Invocation; std::string Error; ArrayRef<const char *> SwiftArgs = UsingSwiftArgs ? Args : llvm::None; if (getASTManager().initCompilerInvocationNoInputs(Invocation, SwiftArgs, CI.getDiags(), Error)) { Consumer.handleRequestError(Error.c_str()); return; } if (!UsingSwiftArgs && initInvocationByClangArguments(Args, Invocation, Error)) { Consumer.handleRequestError(Error.c_str()); return; } trace::TracedOperation TracedOp; if (trace::enabled()) { trace::SwiftInvocation SwiftArgs; SwiftArgs.Args.Args.assign(Args.begin(), Args.end()); // NOTE: do not use primary file // NOTE: do not use files TracedOp.start(trace::OperationKind::OpenHeaderInterface, SwiftArgs, {std::make_pair("Name", Name), std::make_pair("HeaderName", HeaderName)}); } Invocation.getClangImporterOptions().ImportForwardDeclarations = true; if (swiftVersion.hasValue()) { auto swiftVer = version::Version({swiftVersion.getValue()}); Invocation.getLangOptions().EffectiveLanguageVersion = swiftVer; } auto IFaceGenRef = SwiftInterfaceGenContext::create(Name, /*IsModule=*/false, HeaderName, None, Invocation, Error, SynthesizedExtensions, None); if (!IFaceGenRef) { Consumer.handleRequestError(Error.c_str()); return; } IFaceGenRef->reportEditorInfo(Consumer); // reportEditorInfo requires exclusive access to the AST, so don't add this // to the service cache until it has returned. IFaceGenContexts.set(Name, IFaceGenRef); }
std::unique_ptr<swift::CompilerInstance> Migrator::performAFixItMigration(version::Version SwiftLanguageVersion) { auto InputState = States.back(); auto InputText = InputState->getOutputText(); auto InputBuffer = llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename()); CompilerInvocation Invocation { StartInvocation }; Invocation.clearInputs(); Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion; auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs; auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(), "-aarch64-use-tbi"); if (aarch64_use_tbi != LLVMArgs.end()) { LLVMArgs.erase(aarch64_use_tbi); } // SE-0160: When migrating, always use the Swift 3 @objc inference rules, // which drives warnings with the "@objc" Fix-Its. Invocation.getLangOptions().EnableSwift3ObjCInference = true; // The default behavior of the migrator, referred to as "minimal" migration // in SE-0160, only adds @objc Fix-Its to those cases where the Objective-C // entry point is explicitly used somewhere in the source code. The user // may also select a workflow that adds @objc for every declaration that // would infer @objc under the Swift 3 rules but would no longer infer // @objc in Swift 4. Invocation.getLangOptions().WarnSwift3ObjCInference = getMigratorOptions().KeepObjcVisibility ? Swift3ObjCInferenceWarnings::Complete : Swift3ObjCInferenceWarnings::Minimal; const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions(); auto InputBuffers = OrigFrontendOpts.InputBuffers; auto InputFilenames = OrigFrontendOpts.InputFilenames; for (const auto &Buffer : InputBuffers) { Invocation.addInputBuffer(Buffer); } for (const auto &Filename : InputFilenames) { Invocation.addInputFilename(Filename); } const unsigned PrimaryIndex = Invocation.getFrontendOptions().InputBuffers.size(); Invocation.addInputBuffer(InputBuffer.get()); Invocation.getFrontendOptions().PrimaryInput = { PrimaryIndex, SelectedInput::InputKind::Buffer }; auto Instance = llvm::make_unique<swift::CompilerInstance>(); if (Instance->setup(Invocation)) { return nullptr; } FixitApplyDiagnosticConsumer FixitApplyConsumer { InputText, getInputFilename(), }; Instance->addDiagnosticConsumer(&FixitApplyConsumer); Instance->performSema(); StringRef ResultText = InputText; unsigned ResultBufferID = InputState->getOutputBufferID(); if (FixitApplyConsumer.getNumFixitsApplied() > 0) { SmallString<4096> Scratch; llvm::raw_svector_ostream OS(Scratch); FixitApplyConsumer.printResult(OS); auto ResultBuffer = llvm::MemoryBuffer::getMemBufferCopy(OS.str()); ResultText = ResultBuffer->getBuffer(); ResultBufferID = SrcMgr.addNewSourceBuffer(std::move(ResultBuffer)); } States.push_back(MigrationState::make(MigrationKind::CompilerFixits, SrcMgr, InputState->getOutputBufferID(), ResultBufferID)); return Instance; }