mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Adds a tool `swift-symbolgraph-extract` that reads an existing Swift module and prints a platform- and language-agnostic JSON description of the module, primarly for documentation. Adds a small sub-library `SymbolGraphGen` which houses the core implementation for collecting relevant information about declarations. The main entry point is integrated directly into the driver as a mode: the tool is meant to be run outside of the normal edit-compile-run/test workflow to avoid impacting build times. Along with common options for other tools, unique options include `pretty-print` for debugging, and a `minimum-access-level` options for including internal documentation. A symbol graph is a directed graph where the nodes are symbols in a module and the edges are relationships between them. For example, a `struct S` may have a member `var x`. The graph would have two nodes for `S` and `x`, and one "member-of" relationship edge. Other relationship kinds include "inherits-from" or "conforms to". The data format for a symbol graph is still under development and may change without notice until a specificiation and versioning scheme is published. Various aspects about a symbol are recorded in the nodes, such as availability, documentation comments, or data needed for printing the shapes of declarations without having to understand specifics about the langauge. Implicit and public-underscored stdlib declarations are not included by default. rdar://problem/55346798
442 lines
17 KiB
C++
442 lines
17 KiB
C++
//===--- Driver.h - Swift compiler driver -----------------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 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 parts of the compiler driver.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_DRIVER_DRIVER_H
|
|
#define SWIFT_DRIVER_DRIVER_H
|
|
|
|
#include "swift/AST/IRGenOptions.h"
|
|
#include "swift/Basic/FileTypes.h"
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "swift/Basic/OptionSet.h"
|
|
#include "swift/Basic/OutputFileMap.h"
|
|
#include "swift/Basic/Sanitizers.h"
|
|
#include "swift/Driver/Util.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace llvm {
|
|
namespace opt {
|
|
class Arg;
|
|
class ArgList;
|
|
class OptTable;
|
|
class InputArgList;
|
|
class DerivedArgList;
|
|
}
|
|
}
|
|
|
|
namespace swift {
|
|
namespace sys {
|
|
class TaskQueue;
|
|
}
|
|
class DiagnosticEngine;
|
|
namespace driver {
|
|
class Action;
|
|
class CommandOutput;
|
|
class Compilation;
|
|
class Job;
|
|
class JobAction;
|
|
class ToolChain;
|
|
|
|
/// A class encapsulating information about the outputs the driver
|
|
/// is expected to generate.
|
|
class OutputInfo {
|
|
public:
|
|
enum class Mode {
|
|
/// A standard compilation, using multiple frontend invocations and
|
|
/// -primary-file.
|
|
StandardCompile,
|
|
|
|
/// A compilation using a single frontend invocation without -primary-file.
|
|
SingleCompile,
|
|
|
|
/// A single process that batches together multiple StandardCompile Jobs.
|
|
///
|
|
/// Note: this is a transient value to use _only_ for the individual
|
|
/// BatchJobs that are the temporary containers for multiple StandardCompile
|
|
/// Jobs built by ToolChain::constructBatchJob.
|
|
///
|
|
/// In particular, the driver treats a batch-mode-enabled Compilation as
|
|
/// having OutputInfo::CompilerMode == StandardCompile, with the
|
|
/// Compilation::BatchModeEnabled flag set to true, _not_ as a
|
|
/// BatchModeCompile Compilation. The top-level OutputInfo::CompilerMode for
|
|
/// a Compilation should never be BatchModeCompile.
|
|
BatchModeCompile,
|
|
|
|
/// Invoke the REPL
|
|
REPL,
|
|
|
|
/// Compile and execute the inputs immediately
|
|
Immediate,
|
|
};
|
|
|
|
enum class MSVCRuntime {
|
|
MultiThreaded,
|
|
MultiThreadedDebug,
|
|
MultiThreadedDLL,
|
|
MultiThreadedDebugDLL,
|
|
};
|
|
|
|
/// The mode in which the driver should invoke the frontend.
|
|
Mode CompilerMode = Mode::StandardCompile;
|
|
|
|
Optional<MSVCRuntime> RuntimeVariant = llvm::None;
|
|
|
|
/// The output type which should be used for compile actions.
|
|
file_types::ID CompilerOutputType = file_types::ID::TY_INVALID;
|
|
|
|
/// Describes if and how the output of compile actions should be
|
|
/// linked together.
|
|
LinkKind LinkAction = LinkKind::None;
|
|
|
|
/// Returns true if the linker will be invoked at all.
|
|
bool shouldLink() const { return LinkAction != LinkKind::None; }
|
|
|
|
/// Whether or not the output should contain debug info.
|
|
// FIXME: Eventually this should be replaced by dSYM generation.
|
|
IRGenDebugInfoLevel DebugInfoLevel = IRGenDebugInfoLevel::None;
|
|
|
|
/// What kind of debug info to generate.
|
|
IRGenDebugInfoFormat DebugInfoFormat = IRGenDebugInfoFormat::None;
|
|
|
|
/// Whether or not the driver should generate a module.
|
|
bool ShouldGenerateModule = false;
|
|
|
|
/// Whether or not the driver should treat a generated module as a top-level
|
|
/// output.
|
|
bool ShouldTreatModuleAsTopLevelOutput = false;
|
|
|
|
/// Whether the compiler picked the current module name, rather than the user.
|
|
bool ModuleNameIsFallback = false;
|
|
|
|
/// The number of threads for multi-threaded compilation.
|
|
unsigned numThreads = 0;
|
|
|
|
/// Returns true if multi-threading is enabled.
|
|
bool isMultiThreading() const { return numThreads > 0; }
|
|
|
|
/// The name of the module which we are building.
|
|
std::string ModuleName;
|
|
|
|
/// The path to the SDK against which to build.
|
|
/// (If empty, this implies no SDK.)
|
|
std::string SDKPath;
|
|
|
|
OptionSet<SanitizerKind> SelectedSanitizers;
|
|
|
|
/// Might this sort of compile have explicit primary inputs?
|
|
/// When running a single compile for the whole module (in other words
|
|
/// "whole-module-optimization" mode) there must be no -primary-input's and
|
|
/// nothing in a (preferably non-existent) -primary-filelist. Left to its own
|
|
/// devices, the driver would forget to omit the primary input files, so
|
|
/// return a flag here.
|
|
bool mightHaveExplicitPrimaryInputs(const CommandOutput &Output) const;
|
|
};
|
|
|
|
class Driver {
|
|
public:
|
|
/// DriverKind determines how later arguments are parsed, as well as the
|
|
/// allowable OutputInfo::Mode values.
|
|
enum class DriverKind {
|
|
Interactive, // swift
|
|
Batch, // swiftc
|
|
AutolinkExtract, // swift-autolink-extract
|
|
SwiftIndent, // swift-indent
|
|
SymbolGraph // swift-symbolgraph
|
|
};
|
|
|
|
class InputInfoMap;
|
|
|
|
private:
|
|
std::unique_ptr<llvm::opt::OptTable> Opts;
|
|
|
|
DiagnosticEngine &Diags;
|
|
|
|
/// The name the driver was invoked as.
|
|
std::string Name;
|
|
|
|
/// The original path to the executable.
|
|
std::string DriverExecutable;
|
|
|
|
// Extra args to pass to the driver executable
|
|
SmallVector<std::string, 2> DriverExecutableArgs;
|
|
|
|
DriverKind driverKind = DriverKind::Interactive;
|
|
|
|
/// Default target triple.
|
|
std::string DefaultTargetTriple;
|
|
|
|
/// Indicates whether the driver should print bindings.
|
|
bool DriverPrintBindings;
|
|
|
|
/// Indicates whether the driver should suppress the "no input files" error.
|
|
bool SuppressNoInputFilesError = false;
|
|
|
|
/// Indicates whether the driver should check that the input files exist.
|
|
bool CheckInputFilesExist = true;
|
|
|
|
public:
|
|
Driver(StringRef DriverExecutable, StringRef Name,
|
|
ArrayRef<const char *> Args, DiagnosticEngine &Diags);
|
|
~Driver();
|
|
|
|
const llvm::opt::OptTable &getOpts() const { return *Opts; }
|
|
|
|
const DiagnosticEngine &getDiags() const { return Diags; }
|
|
|
|
const std::string &getSwiftProgramPath() const {
|
|
return DriverExecutable;
|
|
}
|
|
|
|
ArrayRef<std::string> getSwiftProgramArgs() const {
|
|
return DriverExecutableArgs;
|
|
}
|
|
|
|
DriverKind getDriverKind() const { return driverKind; }
|
|
|
|
ArrayRef<const char *> getArgsWithoutProgramNameAndDriverMode(
|
|
ArrayRef<const char *> Args) const;
|
|
|
|
bool getCheckInputFilesExist() const { return CheckInputFilesExist; }
|
|
|
|
void setCheckInputFilesExist(bool Value) { CheckInputFilesExist = Value; }
|
|
|
|
/// Creates an appropriate ToolChain for a given driver, given the target
|
|
/// specified in \p Args (or the default target). Sets the value of \c
|
|
/// DefaultTargetTriple from \p Args as a side effect.
|
|
///
|
|
/// \return A ToolChain, or nullptr if an unsupported target was specified
|
|
/// (in which case a diagnostic error is also signalled).
|
|
///
|
|
/// This uses a std::unique_ptr instead of returning a toolchain by value
|
|
/// because ToolChain has virtual methods.
|
|
std::unique_ptr<ToolChain>
|
|
buildToolChain(const llvm::opt::InputArgList &ArgList);
|
|
|
|
/// Compute the task queue for this compilation and command line argument
|
|
/// vector.
|
|
///
|
|
/// \return A TaskQueue, or nullptr if an invalid number of parallel jobs is
|
|
/// specified. This condition is signalled by a diagnostic.
|
|
std::unique_ptr<sys::TaskQueue> buildTaskQueue(const Compilation &C);
|
|
|
|
/// Construct a compilation object for a given ToolChain and command line
|
|
/// argument vector.
|
|
///
|
|
/// \return A Compilation, or nullptr if none was built for the given argument
|
|
/// vector. A null return value does not necessarily indicate an error
|
|
/// condition; the diagnostics should be queried to determine if an error
|
|
/// occurred.
|
|
std::unique_ptr<Compilation>
|
|
buildCompilation(const ToolChain &TC,
|
|
std::unique_ptr<llvm::opt::InputArgList> ArgList);
|
|
|
|
/// Parse the given list of strings into an InputArgList.
|
|
std::unique_ptr<llvm::opt::InputArgList>
|
|
parseArgStrings(ArrayRef<const char *> Args);
|
|
|
|
/// Resolve path arguments if \p workingDirectory is non-empty, and translate
|
|
/// inputs from -- arguments into a DerivedArgList.
|
|
llvm::opt::DerivedArgList *
|
|
translateInputAndPathArgs(const llvm::opt::InputArgList &ArgList,
|
|
StringRef workingDirectory) const;
|
|
|
|
/// Construct the list of inputs and their types from the given arguments.
|
|
///
|
|
/// \param TC The current tool chain.
|
|
/// \param Args The input arguments.
|
|
/// \param[out] Inputs The list in which to store the resulting compilation
|
|
/// inputs.
|
|
void buildInputs(const ToolChain &TC, const llvm::opt::DerivedArgList &Args,
|
|
InputFileList &Inputs) const;
|
|
|
|
/// Construct the OutputInfo for the driver from the given arguments.
|
|
///
|
|
/// \param TC The current tool chain.
|
|
/// \param Args The input arguments.
|
|
/// \param BatchMode Whether the driver has been explicitly or implicitly
|
|
/// instructed to use batch mode.
|
|
/// \param Inputs The inputs to the driver.
|
|
/// \param[out] OI The OutputInfo in which to store the resulting output
|
|
/// information.
|
|
void buildOutputInfo(const ToolChain &TC,
|
|
const llvm::opt::DerivedArgList &Args,
|
|
const bool BatchMode, const InputFileList &Inputs,
|
|
OutputInfo &OI) const;
|
|
|
|
/// Construct the list of Actions to perform for the given arguments,
|
|
/// which are only done for a single architecture.
|
|
///
|
|
/// \param[out] TopLevelActions The main Actions to build Jobs for.
|
|
/// \param TC the default host tool chain.
|
|
/// \param OI The OutputInfo for which Actions should be generated.
|
|
/// \param OutOfDateMap If present, information used to decide which files
|
|
/// need to be rebuilt.
|
|
/// \param C The Compilation to which Actions should be added.
|
|
void buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
|
|
const ToolChain &TC, const OutputInfo &OI,
|
|
const InputInfoMap *OutOfDateMap,
|
|
Compilation &C) const;
|
|
|
|
/// Construct the OutputFileMap for the driver from the given arguments.
|
|
Optional<OutputFileMap>
|
|
buildOutputFileMap(const llvm::opt::DerivedArgList &Args,
|
|
StringRef workingDirectory,
|
|
bool addEntriesForSourceRangeDependencies) const;
|
|
|
|
/// Add top-level Jobs to Compilation \p C for the given \p Actions and
|
|
/// OutputInfo.
|
|
///
|
|
/// \param TopLevelActions The main Actions to build Jobs for.
|
|
/// \param OI The OutputInfo for which Jobs should be generated.
|
|
/// \param OFM The OutputFileMap for which Jobs should be generated.
|
|
/// \param workingDirectory If non-empty, used to resolve any generated paths.
|
|
/// \param TC The ToolChain to build Jobs with.
|
|
/// \param C The Compilation containing the Actions for which Jobs should be
|
|
/// created.
|
|
void buildJobs(ArrayRef<const Action *> TopLevelActions, const OutputInfo &OI,
|
|
const OutputFileMap *OFM, StringRef workingDirectory,
|
|
const ToolChain &TC, Compilation &C) const;
|
|
|
|
/// A map for caching Jobs for a given Action/ToolChain pair
|
|
using JobCacheMap =
|
|
llvm::DenseMap<std::pair<const Action *, const ToolChain *>, Job *>;
|
|
|
|
/// Create a Job for the given Action \p A, including creating any necessary
|
|
/// input Jobs.
|
|
///
|
|
/// \param C The Compilation which this Job will eventually be part of
|
|
/// \param JA The Action for which a Job should be created
|
|
/// \param OFM The OutputFileMap for which a Job should be created
|
|
/// \param AtTopLevel indicates whether or not this is a top-level Job
|
|
/// \param JobCache maps existing Action/ToolChain pairs to Jobs
|
|
///
|
|
/// \returns a Job for the given Action/ToolChain pair
|
|
Job *buildJobsForAction(Compilation &C, const JobAction *JA,
|
|
const OutputFileMap *OFM,
|
|
StringRef workingDirectory,
|
|
bool AtTopLevel, JobCacheMap &JobCache) const;
|
|
|
|
private:
|
|
void computeMainOutput(Compilation &C, const JobAction *JA,
|
|
const OutputFileMap *OFM, bool AtTopLevel,
|
|
SmallVectorImpl<const Action *> &InputActions,
|
|
SmallVectorImpl<const Job *> &InputJobs,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
StringRef BaseInput,
|
|
StringRef PrimaryInput,
|
|
llvm::SmallString<128> &Buf,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseSwiftModuleOutputPath(Compilation &C,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseSwiftModuleDocOutputPath(Compilation &C,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseSwiftSourceInfoOutputPath(Compilation &C,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
|
|
StringRef workingDirectory,
|
|
llvm::SmallString<128> &buffer,
|
|
CommandOutput *output) const;
|
|
|
|
void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseSerializedDiagnosticsPath(Compilation &C, const JobAction *JA,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseDependenciesOutputPaths(Compilation &C,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
llvm::SmallString<128> &Buf,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseOptimizationRecordPath(Compilation &C,
|
|
StringRef workingDirectory,
|
|
llvm::SmallString<128> &Buf,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseObjectiveCHeaderOutputPath(Compilation &C,
|
|
const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseLoadedModuleTracePath(Compilation &C,
|
|
StringRef workingDirectory,
|
|
llvm::SmallString<128> &Buf,
|
|
CommandOutput *Output) const;
|
|
|
|
void chooseTBDPath(Compilation &C, const TypeToPathMap *OutputMap,
|
|
StringRef workingDirectory, llvm::SmallString<128> &Buf,
|
|
CommandOutput *Output) const;
|
|
|
|
public:
|
|
/// Handle any arguments which should be treated before building actions or
|
|
/// binding tools.
|
|
///
|
|
/// \return Whether any compilation should be built for this invocation
|
|
bool handleImmediateArgs(const llvm::opt::ArgList &Args, const ToolChain &TC);
|
|
|
|
/// Print the list of Actions in a Compilation.
|
|
void printActions(const Compilation &C) const;
|
|
|
|
/// Print the driver version.
|
|
void printVersion(const ToolChain &TC, raw_ostream &OS) const;
|
|
|
|
/// Print the help text.
|
|
///
|
|
/// \param ShowHidden Show hidden options.
|
|
void printHelp(bool ShowHidden) const;
|
|
|
|
private:
|
|
/// Parse the driver kind.
|
|
///
|
|
/// \param Args The arguments passed to the driver (excluding the path to the
|
|
/// driver)
|
|
void parseDriverKind(ArrayRef<const char *> Args);
|
|
|
|
/// Examine potentially conficting arguments and warn the user if
|
|
/// there is an actual conflict.
|
|
/// \param Args The input arguments.
|
|
/// \param Inputs The inputs to the driver.
|
|
/// \param BatchModeOut An out-parameter flag that indicates whether to
|
|
/// batch the jobs of the resulting \c Mode::StandardCompile compilation.
|
|
OutputInfo::Mode computeCompilerMode(const llvm::opt::DerivedArgList &Args,
|
|
const InputFileList &Inputs,
|
|
bool &BatchModeOut) const;
|
|
};
|
|
|
|
} // end namespace driver
|
|
} // end namespace swift
|
|
|
|
#endif
|