How do you look at what the compiler produced at each stage?
Predict first
Which flag prints SIL after the mandatory passes but without optimisation?
// A: -emit-silgen
// B: -emit-sil
// C: -emit-ir
- A
- B
- C
Mental model. Each flag is a window into a different room of the factory. You can stand at the one you care about and see exactly what is being built.
Ask the compiler to stop and print. swiftc -dump-ast shows the type-checked tree. -emit-silgen shows raw SIL, -emit-sil SIL after the mandatory passes, and -emit-sil -O SIL after optimisation. -emit-ir shows LLVM IR, and -S the assembly. Add -wmo to see whole-module results, and -module-name if you want readable symbol names. swift demangle '$s4main3addyS2i_SitF' turns a mangled name into main.add(Swift.Int, Swift.Int) -> Swift.Int.
For build time rather than output: -Xfrontend -debug-time-function-bodies lists the slowest function bodies, -Xfrontend -warn-long-function-bodies=200 and -warn-long-expression-type-checking=200 warn above a threshold in milliseconds, and Xcode’s Build Timeline shows parallelism. Online, Compiler Explorer shows SIL and assembly side by side. Reading even a few lines of SIL is the fastest way to settle “is this call direct?” without guessing.
-emit-silgen stops before the passes, and -emit-ir is already LLVM IR. Plain -emit-sil is SIL with the mandatory passes applied.
| Shows | |
|---|---|
-dump-ast | the type-checked syntax tree |
-emit-silgen | raw SIL, before the mandatory passes |
-emit-sil | SIL after the passes; add -O for optimised SIL |
-emit-ir | LLVM IR |
-S | assembly |
-Xfrontend -debug-time-function-bodies | type-checking time per function |
Common traps
- Reading Debug-build assembly and drawing performance conclusions. Always inspect the optimised output of the configuration you ship.
- Forgetting
-wmo. Without it, per-file output omits optimisations that need the whole module.
They might follow up with
- How do you name symbols readably? Compile a single file with
-module-name Demo, then demangle what you see. - Is SIL stable? No. Its text format changes between compiler versions, so treat it as a debugging aid, not an interface.
Related questions
- 5.1.4 How do you read SIL to tell static dispatch from dynamic dispatch?
- 5.6.1 A Swift file takes forever to compile. How do you find the cause and fix it?
← What does the compiler guarantee through its mandatory SIL passes? How do you read SIL to tell static dispatch from dynamic dispatch? →