Factory.ai

Open-Source Wikis

/

Swift

/

Systems

/

Frontend and driver

apple/swift

Frontend and driver

Active contributors: jrose-apple, DougGregor, akyrtzi

Purpose

The driver is the user-facing swift / swiftc binary that orchestrates a build: discovering source files, planning compile / link jobs, parallelizing them, and invoking the frontend per file. The frontend (swift -frontend) is the per-invocation compiler that actually parses, type-checks, and lowers a single primary file (or a whole module) to an output artifact.

Directory layout

tools/driver/
└── driver.cpp             # main entry point (5 lines)

lib/DriverTool/            # subcommand dispatch (driver vs frontend vs ...)
├── DriverTool.cpp
├── modulewrap_main.cpp
├── swift_api_digester_main.cpp
├── swift_api_extract_main.cpp
└── swift_symbolgraph_extract_main.cpp

lib/Driver/                # the C++ driver (legacy / fallback)
├── Driver.cpp
├── Compilation.cpp
├── Job.cpp
├── DarwinToolChains.cpp
├── UnixToolChains.cpp
├── WindowsToolChains.cpp
└── WebAssemblyToolChains.cpp

lib/Frontend/              # frontend orchestration
├── CompilerInvocation.cpp
├── Frontend.cpp
├── FrontendOptions.cpp
├── ModuleInterfaceLoader.cpp
└── ParseableInterfaceModuleLoader.cpp

lib/FrontendTool/          # frontend body (the actual compile)
└── FrontendTool.cpp        # the dispatch from -frontend args to outputs

The default user-facing driver is actually the Swift-implemented swift-driver which lives in a sibling repo. The C++ lib/Driver/ here is a fallback used for some legacy paths and for bootstrapping.

Key abstractions

Type File Description
swift::mainEntry lib/DriverTool/DriverTool.cpp Decides which subcommand was requested.
swift::Driver lib/Driver/Driver.cpp Top-level driver: parses args, plans jobs.
swift::driver::Compilation lib/Driver/Compilation.cpp Owns the planned set of Jobs and runs them.
swift::driver::Job lib/Driver/Job.cpp One subprocess invocation (compile, link, etc.).
swift::driver::ToolChain lib/Driver/ToolChain.cpp Per-platform compiler/linker selection.
swift::CompilerInvocation include/swift/Frontend/Frontend.h Parsed swift -frontend flags.
swift::CompilerInstance include/swift/Frontend/Frontend.h Live state: ASTContext, source manager, modules.
swift::FrontendOptions include/swift/Frontend/FrontendOptions.h Frontend-specific options enum.
swift::performFrontend lib/FrontendTool/FrontendTool.cpp The frontend's main loop: dispatches to per-action handlers.

How it works

sequenceDiagram
    participant Bin as swift / swiftc binary
    participant DT as DriverTool
    participant Driver as lib/Driver
    participant Frontend as lib/FrontendTool
    Bin->>DT: mainEntry(argc, argv)
    DT->>DT: pick mode by argv[0] / first arg
    alt user invoked driver
        DT->>Driver: Driver::buildCompilation(args)
        Driver->>Driver: discover inputs, plan jobs
        loop per primary file
            Driver->>Frontend: spawn `swift -frontend ...`
            Frontend-->>Driver: .o or .swiftmodule
        end
        Driver->>Driver: link
    else user passed -frontend
        DT->>Frontend: performFrontend(args)
        Frontend-->>Bin: exit code
    end

Driver vs swift-driver

Two implementations exist:

  1. C++ lib/Driver/ -- in this repo, written years ago. Used as a fallback and for some legacy paths (e.g., swift-frontend -emit-stub). Each ToolChain derived class (DarwinToolChains.cpp, UnixToolChains.cpp, WindowsToolChains.cpp, WebAssemblyToolChains.cpp) describes how to invoke the linker, the assembler, and any post-processing tools for that platform.
  2. swift-driver -- a separate Swift-implemented driver in swiftlang/swift-driver. Shipping toolchains use it by default. It links against the same options definitions in lib/Option/.

The frontend's main loop

swift::performFrontend (in lib/FrontendTool/FrontendTool.cpp) is a giant switch on the requested action (-emit-object, -emit-sil, -emit-ir, -typecheck, -emit-module, -emit-symbol-graph, ...). For each primary file:

  1. Build a CompilerInstance (loads the standard library, sets up the ASTContext).
  2. Parse and type-check the primary file.
  3. If the action wants SIL: run SILGen, then the optimizer.
  4. If the action wants IR or an object: run IRGen.
  5. Emit the artifact.

-emit-sib (Swift Intermediate Bitcode) and -emit-module are short-circuit paths that stop at SIL or AST serialization respectively.

Integration points

  • The driver consumes the central options database in lib/Option/Options.td (TableGen). The same .td is used by lib/DriverTool/, swift-driver, and frontend option parsing.
  • The driver invokes Clang for -x c inputs and the linker (ld64, lld, link.exe) per ToolChain.
  • The frontend depends on essentially every other compiler library (AST, Sema, SILGen, SILOptimizer, IRGen, Serialization, Frontend, ClangImporter, Index, IDE, Migrator, ...).

Entry points for modification

  • Adding a new compile action (e.g., -emit-foo): edit lib/Frontend/FrontendOptions.cpp to recognize the option, add a case in performFrontend in lib/FrontendTool/FrontendTool.cpp, and wire it through CompilerInvocation.
  • Adding a driver flag: add to lib/Option/Options.td, then handle it in Driver.cpp and pass through to the frontend.
  • Adding a new ToolChain: subclass swift::driver::ToolChain in lib/Driver/, register in Driver::buildToolChain.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Frontend and driver – Swift wiki | Factory