mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Encapsulate uses of the variables in FrontendInputs with intention-describing functions. Move some code that sets these variables into FrontendInputs and FrontendOptions classes. Create new FrontendInputs class to encapsulate InputFilenames, InputBuffers and PrimaryInput, which were formerly in Frontend. Includes one change in SwiftEditor.cpp to resolve a merge conflict.
502 lines
16 KiB
C++
502 lines
16 KiB
C++
//===--- Frontend.h - frontend utility methods ------------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains declarations of utility methods for parsing and
|
|
// performing semantic on modules.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_FRONTEND_H
|
|
#define SWIFT_FRONTEND_H
|
|
|
|
#include "swift/AST/DiagnosticConsumer.h"
|
|
#include "swift/AST/DiagnosticEngine.h"
|
|
#include "swift/AST/IRGenOptions.h"
|
|
#include "swift/AST/LinkLibrary.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/SILOptions.h"
|
|
#include "swift/AST/SearchPathOptions.h"
|
|
#include "swift/Basic/DiagnosticOptions.h"
|
|
#include "swift/Basic/LangOptions.h"
|
|
#include "swift/Basic/SourceManager.h"
|
|
#include "swift/ClangImporter/ClangImporter.h"
|
|
#include "swift/ClangImporter/ClangImporterOptions.h"
|
|
#include "swift/Frontend/FrontendOptions.h"
|
|
#include "swift/Migrator/MigratorOptions.h"
|
|
#include "swift/Parse/CodeCompletionCallbacks.h"
|
|
#include "swift/Parse/Parser.h"
|
|
#include "swift/SIL/SILModule.h"
|
|
#include "swift/Sema/SourceLoader.h"
|
|
#include "swift/Serialization/Validation.h"
|
|
#include "swift/Subsystems.h"
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
#include "llvm/Option/ArgList.h"
|
|
#include "llvm/Support/Host.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include <memory>
|
|
|
|
namespace swift {
|
|
|
|
class SerializedModuleLoader;
|
|
|
|
/// The abstract configuration of the compiler, including:
|
|
/// - options for all stages of translation,
|
|
/// - information about the build environment,
|
|
/// - information about the job being performed, and
|
|
/// - lists of inputs.
|
|
///
|
|
/// A CompilerInvocation can be built from a frontend command line
|
|
/// using parseArgs. It can then be used to build a CompilerInstance,
|
|
/// which manages the actual compiler execution.
|
|
class CompilerInvocation {
|
|
LangOptions LangOpts;
|
|
FrontendOptions FrontendOpts;
|
|
ClangImporterOptions ClangImporterOpts;
|
|
SearchPathOptions SearchPathOpts;
|
|
DiagnosticOptions DiagnosticOpts;
|
|
MigratorOptions MigratorOpts;
|
|
SILOptions SILOpts;
|
|
IRGenOptions IRGenOpts;
|
|
|
|
llvm::MemoryBuffer *CodeCompletionBuffer = nullptr;
|
|
|
|
/// \brief Code completion offset in bytes from the beginning of the main
|
|
/// source file. Valid only if \c isCodeCompletion() == true.
|
|
unsigned CodeCompletionOffset = ~0U;
|
|
|
|
CodeCompletionCallbacksFactory *CodeCompletionFactory = nullptr;
|
|
|
|
public:
|
|
CompilerInvocation();
|
|
|
|
/// Initializes the compiler invocation for the list of arguments.
|
|
///
|
|
/// All parsing should be additive, i.e. options should not be reset to their
|
|
/// default values given the /absence/ of a flag. This is because \c parseArgs
|
|
/// may be used to modify an already partially configured invocation.
|
|
///
|
|
/// If non-empty, relative search paths are resolved relative to
|
|
/// \p workingDirectory.
|
|
///
|
|
/// \returns true if there was an error, false on success.
|
|
bool parseArgs(ArrayRef<const char *> Args, DiagnosticEngine &Diags,
|
|
StringRef workingDirectory = {});
|
|
|
|
/// Sets specific options based on the given serialized Swift binary data.
|
|
///
|
|
/// This is additive, i.e. options are not reset to their default values given
|
|
/// the /absence/ of a flag. However, flags that only have a single value may
|
|
/// (and should) be overwritten by this method.
|
|
///
|
|
/// Invoking this on more than one serialized AST is likely to result in
|
|
/// one or both of them failing to load. Please pick one AST to provide base
|
|
/// flags for the entire ASTContext and let the others succeed or fail the
|
|
/// normal way. (Some additive flags, like search paths, will be handled
|
|
/// properly during normal module loading.)
|
|
///
|
|
/// \returns Status::Valid on success, one of the Status issues on error.
|
|
serialization::Status loadFromSerializedAST(StringRef data);
|
|
|
|
/// Serialize the command line arguments for emitting them
|
|
/// to DWARF and inject SDKPath if necessary.
|
|
static void buildDWARFDebugFlags(std::string &Output,
|
|
const ArrayRef<const char*> &Args,
|
|
StringRef SDKPath,
|
|
StringRef ResourceDir);
|
|
|
|
void setTargetTriple(StringRef Triple);
|
|
|
|
StringRef getTargetTriple() const {
|
|
return LangOpts.Target.str();
|
|
}
|
|
|
|
void setClangModuleCachePath(StringRef Path) {
|
|
ClangImporterOpts.ModuleCachePath = Path.str();
|
|
}
|
|
|
|
StringRef getClangModuleCachePath() const {
|
|
return ClangImporterOpts.ModuleCachePath;
|
|
}
|
|
|
|
void setImportSearchPaths(const std::vector<std::string> &Paths) {
|
|
SearchPathOpts.ImportSearchPaths = Paths;
|
|
}
|
|
|
|
ArrayRef<std::string> getImportSearchPaths() const {
|
|
return SearchPathOpts.ImportSearchPaths;
|
|
}
|
|
|
|
void setFrameworkSearchPaths(
|
|
const std::vector<SearchPathOptions::FrameworkSearchPath> &Paths) {
|
|
SearchPathOpts.FrameworkSearchPaths = Paths;
|
|
}
|
|
|
|
ArrayRef<SearchPathOptions::FrameworkSearchPath> getFrameworkSearchPaths() const {
|
|
return SearchPathOpts.FrameworkSearchPaths;
|
|
}
|
|
|
|
void setExtraClangArgs(const std::vector<std::string> &Args) {
|
|
ClangImporterOpts.ExtraArgs = Args;
|
|
}
|
|
|
|
ArrayRef<std::string> getExtraClangArgs() const {
|
|
return ClangImporterOpts.ExtraArgs;
|
|
}
|
|
|
|
void addLinkLibrary(StringRef name, LibraryKind kind) {
|
|
IRGenOpts.LinkLibraries.push_back({name, kind});
|
|
}
|
|
|
|
ArrayRef<LinkLibrary> getLinkLibraries() const {
|
|
return IRGenOpts.LinkLibraries;
|
|
}
|
|
|
|
void setMainExecutablePath(StringRef Path);
|
|
|
|
void setRuntimeResourcePath(StringRef Path);
|
|
|
|
void setSDKPath(const std::string &Path) {
|
|
SearchPathOpts.SDKPath = Path;
|
|
}
|
|
|
|
StringRef getSDKPath() const {
|
|
return SearchPathOpts.SDKPath;
|
|
}
|
|
|
|
void setSerializedDiagnosticsPath(StringRef Path) {
|
|
FrontendOpts.SerializedDiagnosticsPath = Path;
|
|
}
|
|
StringRef getSerializedDiagnosticsPath() const {
|
|
return FrontendOpts.SerializedDiagnosticsPath;
|
|
}
|
|
|
|
LangOptions &getLangOptions() {
|
|
return LangOpts;
|
|
}
|
|
const LangOptions &getLangOptions() const {
|
|
return LangOpts;
|
|
}
|
|
|
|
FrontendOptions &getFrontendOptions() { return FrontendOpts; }
|
|
const FrontendOptions &getFrontendOptions() const { return FrontendOpts; }
|
|
|
|
ClangImporterOptions &getClangImporterOptions() { return ClangImporterOpts; }
|
|
const ClangImporterOptions &getClangImporterOptions() const {
|
|
return ClangImporterOpts;
|
|
}
|
|
|
|
SearchPathOptions &getSearchPathOptions() { return SearchPathOpts; }
|
|
const SearchPathOptions &getSearchPathOptions() const {
|
|
return SearchPathOpts;
|
|
}
|
|
|
|
DiagnosticOptions &getDiagnosticOptions() { return DiagnosticOpts; }
|
|
const DiagnosticOptions &getDiagnosticOptions() const {
|
|
return DiagnosticOpts;
|
|
}
|
|
|
|
const MigratorOptions &getMigratorOptions() const {
|
|
return MigratorOpts;
|
|
}
|
|
|
|
SILOptions &getSILOptions() { return SILOpts; }
|
|
const SILOptions &getSILOptions() const { return SILOpts; }
|
|
|
|
IRGenOptions &getIRGenOptions() { return IRGenOpts; }
|
|
const IRGenOptions &getIRGenOptions() const { return IRGenOpts; }
|
|
|
|
void setParseStdlib() {
|
|
FrontendOpts.ParseStdlib = true;
|
|
}
|
|
|
|
bool getParseStdlib() const {
|
|
return FrontendOpts.ParseStdlib;
|
|
}
|
|
|
|
void setInputKind(InputFileKind K) {
|
|
FrontendOpts.InputKind = K;
|
|
}
|
|
|
|
InputFileKind getInputKind() const {
|
|
return FrontendOpts.InputKind;
|
|
}
|
|
|
|
SourceFileKind getSourceFileKind() const;
|
|
|
|
void setModuleName(StringRef Name) {
|
|
FrontendOpts.ModuleName = Name.str();
|
|
IRGenOpts.ModuleName = Name.str();
|
|
}
|
|
|
|
StringRef getModuleName() const {
|
|
return FrontendOpts.ModuleName;
|
|
}
|
|
|
|
void addInputFilename(StringRef Filename) {
|
|
FrontendOpts.Inputs.addInputFilename(Filename);
|
|
}
|
|
|
|
/// Does not take ownership of \p Buf.
|
|
void addInputBuffer(llvm::MemoryBuffer *Buf) {
|
|
FrontendOpts.Inputs.addInputBuffer(Buf);
|
|
}
|
|
|
|
void setPrimaryInput(SelectedInput pi) {
|
|
FrontendOpts.Inputs.setPrimaryInput(pi);
|
|
}
|
|
|
|
void clearInputs() {
|
|
FrontendOpts.Inputs.clearInputs();
|
|
}
|
|
|
|
StringRef getOutputFilename() const {
|
|
return FrontendOpts.getSingleOutputFilename();
|
|
}
|
|
|
|
void setCodeCompletionPoint(llvm::MemoryBuffer *Buf, unsigned Offset) {
|
|
assert(Buf);
|
|
CodeCompletionBuffer = Buf;
|
|
CodeCompletionOffset = Offset;
|
|
// We don't need typo-correction for code-completion.
|
|
// FIXME: This isn't really true, but is a performance issue.
|
|
LangOpts.TypoCorrectionLimit = 0;
|
|
}
|
|
|
|
std::pair<llvm::MemoryBuffer *, unsigned> getCodeCompletionPoint() const {
|
|
return std::make_pair(CodeCompletionBuffer, CodeCompletionOffset);
|
|
}
|
|
|
|
/// \returns true if we are doing code completion.
|
|
bool isCodeCompletion() const {
|
|
return CodeCompletionOffset != ~0U;
|
|
}
|
|
|
|
void setCodeCompletionFactory(CodeCompletionCallbacksFactory *Factory) {
|
|
CodeCompletionFactory = Factory;
|
|
}
|
|
|
|
CodeCompletionCallbacksFactory *getCodeCompletionFactory() const {
|
|
return CodeCompletionFactory;
|
|
}
|
|
|
|
void setDelayedFunctionBodyParsing(bool Val) {
|
|
FrontendOpts.DelayedFunctionBodyParsing = Val;
|
|
}
|
|
|
|
bool isDelayedFunctionBodyParsing() const {
|
|
return FrontendOpts.DelayedFunctionBodyParsing;
|
|
}
|
|
|
|
/// Retrieve a module hash string that is suitable for uniquely
|
|
/// identifying the conditions under which the module was built, for use
|
|
/// in generating a cached PCH file for the bridging header.
|
|
std::string getPCHHash() const;
|
|
|
|
SourceFile::ImplicitModuleImportKind getImplicitModuleImportKind() {
|
|
if (getInputKind() == InputFileKind::IFK_SIL) {
|
|
return SourceFile::ImplicitModuleImportKind::None;
|
|
}
|
|
if (getParseStdlib()) {
|
|
return SourceFile::ImplicitModuleImportKind::Builtin;
|
|
}
|
|
return SourceFile::ImplicitModuleImportKind::Stdlib;
|
|
}
|
|
};
|
|
|
|
/// A class which manages the state and execution of the compiler.
|
|
/// This owns the primary compiler singletons, such as the ASTContext,
|
|
/// as well as various build products such as the SILModule.
|
|
///
|
|
/// Before a CompilerInstance can be used, it must be configured by
|
|
/// calling \a setup. If successful, this will create an ASTContext
|
|
/// and set up the basic compiler invariants. Calling \a setup multiple
|
|
/// times on a single CompilerInstance is not permitted.
|
|
class CompilerInstance {
|
|
CompilerInvocation Invocation;
|
|
SourceManager SourceMgr;
|
|
DiagnosticEngine Diagnostics{SourceMgr};
|
|
std::unique_ptr<ASTContext> Context;
|
|
std::unique_ptr<SILModule> TheSILModule;
|
|
|
|
DependencyTracker *DepTracker = nullptr;
|
|
ReferencedNameTracker *NameTracker = nullptr;
|
|
|
|
ModuleDecl *MainModule = nullptr;
|
|
SerializedModuleLoader *SML = nullptr;
|
|
|
|
/// Contains buffer IDs for input source code files.
|
|
std::vector<unsigned> InputSourceCodeBufferIDs;
|
|
|
|
struct PartialModuleInputs {
|
|
std::unique_ptr<llvm::MemoryBuffer> ModuleBuffer;
|
|
std::unique_ptr<llvm::MemoryBuffer> ModuleDocBuffer;
|
|
};
|
|
|
|
/// Contains \c MemoryBuffers for partial serialized module files and
|
|
/// corresponding partial serialized module documentation files.
|
|
std::vector<PartialModuleInputs> PartialModules;
|
|
|
|
enum : unsigned { NO_SUCH_BUFFER = ~0U };
|
|
unsigned MainBufferID = NO_SUCH_BUFFER;
|
|
|
|
/// PrimaryBufferID corresponds to PrimaryInput.
|
|
unsigned PrimaryBufferID = NO_SUCH_BUFFER;
|
|
bool isWholeModuleCompilation() { return PrimaryBufferID == NO_SUCH_BUFFER; }
|
|
|
|
SourceFile *PrimarySourceFile = nullptr;
|
|
|
|
void createSILModule();
|
|
void setPrimarySourceFile(SourceFile *SF);
|
|
|
|
bool setupForFileAt(unsigned i);
|
|
|
|
public:
|
|
SourceManager &getSourceMgr() { return SourceMgr; }
|
|
|
|
DiagnosticEngine &getDiags() { return Diagnostics; }
|
|
|
|
ASTContext &getASTContext() {
|
|
return *Context;
|
|
}
|
|
bool hasASTContext() const { return Context != nullptr; }
|
|
|
|
SILOptions &getSILOptions() { return Invocation.getSILOptions(); }
|
|
const SILOptions &getSILOptions() const { return Invocation.getSILOptions(); }
|
|
|
|
void addDiagnosticConsumer(DiagnosticConsumer *DC) {
|
|
Diagnostics.addConsumer(*DC);
|
|
}
|
|
|
|
void setDependencyTracker(DependencyTracker *DT) {
|
|
assert(!Context && "must be called before setup()");
|
|
DepTracker = DT;
|
|
}
|
|
DependencyTracker *getDependencyTracker() {
|
|
return DepTracker;
|
|
}
|
|
|
|
void setReferencedNameTracker(ReferencedNameTracker *tracker) {
|
|
assert(!PrimarySourceFile && "must be called before performSema()");
|
|
NameTracker = tracker;
|
|
}
|
|
ReferencedNameTracker *getReferencedNameTracker() {
|
|
return NameTracker;
|
|
}
|
|
|
|
/// Set the SIL module for this compilation instance.
|
|
///
|
|
/// The CompilerInstance takes ownership of the given SILModule object.
|
|
void setSILModule(std::unique_ptr<SILModule> M) {
|
|
TheSILModule = std::move(M);
|
|
}
|
|
|
|
SILModule *getSILModule() {
|
|
return TheSILModule.get();
|
|
}
|
|
|
|
std::unique_ptr<SILModule> takeSILModule() {
|
|
return std::move(TheSILModule);
|
|
}
|
|
|
|
bool hasSILModule() {
|
|
return static_cast<bool>(TheSILModule);
|
|
}
|
|
|
|
ModuleDecl *getMainModule();
|
|
|
|
SerializedModuleLoader *getSerializedModuleLoader() const { return SML; }
|
|
|
|
ArrayRef<unsigned> getInputBufferIDs() const { return InputSourceCodeBufferIDs; }
|
|
|
|
ArrayRef<LinkLibrary> getLinkLibraries() const {
|
|
return Invocation.getLinkLibraries();
|
|
}
|
|
|
|
bool hasSourceImport() const {
|
|
return Invocation.getFrontendOptions().EnableSourceImport;
|
|
}
|
|
|
|
/// Gets the SourceFile which is the primary input for this CompilerInstance.
|
|
/// \returns the primary SourceFile, or nullptr if there is no primary input
|
|
SourceFile *getPrimarySourceFile() { return PrimarySourceFile; }
|
|
|
|
/// \brief Returns true if there was an error during setup.
|
|
bool setup(const CompilerInvocation &Invocation);
|
|
|
|
/// Parses and type-checks all input files.
|
|
void performSema();
|
|
|
|
/// Parses the input file but does no type-checking or module imports.
|
|
/// Note that this only supports parsing an invocation with a single file.
|
|
///
|
|
///
|
|
void performParseOnly(bool EvaluateConditionals = false);
|
|
|
|
/// Frees up the ASTContext and SILModule objects that this instance is
|
|
/// holding on.
|
|
void freeContextAndSIL();
|
|
|
|
private:
|
|
/// Load stdlib & return true if should continue, i.e. no error
|
|
bool loadStdlib();
|
|
ModuleDecl *importUnderlyingModule();
|
|
ModuleDecl *importBridgingHeader();
|
|
|
|
void
|
|
getImplicitlyImportedModules(SmallVectorImpl<ModuleDecl *> &importModules);
|
|
|
|
public: // for static functions in Frontend.cpp
|
|
struct ImplicitImports {
|
|
SourceFile::ImplicitModuleImportKind kind;
|
|
ModuleDecl *objCModuleUnderlyingMixedFramework;
|
|
ModuleDecl *headerModule;
|
|
SmallVector<ModuleDecl *, 4> modules;
|
|
|
|
explicit ImplicitImports(CompilerInstance &compiler);
|
|
};
|
|
|
|
private:
|
|
void createREPLFile(const ImplicitImports &implicitImports) const;
|
|
std::unique_ptr<DelayedParsingCallbacks> computeDelayedParsingCallback();
|
|
|
|
void addMainFileToModule(const ImplicitImports &implicitImports);
|
|
|
|
void parseAndCheckTypes(const ImplicitImports &implicitImports);
|
|
|
|
void parseLibraryFile(unsigned BufferID,
|
|
const ImplicitImports &implicitImports,
|
|
PersistentParserState &PersistentState,
|
|
DelayedParsingCallbacks *DelayedParseCB);
|
|
|
|
/// Return true if had load error
|
|
bool
|
|
parsePartialModulesAndLibraryFiles(const ImplicitImports &implicitImports,
|
|
PersistentParserState &PersistentState,
|
|
DelayedParsingCallbacks *DelayedParseCB);
|
|
|
|
OptionSet<TypeCheckingFlags> computeTypeCheckingOptions();
|
|
|
|
void forEachFileToTypeCheck(llvm::function_ref<void(SourceFile &)> fn);
|
|
|
|
void parseAndTypeCheckMainFile(PersistentParserState &PersistentState,
|
|
DelayedParsingCallbacks *DelayedParseCB,
|
|
OptionSet<TypeCheckingFlags> TypeCheckOptions);
|
|
void performTypeCheckingAndDelayedParsing();
|
|
|
|
void finishTypeChecking(OptionSet<TypeCheckingFlags> TypeCheckOptions);
|
|
};
|
|
|
|
} // namespace swift
|
|
|
|
#endif
|