|
| 1 | +## How to update Debug Info in the Swift Compiler |
| 2 | + |
| 3 | +### Introduction |
| 4 | + |
| 5 | +This document describes how debug info works at the SIL level and how to |
| 6 | +correctly update debug info in SIL optimization passes. This document is |
| 7 | +inspired by its LLVM analog, [How to Update Debug Info: A Guide for LLVM Pass |
| 8 | +Authors](https://llvm.org/docs/HowToUpdateDebugInfo.html), which is recommended |
| 9 | +reading, since all of the concepts discussed there also apply to SIL. |
| 10 | + |
| 11 | +### Source Locations |
| 12 | + |
| 13 | +Contrary to LLVM IR, SIL makes source locations and lexical scopes mandatory on |
| 14 | +all instructions. SIL transformations should follow the LLVM guide for when to |
| 15 | +merge drop and copy locations, since all the same considerations apply. Helpers |
| 16 | +like `SILBuilderWithScope` make it easy to copy source locations when expanding |
| 17 | +SIL instructions. |
| 18 | + |
| 19 | +### Variables, Variable Locations |
| 20 | + |
| 21 | +Source variables are represented by `debug_value` instructions, and may also be |
| 22 | +described in variable-carrying instructions (`alloc_stack`, `alloc_box`). There |
| 23 | +is no semantic difference between describing a variable in an allocation |
| 24 | +instruction directly or describing it in an `debug_value` following the |
| 25 | +allocation instruction. Variables are uniquely identified via their lexical |
| 26 | +scope, which also includes inline information, and their name and binding kind. |
| 27 | + |
| 28 | +Each `debug_value` (and variable-carrying instruction) defines an update point |
| 29 | +for the location of (part of) that source variable. A variable location is an |
| 30 | +SSA value or constant, modified by a debug expression that can transform that |
| 31 | +value, yielding the value of that variable. The debug expressions get lowered |
| 32 | +into LLVM [DIExpressions](https://llvm.org/docs/LangRef.html#diexpression) which |
| 33 | +get lowered into [DWARF](https://dwarfstd.org) expressions. Optimizations like |
| 34 | +SROA may split a source variable into multiple smaller fragments. An |
| 35 | +`op_fragment` is used to denote a location of a partial variable. Each variable |
| 36 | +(fragment) location is valid until the end of the current basic block, or until |
| 37 | +another `debug_value` describes another location for a variable fragment for the |
| 38 | +same unique variable that overlaps with that (fragment of the) variable. |
| 39 | +Variables may be undefined, in which case the SSA value is `undef`. |
| 40 | + |
| 41 | +### Rules of thumb |
| 42 | +- Optimization passes may never drop a variable entirely. If a variable is |
| 43 | + entirely optimized away, an `undef` debug value should still be kept. |
| 44 | +- A `debug_value` must always describe a correct value for that source variable |
| 45 | + at that source location. If a value is only correct on some paths through that |
| 46 | + instruction, it must be replaced with `undef`. Debug info never speculates. |
| 47 | +- When a SIL instruction referenced by a `debug_value` is (really, any |
| 48 | + instruction) deleted, call salvageDebugInfo(). It will try to capture the |
| 49 | + effect of the deleted instruction in a debug expression, so the location can |
| 50 | + be preserved. |
0 commit comments