Swirl is a statically and strongly-typed, systems programming language, leveraging the LLVM Infrastructure for optimal native code generation.
Website | Docs | Contributing
The following text is a brief on the compilation pipeline of the Compiler (details are skipped):
-
CompilerInst: the entry point, this class represents a single contained instantiation of the Compiler, owning resources which are shared across all aspects of a project's compilation. -
Module: The compiler implements a typical module system, each Swirl file is treated as a "module" which can control the visibility of the symbols it owns (or imports) to other modules (via theexportkeyword). All modules are owned and managed by an instance ofModuleManagerwhich in turn is owned byCompilerInst. -
Parser: responsible for building the Abstract Syntax Tree for modules, a Parser is created for each module and invoked to build its AST, then destroyed. The Parser owns the lexer (tokenizer). -
Sema (Semantic Analysis): sema is a multi-pass step, consisting of the following passes:
SymbolRegistrationPass: this pass registers symbols in theSymbolManagerand resolves locally-declared symbol references into their concreteIdentInfo*.SymbolResolver: handles bringing imported symbols into a module's scope and resolves all globally-declared symbol references.TypeResolver: this is the pass which owns the Type-System's implementation. It enforces type constrains and performs type-inference.
Note: unlike parsing, Sema and the succeeding steps are performed in parallel for all modules which belong in the same "batch", a batch consists of modules which do not depend on each other, this topological sorting is done by the helper class
ModuleManagerwhich also keeps ownership of everyModuleobject. -
If no errors were reported in the previous stage, the completion of Sema is followed by a post-sema pipeline which consists of the passes responsible for:
- Compile-Time Evaluation: evaluates and substitutes all
comptime-marked constructs. Resides here. - Generic Instantion: monomorphizes generic constructs based on the generic arguments passed in their invocation. Resides here.
- Compile-Time Evaluation: evaluates and substitutes all
-
LLVMBackend: this class owns the codegen logic for generating the LLVM IR, since all the needed information to codegen a Module is already built in previous stages, each Module is codegen'ed in parallel.
flowchart TB
subgraph Entry["CompilerInst (orchestrates the whole pipeline)"]
A1["• Owns ThreadPool, ErrorManager, FileSystem, StringPool<br/>• Owns ModuleManager<br/>• Calls Module::parse() for each module<br/>• Drives the batched Sema loop<br/>• Starts LLVM codegen + linking"]
end
subgraph Phase1["① Parsing Phase — Per Module"]
direction LR
M["Module<br/>(Each .swirl file)<br/>• AST, SymbolTable<br/>• BumpAllocator"]
L["Lexer / Tokenizer<br/>TokenStream + Tokens"]
P["Parser<br/>• Created per module, then destroyed<br/>• Builds AST<br/>• Owns ExpressionParser <br/>• Owns the Tokenizer (lexer)"]
M --> L --> P
end
subgraph Phase2["② Semantic Analysis — 3 Passes (batched & parallel)"]
MM["ModuleManager<br/>• Topological sort → zero-dep batches<br/>• Modules in same batch run parallel<br/>• Each module performs all 3 passes"]
SRP["1. SymbolRegistrationPass<br/>• Registers symbols in SymbolManager<br/>• Resolves local refs → IdentInfo*"]
SR["2. SymbolResolver<br/>• Imports symbols into scope<br/>• Resolves global refs"]
TR["3. TypeResolver<br/>• Type enforcement + inference<br/>• via TypeManager + SwTypes"]
MM -.- SRP --> SR --> TR
end
subgraph Phase3["③ Post-Sema"]
CT["Compile-Time Evaluation<br/>ComptimeEvaluator + Value"]
GI["Generic Instantiation<br/>GenericInstantiator + GenericSubstitutor<br/>(monomorphization)"]
end
subgraph Phase4["④ LLVM Codegen"]
CG["LLVMBackend<br/>• Generates LLVM IR per module (parallel)<br/>• Object file generation"]
LINK["Linker — links objects + deps → executable"]
end
Entry -->|"Module::parse()"| Phase1
Phase1 -->|"AST"| Phase2
Phase2 -->|"no errors"| Phase3
Phase3 --> Phase4
CG --> LINK
LINK --> DONE["[Done]"]
style Entry fill:#1a1a2e,color:#eee,stroke:#e94560,stroke-width:2px
style Phase1 fill:#533483,color:#eee,stroke:#e94560,stroke-width:2px
style Phase2 fill:#0f3460,color:#eee,stroke:#e94560,stroke-width:2px
style Phase3 fill:#16213e,color:#eee,stroke:#e94560,stroke-width:2px
style Phase4 fill:#1a1a2e,color:#eee,stroke:#e94560,stroke-width:2px
We welcome contributions to Swirl! To start contributing to Swirl, fork the repository, create a new branch, make the changes, and submit a pull request. Read the Docs for more info.
If you want to request a new feature or report a bug, you can use the GitHub issues tracker. We will do our best to respond as quickly.