Open-Source Wikis

/

Swift

/

Systems

/

SILGen

apple/swift

SILGen

Active contributors: jckarter, kavon, atrick

Purpose

SILGen lowers the type-checked AST to raw SIL (Swift Intermediate Language). It introduces explicit memory management, calling conventions, and the lowered semantics of language features (initializers, deinitializers, generics, closures, async/await, throws, casts, dynamic dispatch).

The output of SILGen is raw -- it has not yet been validated for definite initialization, ownership, or other invariants enforced by mandatory passes. After mandatory passes run, the SIL is canonical and is the input to IRGen. See SIL and the SIL optimizer for the post-SILGen pipeline.

Directory layout

lib/SILGen/                            (71 files)
├── SILGen.cpp                         # top-level entry: generate SIL for a SourceFile
├── SILGenFunction.cpp                 # per-function SIL emission state
├── SILGenExpr.cpp                     # lowering Exprs
├── SILGenStmt.cpp                     # lowering Stmts
├── SILGenApply.cpp                    # 8,516 lines — function application
├── SILGenBuilder.cpp                  # the IRBuilder-style SIL emitter
├── SILGenConvert.cpp                  # implicit conversions, bridging
├── SILGenDecl.cpp                     # local var decls, lazy/global init
├── SILGenDestructor.cpp
├── SILGenDistributed.cpp              # distributed actor calls
├── SILGenDynamicCast.cpp
├── SILGenEpilog.cpp
├── SILGenForeignError.cpp
├── SILGenGenerics.cpp
├── SILGenLValue.cpp                   # left-value emission
├── SILGenPattern.cpp
├── SILGenPoly.cpp                     # reabstraction thunks
├── SILGenProlog.cpp
├── SILGenStmt.cpp
└── SILGenThunk.cpp

Key abstractions

Type File Description
swift::Lowering::SILGenModule lib/SILGen/SILGen.cpp Per-module SIL generation state.
swift::Lowering::SILGenFunction lib/SILGen/SILGenFunction.cpp Per-function emission. Owns the current SILBuilder, scopes, and the cleanup stack.
swift::Lowering::ManagedValue include/swift/SIL/ManagedValue.h A SILValue plus an ownership cleanup. The unit of currency in SILGen.
swift::Lowering::Cleanup include/swift/SIL/Cleanup.h A registered piece of teardown code (release, dealloc, ...).
swift::Lowering::Scope include/swift/SIL/Scope.h Lexical scope; pops cleanups on exit.
swift::SILGenBuilder lib/SILGen/SILGenBuilder.cpp Helper API around SILBuilder for ManagedValue-aware emission.

How it works

graph TD
    AST[Typed AST] --> SILGenModule
    SILGenModule -->|"per Decl"| SILGenFunction
    SILGenFunction --> Prolog[SILGenProlog<br/>argument lowering]
    Prolog --> Body
    Body -->|"SILGenStmt / SILGenExpr"| SILBuilder
    Body --> Cleanups[Cleanup stack]
    Cleanups --> Epilog[SILGenEpilog<br/>destructors / returns]
    Epilog --> RawSIL["Raw SIL output"]

SILGen is direct-style code generation over the AST. For each function:

  1. Prolog -- introduce SIL parameters (with appropriate ownership), copy them into local boxes if the language exposes them as var, register cleanups for owned arguments.
  2. Body -- recursively visit the AST. Statements lower in SILGenStmt.cpp; expressions in SILGenExpr.cpp and SILGenApply.cpp (call expressions, with all the calling-convention complexity).
  3. Cleanup stack -- as values are produced, their Cleanups are pushed. When a scope exits, the cleanups run in reverse order, emitting destroy_addr, destroy_value, etc.
  4. Epilog -- emit return cleanup, the return instruction, and any remaining unwind machinery (for throws or async).

Notable lowering jobs

  • Reabstraction (SILGenPoly.cpp) -- when a value's calling convention has to change (e.g., (Int) -> String passed where <T, U> (T) -> U is expected), SILGen emits a reabstraction thunk. See docs/Lexicon.md entry for "abstraction pattern".
  • async/await -- SILGenApply.cpp and SILGenStmt.cpp lower await to await_async_continuation or hop_to_executor. The Concurrency runtime in stdlib/public/Concurrency/ provides the executor.
  • throws -- error-returning functions get a special "error result" parameter (@error). try becomes a try_apply instruction with an error successor.
  • Casts -- as, as?, as! lower in SILGenDynamicCast.cpp using checked_cast_addr_br / unconditional_checked_cast.
  • Property accessors -- _read, _modify, get, set, init accessors are all separate SIL functions; SILGen synthesizes them and chooses an access pattern at call sites (see docs/Lexicon.md "access pattern").
  • Generics -- generic functions lower into @generic SIL functions with archetype types. Specialization happens in the optimizer, not here.
  • Distributed actors (SILGenDistributed.cpp) -- remote calls expand into a witness for DistributedActorSystem.

Integration points

  • Reads the typed AST produced by Sema. All types must be resolved.
  • Writes raw SIL into a swift::SILModule (defined in include/swift/SIL/).
  • Coordinates with the SIL optimizer: the mandatory passes immediately following SILGen complete the lowering (definite initialization, ownership lowering for legacy paths, mandatory inlining of @_transparent and the like).
  • Knows about the standard library because it emits direct calls to Builtin operations; see lib/SILGen/SILGenBuiltin.cpp.

Entry points for modification

  • Adding a new lowering for a Decl kind: extend SILGenDecl.cpp or SILGen.cpp's emitDecl.
  • Lowering a new statement: extend SILGenStmt.cpp::SILGenFunction::emitStmt.
  • Lowering a new expression: add a visitor in SILGenExpr.cpp (SILGenFunction::emitExpr).
  • Investigating a SILGen bug: emit raw SIL via swift -frontend -emit-silgen file.swift.

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

SILGen – Swift wiki | Factory