Skip to content

Commit 1231dda

Browse files
aparshin-inteligcbot
authored andcommitted
update documentation for GenXDebugInfo pass
1 parent 1cc258e commit 1231dda

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

IGC/VectorCompiler/lib/GenXCodeGen/GenXDebugInfo.cpp

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,186 @@ SPDX-License-Identifier: MIT
3434

3535
#include "Probe/Assertion.h"
3636

37+
//
38+
/// GenXDebugInfo
39+
/// -------------
40+
///
41+
/// The goal of the pass is to provide debug information for each generated
42+
/// genisa instruction (if such information is available). The debug
43+
/// information is encoded in DWARF format.
44+
///
45+
/// Ultimately, the pass gets data from 2 sources:
46+
///
47+
/// 1. LLVM debug information encoded in LLVM IR itself. It captures the
48+
/// important pieces of the source language's Abstract Syntax Tree and
49+
/// maps it onto LLVM code.
50+
/// LLVM framework should maintain it automatically, given that we follow
51+
/// relatively simple rules while designing IR transformations:
52+
/// https://llvm.org/docs/HowToUpdateDebugInfo.html
53+
///
54+
/// 2. Debug information obtained from the finalizer. This information is
55+
/// encoded in some proprietary format (blob) and contains the following:
56+
/// a. mapping between vISA and genISA instructions
57+
/// b. live intervals of the virtual registers, information about spilled
58+
/// values, etc.
59+
/// c. call frame information
60+
///
61+
/// The pass feeds the above information to the DebugInfo library which in turn
62+
/// produces the final DWARF.
63+
///
64+
/// Operation of the pass
65+
/// ^^^^^^^^^^^^^^^^^^^^^
66+
///
67+
/// The pass assumes that some data is already being made available by other
68+
/// passes/analysis.
69+
///
70+
/// * FunctionGroupAnalysis:
71+
/// provides information about the overall "structure"
72+
/// of the program: functions, stack calls, indirect calls, subroutines and
73+
/// relationships.
74+
///
75+
/// * GenXModule:
76+
/// 1. for each LLVM Function provides information about
77+
/// LLVM instruction -> vISA instructions mapping. This information is
78+
/// produced/maintained during operation of CISABuilder pass.
79+
/// 2. for each LLVM Function provides access to a corresponding
80+
/// *VISAKernel* object.
81+
///
82+
/// * GenXVisaRegAlloc:
83+
/// provides the mapping between LLVM values and virtual registers.
84+
///
85+
/// * GenXCisaBuilder:
86+
/// provides access to VISABuilder, which allows us to have access to
87+
/// VISAKernel objects (some Functions from LLVM IR, like the ones
88+
/// representing kernel spawns these) that contain:
89+
/// a. debug information maintained by finalizer (see above)
90+
/// b. the respected gen binaries
91+
///
92+
/// Data Structures
93+
/// ^^^^^^^^^^^^^^^
94+
///
95+
/// Since data is aggregated from different sources, some extra data structures
96+
/// are used to simplify bookkeeping.
97+
///
98+
/// - *genx::di::VisaMapping*
99+
/// provides the mapping from LLMV IR instruction to vISA instruction index,
100+
/// that represents the first vISA instruction spawned by the LLVM IR
101+
/// instruction. A single LLVM IR instruction can spawn several
102+
/// vISA instructions - currently the number of spawned instructions is
103+
/// derived implicitly (which is not always correct but works in most of the
104+
/// cases).
105+
///
106+
/// - *ProgramInfo*
107+
/// A transient object that groups several llvm Functions that are eventually
108+
/// get compiled into a single gen entity. A separate elf file with the
109+
/// debug information is generated for each gen entity.
110+
///
111+
/// The grouping is done as follows:
112+
/// - We piggyback on FunctionGroup analysis. Each kernel function becomes the
113+
/// head of the group. Different FunctionGroups always result in different
114+
/// *ProgramInfo* objects. However, a single FunctionGroup can be split even
115+
/// further. This can happen if we have an indirect call to some function. In
116+
/// this case, this function shall is compiled into a separate gen object
117+
/// (and a separate VISAKernel is produced aswell).
118+
///
119+
/// The above approach does not work correctly in all cases. See
120+
/// *KNOWN ISSUES* section.
121+
///
122+
/// - *CompiledVisaWrapper*
123+
/// For an arbitrary pair of llvm IR Function and VISAKernel objects,
124+
/// does the following:
125+
/// + Validates that IR Function and VISAKernel object are related (that is
126+
/// the vISA spawned by IR Function is owned by the VISAKernel.
127+
/// + Extracts Gen Binary.
128+
/// + Extracts Debug Info Blob from finalizer and decodes it.
129+
///
130+
/// *GenXFunction*
131+
/// An object that loosely resembles MachineFunctoin from the LLVM Machine IR.
132+
/// This is an object that for a given LLVM IR Function can access to:
133+
/// - LLVM IR Function
134+
/// - VisaMapping
135+
/// - Subtarget
136+
/// - CompiledVisaWrapper
137+
/// - GenXVisaRegAlloc
138+
/// GenXFunctoin serves as a primary method to communicate with the DebugInfo
139+
/// library. The data these objects hold allow us to reason about the debug
140+
/// information for any Gen construct (instruction, variable, etc).
141+
///
142+
/// Examples
143+
/// ^^^^^^^^
144+
///
145+
/// Examples below use the following naming conventions:
146+
/// K* - kernel function
147+
/// L* - subroutine (non-inlined function)
148+
/// S* - simple stack call
149+
/// I* - indirectly-called function
150+
///
151+
/// FunctionGroup construction peculiarities.
152+
///
153+
/// When function groups are constructed, we do some peculiar transformations.
154+
///
155+
/// Case_1 (FG):
156+
/// Source Code: { K1 calls L1, K2 calls L1 }
157+
/// IR after function groups: { G1 = {K1, L1}, G2 = { K2, L1'} },
158+
/// where L1' is a clone of L1.
159+
/// Case_2 (FG):
160+
/// Source Code: { K1 calls S_1, both call L1 }.
161+
/// IR after function groups: { G1 = {K1, L1, S1, L1' } }.
162+
/// Case_3 (FG):
163+
/// Source Code: { K1 calls I1 and I2 }.
164+
/// IR after function grups { G1 = {K1}, G2 = {I1}, G3={I2} }.
165+
///
166+
/// VISA/genISA construction peculiarities.
167+
///
168+
/// Case 1:
169+
/// Source code: K1, K1.
170+
/// Compilation phase:
171+
/// two function groups are created, K1 and K2 are heads.
172+
/// two different VISAKernel produced.
173+
/// DebugInfoGeneration:
174+
/// Decoded Debug info for each VISAKernel contains:
175+
/// one compiled object description.
176+
/// two "*.elf" files are created.
177+
///
178+
/// Case 2:
179+
/// Source code: K1, S1. K1 calls S1.
180+
/// Compilation phase:
181+
/// 1 function group is created, K1 is the head.
182+
/// 1 VISAKernel and 1 VISAFunction are created.
183+
/// DebugInfoGeneratation:
184+
/// Decoded debug info contains *2* compiled objects.
185+
/// Each object has separate vISA indexes - visa instructions are
186+
/// counted separately. Still, both are compiled into the same gen
187+
/// object, so only one "*.elf" file is emitted.
188+
///
189+
/// Case 3:
190+
/// Source code: K1, I1. K1 calls I1
191+
/// Compilation phase:
192+
/// 1 function group is created, K1 is the head.
193+
/// Somehow 2 VISAKernels are created.
194+
/// DebugInfoGeneratation:
195+
/// Decoded debug info contains *1* compiled objects (but we have 2
196+
/// VISAKernel).
197+
/// In the end, we emit two "*.elf" files.
198+
///
199+
/// KNOWN ISSUES
200+
/// ^^^^^^^^^^^^
201+
///
202+
/// Note: see the "Examples" section for the description of the used naming
203+
/// convention.
204+
///
205+
/// Case 1: (debug info can't be emitted)
206+
/// Source code: *K1*, *L1* *K1* calls *L1*.
207+
/// Compilation phase:
208+
/// 1 function group is created.
209+
/// 1 VISAKernel produced.
210+
/// DebugInfoGeneration:
211+
/// 1 *ProgramInfo* created { K1, L1}.
212+
/// Decoded Debug info contains 1 compiled object, that has 1 subroutines.
213+
///
214+
/// Problem: way to map LLVM Function onto subroutine is not implemented.
215+
//===----------------------------------------------------------------------===//
216+
37217
#define DEBUG_TYPE "GENX_DEBUG_INFO"
38218

39219
using namespace llvm;

0 commit comments

Comments
 (0)