1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2020-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #include "FunctionGroup.h"
10 
11 #include "GenXDebugInfo.h"
12 #include "GenXTargetMachine.h"
13 #include "GenXVisaRegAlloc.h"
14 
15 #include "vc/GenXOpts/Utils/KernelInfo.h"
16 #include "vc/Support/BackendConfig.h"
17 #include "vc/Support/GenXDiagnostic.h"
18 
19 #include "visa/include/visaBuilder_interface.h"
20 
21 #include "DebugInfo/StreamEmitter.hpp"
22 #include "DebugInfo/VISAIDebugEmitter.hpp"
23 #include "DebugInfo/VISAModule.hpp"
24 
25 #include <llvm/Analysis/CallGraph.h>
26 #include <llvm/CodeGen/TargetPassConfig.h>
27 #include <llvm/IR/DebugInfoMetadata.h>
28 #include <llvm/IR/Function.h>
29 #include <llvm/IR/Instruction.h>
30 #include <llvm/IR/IntrinsicInst.h>
31 #include <llvm/InitializePasses.h>
32 #include <llvm/Support/CommandLine.h>
33 #include <llvm/Support/Casting.h>
34 #include <llvm/Support/Errc.h>
35 #include <llvm/Support/Error.h>
36 
37 #include "llvmWrapper/IR/DerivedTypes.h"
38 
39 #include "Probe/Assertion.h"
40 
41 #include <unordered_set>
42 
43 //
44 /// GenXDebugInfo
45 /// -------------
46 ///
47 /// The goal of the pass is to provide debug information for each generated
48 /// genisa instruction (if such information is available).  The debug
49 /// information is encoded in DWARF format.
50 ///
51 /// Ultimately, the pass gets data from 2 sources:
52 ///
53 ///   1. LLVM debug information encoded in LLVM IR itself. It captures the
54 ///   important pieces of the source language's Abstract Syntax Tree and
55 ///   maps it onto LLVM code.
56 ///   LLVM framework should maintain it automatically, given that we follow
57 ///   relatively simple rules while designing IR transformations:
58 ///      https://llvm.org/docs/HowToUpdateDebugInfo.html
59 ///
60 ///   2. Debug information obtained from the finalizer. This information is
61 ///   encoded in some proprietary format (blob) and contains the following:
62 ///     a. mapping between vISA and genISA instructions
63 ///     b. live intervals of the virtual registers, information about spilled
64 ///     values, etc.
65 ///     c. call frame information
66 ///
67 /// The pass feeds the above information to the DebugInfo library which in turn
68 /// produces the final DWARF.
69 ///
70 /// Operation of the pass
71 /// ^^^^^^^^^^^^^^^^^^^^^
72 ///
73 /// The pass assumes that some data is already being made available by other
74 /// passes/analysis.
75 ///
76 /// * FunctionGroupAnalysis:
77 ///     provides information about the overall "structure"
78 ///     of the program: functions, stack calls, indirect calls, subroutines and
79 ///     relationships.
80 ///
81 /// * GenXModule:
82 ///     1. for each LLVM Function provides information about
83 ///        LLVM instruction -> vISA instructions mapping. This information is
84 ///        produced/maintained during operation of CISABuilder pass.
85 ///     2. for each LLVM Function provides access to a corresponding
86 ///      *VISAKernel* object.
87 ///
88 /// * GenXVisaRegAlloc:
89 ///     provides the mapping between LLVM values and virtual registers.
90 ///
91 /// * GenXCisaBuilder:
92 ///     provides access to VISABuilder, which allows us to have access to
93 ///     VISAKernel objects (some Functions from LLVM IR, like the ones
94 ///     representing kernel spawns these) that contain:
95 ///         a. debug information maintained by finalizer (see above)
96 ///         b. the respected gen binaries
97 ///
98 /// Data Structures
99 /// ^^^^^^^^^^^^^^^
100 ///
101 /// Since data is aggregated from different sources, some extra data structures
102 /// are used to simplify bookkeeping.
103 ///
104 /// - *genx::di::VisaMapping*
105 ///   provides the mapping from LLMV IR instruction to vISA instruction index,
106 ///   that represents the first vISA instruction spawned by the LLVM IR
107 ///   instruction. A single LLVM IR instruction can spawn several
108 ///   vISA instructions - currently the number of spawned instructions is
109 ///   derived implicitly (which is not always correct but works in most of the
110 ///   cases).
111 ///
112 /// - *ModuleToVisaTransformInfo*
113 ///   Provides information about how LLVM IR functions are mapped onto various
114 ///   vISA (and genISA) objects. Allows us to answer the following questions:
115 ///     - Is a function a subroutine on vISA level?
116 ///     - If a function is a subroutine, what LLVM IR function corresponds to
117 ///     vISA-level "owner" of this subroutine. An "owner" in this case is
118 ///     either VISAFunction or VISAKernel containing the subroutine.
119 ///     - Is LLVM IR function a "primary" one? "primary" function is the one
120 ///     that spawns vISA entity that gets compiled into a separate gen object
121 ///     - For an arbitrary LLVM IR function, get a set of "primary" functions
122 ///     that contain a compiled vISA corresponding to the function in question
123 ///     compiled into their gen objects.
124 ///
125 /// - *ProgramInfo*
126 ///   A transient object that groups several llvm Functions that are eventually
127 ///   get compiled into a single gen entity. A separate elf file with the
128 ///   debug information is generated for each gen entity.
129 ///   The grouping is with a help of *ModuleToVisaTransformInfo* object.
130 ///
131 /// - *GenObjectWrapper*
132 ///  Wrapper over the data produced by the finalizer after a kernel gets
133 ///  compiled. Simplifies/Provides access to the following:
134 ///     + gen binary (gen machine instructions)
135 ///     + decoded *gen* debug info and raw gen debug info blob
136 ///     + FINALIZER_INFO structure
137 ///
138 /// - *CompiledVisaWrapper*
139 ///  For an arbitrary pair of llvm IR Function and VISAKernel objects,
140 ///  does the following:
141 ///     + Validates that IR Function and VISAKernel object are related (that is
142 ///       the vISA spawned by IR Function is owned by the VISAKernel.
143 ///     + Provides services to access *gen* debug info from an appropriate
144 ///     compiled object (*gen* debug info concept).
145 ///
146 /// *GenXFunction*
147 ///  An object that loosely resembles MachineFunction from the LLVM Machine IR.
148 ///  This is an object that for a given LLVM IR Function provides access to:
149 ///     - LLVM IR Function
150 ///     - VisaMapping
151 ///     - Subtarget
152 ///     - data from CompiledVisaWrapper/GenObjectWrapper
153 ///     - GenXVisaRegAlloc
154 ///  GenXFunctoin serves as a primary method to communicate with the DebugInfo
155 ///  library. The data these objects hold allow us to reason about the debug
156 ///  information for any Gen construct (instruction, variable, etc).
157 ///
158 /// Examples
159 /// ^^^^^^^^
160 ///
161 /// Examples below use the following naming conventions:
162 ///     K* - kernel function
163 ///     L* - subroutine (non-inlined function)
164 ///     S* - simple stack call
165 ///     I* - indirectly-called function
166 ///
167 /// FunctionGroup construction peculiarities.
168 ///
169 ///   When function groups are constructed, we do some peculiar transformations.
170 ///
171 ///    Case_1 (FG):
172 ///         Source Code: { K1 calls L1, K2 calls L1 }
173 ///         IR after function groups: { G1 = {K1, L1}, G2 = { K2, L1'} },
174 ///             where L1' is a clone of L1.
175 ///    Case_2 (FG):
176 ///         Source Code: { K1 calls S_1, both call L1 }.
177 ///         IR after function groups: { G1 = {K1, L1, S1, L1' } }.
178 ///    Case_3 (FG):
179 ///         Source Code: { K1 calls I1 and I2 }.
180 ///         IR after function grups { G1 = {K1}, G2 = {I1}, G3={I2} }.
181 ///
182 /// VISA/genISA  construction peculiarities.
183 ///
184 ///   Case 1:
185 ///     Source code: K1, K2.
186 ///     Compilation phase:
187 ///         two function groups are created, K1 and K2 are heads.
188 ///         two different VISAKernel produced.
189 ///     DebugInfoGeneration:
190 ///         Decoded Debug info for each VISAKernel contains:
191 ///           one compiled object description.
192 ///           two "*.elf" files are created.
193 ///
194 ///   Case 2:
195 ///     Source code: K1, S1. K1 calls S1.
196 ///     Compilation phase:
197 ///         1 function group is created, K1 is the head.
198 ///         1 VISAKernel and 1 VISAFunction are created.
199 ///     DebugInfoGeneratation:
200 ///         Decoded debug info contains *2* compiled objects.
201 ///         Each object has separate vISA indexes - visa instructions are
202 ///         counted separately. Still, both are compiled into the same gen
203 ///         object, so only one "*.elf" file is emitted.
204 ///
205 ///   Case 3:
206 ///     Source code: K1, I1. K1 calls I1
207 ///     Compilation phase:
208 ///         1 function group is created, K1 is the head.
209 ///         Somehow 2 VISAKernels are created.
210 ///     DebugInfoGeneratation:
211 ///         Decoded debug info contains *1* compiled objects (but we have 2
212 ///         VISAKernel).
213 ///         In the end, we emit two "*.elf" files.
214 ///
215 //===----------------------------------------------------------------------===//
216 
217 #define DEBUG_TYPE "GENX_DEBUG_INFO"
218 
219 using namespace llvm;
220 
221 static cl::opt<bool>
222     DbgOpt_ValidationEnable("vc-dbginfo-enable-validation",
223                             cl::init(false), cl::Hidden,
224                             cl::desc("same as IGC_DebugInfoValidation"));
225 static cl::opt<bool>
226     DbgOpt_ZeBinCompatible("vc-experimental-dbg-info-zebin-compatible",
227                            cl::init(false), cl::Hidden,
228                            cl::desc("same as IGC_ZeBinCompatibleDebugging"));
229 
230 static cl::opt<std::string> DbgOpt_VisaTransformInfoPath(
231     "vc-dump-module-to-visa-transform-info-path", cl::init(""), cl::Hidden,
232     cl::desc("filename into which MVTI is dumped"));
233 
234 template <typename ContainerT>
235 using EmplaceTy = decltype(std::declval<ContainerT>().emplace());
236 
237 template <typename ContainerT>
238 using CheckedEmplace = decltype(std::declval<EmplaceTy<ContainerT>>().second);
239 
240 template <typename ContainerT>
241 using IsCheckedEmplace = std::is_same<bool, CheckedEmplace<ContainerT>>;
242 
243 template <typename ContainerT>
244 using IsNonCheckedEmplace =
245     std::is_same<EmplaceTy<ContainerT>, typename ContainerT::iterator>;
246 
247 // Naive function that checks the presence of copies.
248 // Container must be multimap-like, values must be comparable.
249 template <typename ContainerT>
hasCopy(const ContainerT & Container,typename ContainerT::iterator ToCheck)250 static bool hasCopy(const ContainerT &Container,
251                     typename ContainerT::iterator ToCheck) {
252   auto Range = Container.equal_range(ToCheck->first);
253   auto Result = std::count_if(Range.first, Range.second, [ToCheck](auto It) {
254     return It.second == ToCheck->second;
255   });
256 
257   return Result > 1;
258 }
259 
260 // checkedEmplace for multimap-like containers. It will be called if
261 // Container.emplace() returns Container::iterator. For such containers, emplace
262 // will always happen and therefore copies can be silently inserted.
263 template <typename ContainerT, class... ArgsT>
264 static std::enable_if_t<IsNonCheckedEmplace<ContainerT>::value, void>
checkedEmplace(ContainerT & Container,ArgsT &&...Args)265 checkedEmplace(ContainerT &Container, ArgsT &&... Args) {
266   auto Result = Container.emplace(std::forward<ArgsT>(Args)...);
267   IGC_ASSERT_MESSAGE(!hasCopy(Container, Result),
268                      "a copy of the existing element was emplaced");
269   (void)Result;
270 }
271 
272 // checkedEmplace for map/set-like containers. If Container.emplace() returns a
273 // pair whose second element has bool type, this version will be called.
274 template <typename ContainerT, class... ArgsT>
275 static std::enable_if_t<IsCheckedEmplace<ContainerT>::value, void>
checkedEmplace(ContainerT & Container,ArgsT &&...Args)276 checkedEmplace(ContainerT &Container, ArgsT &&... Args) {
277   auto Result = Container.emplace(std::forward<ArgsT>(Args)...);
278   IGC_ASSERT_MESSAGE(Result.second, "unexpected insertion failure");
279   (void)Result;
280 }
281 
compareFunctionNames(const Function * LF,const Function * RF)282 static bool compareFunctionNames(const Function *LF, const Function *RF) {
283   IGC_ASSERT(LF && RF);
284   return LF->getName() > RF->getName();
285 }
286 
287 template <typename ContainerT>
288 static std::vector<const Function *>
extractSortedFunctions(const ContainerT & C)289 extractSortedFunctions(const ContainerT &C) {
290   std::vector<const Function *> Result;
291   std::transform(C.begin(), C.end(), std::back_inserter(Result),
292                  [](const auto &It) { return It.first; });
293   std::sort(Result.begin(), Result.end(), compareFunctionNames);
294   return Result;
295 }
296 
297 // NOTE: the term "program" is used to avoid a potential confusion
298 // since the term "kernel" may introduce some ambiguity.
299 // Here a "program" represents a kind of wrapper over a standalone vISA
300 // object (which currently is produced by function groups and
301 // visa-external functions) that finally gets compiled into a stand-alone
302 // gen entity (binary gen kernel) with some auxiliary information
303 struct ProgramInfo {
304   struct FunctionInfo {
305     const genx::di::VisaMapping &VisaMapping;
306     const Function &F;
307   };
308 
309   const ModuleToVisaTransformInfo &MVTI;
310   VISAKernel &CompiledKernel;
311   std::vector<FunctionInfo> FIs;
312 
getEntryPointProgramInfo313   const Function &getEntryPoint() const {
314     IGC_ASSERT(!FIs.empty());
315     return FIs.front().F;
316   }
317 };
318 
319 //
320 // ModuleToVisaTransformInfo
321 // Proides information about how LLVM IR functions are mapped onto various
322 // vISA (and genISA) objects.
323 class ModuleToVisaTransformInfo {
324   using FunctionMapping =
325       std::unordered_map<const Function *, const Function *>;
326   using FunctionMultiMapping =
327       std::unordered_multimap<const Function *, const Function *>;
328   // Note: pointer to VISAKernel can represent either a true kernel or
329   // VISAFunction, depending on the context (this is vISA API limitation)
330   using FunctionToVisaMapping =
331       std::unordered_map<const Function *, VISAKernel *>;
332 
333   // Records information about a subroutine and its "owner". The "owner" of
334   // a subroutine is LLVM IR function that spawned *VISAFunction* that contains
335   // vISA for the subroutine
336   FunctionMapping SubroutineOwnersInfo;
337   // "VisaSpanwer" is LLVM IR function that produce *VISAFunction*.
338   // Different "VISAFunctions" have their own vISA instructions enumerated
339   // separately, but they still can be compiled into a single gen object.
340   // does not allow to distiguish those easily).
341   FunctionToVisaMapping VisaSpawnerInfo;
342   // A separate gen object is usually produced by KernelFunctions -
343   // the relationsip between VisaFunction and KernelFunctions is
344   // captured by the FunctionOnwers
345   FunctionMultiMapping FunctionOwnersInfo;
346   // "Kernel functions" are functions that produce genISA object
347   // Usually these are FuntionGroup heads, but indirectly-called functions
348   // also spawn there own genISA object files
349   FunctionToVisaMapping KernelFunctionsInfo;
350   std::unordered_set<const Function *> SourceLevelKernels;
351 
352   void extractSubroutineInfo(const Function &F, VISABuilder &VB,
353                              const FunctionGroupAnalysis &FGA);
354   void extractVisaFunctionsEmitters(VISABuilder &VB,
355                                     const FunctionGroupAnalysis &FGA,
356                                     const CallGraph &CG);
357 
358   void extractKernelFunctions(VISABuilder &VB,
359                               const FunctionGroupAnalysis &FGA);
360   void propagatePrimaryEmitter(const CallGraphNode &CGNode,
361                                const Function &PrimaryEmitter);
362 
363 public:
364   void print(raw_ostream &OS) const;
365   void dump() const;
366 
isSourceLevelKernel(const Function * F) const367   bool isSourceLevelKernel(const Function *F) const {
368     return SourceLevelKernels.find(F) != SourceLevelKernels.end();
369   }
isKernelFunction(const Function * F) const370   bool isKernelFunction(const Function *F) const {
371     return KernelFunctionsInfo.find(F) != KernelFunctionsInfo.end();
372   }
isSubroutine(const Function * F) const373   bool isSubroutine(const Function *F) const {
374     return SubroutineOwnersInfo.find(F) != SubroutineOwnersInfo.end();
375   }
isVisaFunctionSpawner(const Function * F) const376   bool isVisaFunctionSpawner(const Function *F) const {
377     return VisaSpawnerInfo.find(F) != VisaSpawnerInfo.end();
378   }
379   // Currently unused
380   // For a provided function returns visa object spawned by this function
381   // visa object can represent either VISAKernel or VISAFunction
getSpawnedVISAFunction(const Function * F) const382   VISAKernel *getSpawnedVISAFunction(const Function *F) const {
383     IGC_ASSERT(!isSubroutine(F));
384     auto SpawnedInfoIt = VisaSpawnerInfo.find(F);
385     IGC_ASSERT(SpawnedInfoIt != VisaSpawnerInfo.end());
386     return SpawnedInfoIt->second;
387   }
388   // Return a VISA object representing true *VISAKernel* that was spawned by a
389   // "kernel" function: IR kernel or indirectly called function.
getSpawnedVISAKernel(const Function * F) const390   VISAKernel *getSpawnedVISAKernel(const Function *F) const {
391     IGC_ASSERT_MESSAGE(isKernelFunction(F),
392                        "kernel or indirectly called function is expected");
393     return KernelFunctionsInfo.at(F);
394   }
395   // return an "owner" (on vISA level) of the function representing a
396   // subroutine
getSubroutineOwner(const Function * F) const397   const Function *getSubroutineOwner(const Function *F) const {
398     IGC_ASSERT(isSubroutine(F));
399     auto SubInfoIt = SubroutineOwnersInfo.find(F);
400     IGC_ASSERT(SubInfoIt != SubroutineOwnersInfo.end());
401     return SubInfoIt->second;
402   }
403   // PrimaryEmitter is the function spawning gen object, that
404   // contains the vISA object emitted by the specified function
405   std::unordered_set<const Function *>
406   getPrimaryEmittersForVisa(const Function *F, bool Strict = true) const;
407 
getPrimaryFunctions() const408   std::vector<const Function *> getPrimaryFunctions() const {
409     return extractSortedFunctions(KernelFunctionsInfo);
410   }
411 
412   std::vector<const Function *>
413     getSecondaryFunctions(const Function *PrimaryFunction) const;
414 
415   ModuleToVisaTransformInfo(VISABuilder &VB, const FunctionGroupAnalysis &FGA,
416                             const CallGraph &CG);
417 };
418 
419 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const420 void ModuleToVisaTransformInfo::dump() const {
421   print(errs());
422   errs() << "\n";
423 }
424 #endif
425 
print(raw_ostream & OS) const426 void ModuleToVisaTransformInfo::print(raw_ostream &OS) const {
427 
428   auto KernelFunctions = extractSortedFunctions(KernelFunctionsInfo);
429   auto Subroutines = extractSortedFunctions(SubroutineOwnersInfo);
430   auto VisaProducers = extractSortedFunctions(VisaSpawnerInfo);
431 
432   // filter-out kernel functions
433   VisaProducers.erase(
434       std::remove_if(VisaProducers.begin(), VisaProducers.end(),
435                      [this](const auto *F) { return isKernelFunction(F); }),
436       VisaProducers.end());
437 
438   auto PrintFunctionSubroutines = [this, &OS, &Subroutines](const Function *F,
439                                                             StringRef Prefix) {
440     unsigned Counter = 0;
441     for (const auto *LF : Subroutines) {
442       if (getSubroutineOwner(LF) != F)
443         continue;
444       OS << Prefix << "l." << Counter << " " << LF->getName() << "\n";
445       ++Counter;
446     }
447   };
448 
449   for (size_t i = 0, NumKF = KernelFunctions.size(); i < NumKF; ++i) {
450     const auto *KF = KernelFunctions[i];
451     OS << "[" << i << "] " << KF->getName() << " "
452        << (SourceLevelKernels.count(KF) != 0 ? "(K)" : "(I)") << "\n";
453 
454     PrintFunctionSubroutines(KF, "    ");
455 
456     unsigned SubIdx = 0;
457     for (const auto *VF : VisaProducers) {
458       if (!getPrimaryEmittersForVisa(VF).count(KF))
459         continue;
460       OS << "    v." << SubIdx << " " << VF->getName() << "\n";
461       PrintFunctionSubroutines(VF, "        ");
462       ++SubIdx;
463     }
464   }
465 }
getSecondaryFunctions(const Function * PrimaryFunction) const466 std::vector<const Function *> ModuleToVisaTransformInfo::getSecondaryFunctions(
467     const Function *PrimaryFunction) const {
468   auto IsSecondaryFunction = [PrimaryFunction, this](const Function *F) {
469     if (F == PrimaryFunction)
470       return false;
471     return getPrimaryEmittersForVisa(F).count(PrimaryFunction) > 0;
472   };
473   IGC_ASSERT(isKernelFunction(PrimaryFunction));
474   std::vector<const Function *> Result;
475   for (const auto &[F, VF] : SubroutineOwnersInfo) {
476     (void)VF;
477     if (IsSecondaryFunction(F))
478       Result.push_back(F);
479   }
480   for (const auto &[F, VF] : VisaSpawnerInfo) {
481     (void)VF;
482     if (IsSecondaryFunction(F))
483       Result.push_back(F);
484   }
485   std::sort(Result.begin(), Result.end(), compareFunctionNames);
486   return Result;
487 }
488 
extractSubroutineInfo(const Function & F,VISABuilder & VB,const FunctionGroupAnalysis & FGA)489 void ModuleToVisaTransformInfo::extractSubroutineInfo(
490     const Function &F, VISABuilder &VB, const FunctionGroupAnalysis &FGA) {
491   IGC_ASSERT(isVisaFunctionSpawner(&F));
492   const auto *Gr = FGA.getAnyGroup(&F);
493   IGC_ASSERT(Gr);
494   for (const Function *SF : *Gr) {
495     if (isKernelFunction(SF))
496       continue;
497     if (genx::requiresStackCall(SF))
498       continue;
499     checkedEmplace(SubroutineOwnersInfo, SF, &F);
500   }
501 }
502 
503 std::unordered_set<const Function *>
getPrimaryEmittersForVisa(const Function * F,bool Strict) const504 ModuleToVisaTransformInfo::getPrimaryEmittersForVisa(const Function *F,
505                                                      bool Strict) const {
506   if (isSubroutine(F)) {
507     auto SubrInfoIt = SubroutineOwnersInfo.find(F);
508     IGC_ASSERT(SubrInfoIt != SubroutineOwnersInfo.end());
509     const Function *SubrOwner = SubrInfoIt->second;
510     IGC_ASSERT(SubrOwner);
511     IGC_ASSERT(!isSubroutine(SubrOwner));
512     return getPrimaryEmittersForVisa(SubrOwner);
513   }
514   auto InfoRange = FunctionOwnersInfo.equal_range(F);
515   std::unordered_set<const Function *> PrimaryEmitters;
516   std::transform(InfoRange.first, InfoRange.second,
517                  std::inserter(PrimaryEmitters, PrimaryEmitters.end()),
518                  [](auto It) { return It.second; });
519 
520   if (Strict) {
521     IGC_ASSERT_MESSAGE(!PrimaryEmitters.empty(),
522                        "could not get primary emitter");
523   }
524   return PrimaryEmitters;
525 }
526 
propagatePrimaryEmitter(const CallGraphNode & CGNode,const Function & PrimaryEmitter)527 void ModuleToVisaTransformInfo::propagatePrimaryEmitter(
528     const CallGraphNode &CGNode, const Function &PrimaryEmitter) {
529   const Function *F = CGNode.getFunction();
530   if (!F)
531     return;
532   if (genx::requiresStackCall(F) && !genx::isReferencedIndirectly(F)) {
533     auto Range = FunctionOwnersInfo.equal_range(F);
534     auto Res =
535         std::find_if(Range.first, Range.second, [&PrimaryEmitter](auto Info) {
536           return Info.second == &PrimaryEmitter;
537         });
538     // F -> PrimaryEmitter was already inserted. It happens if a recursion
539     // exists.
540     if (Res != Range.second)
541       return;
542     LLVM_DEBUG(dbgs() << "setting <" << PrimaryEmitter.getName()
543                       << "> as a host of the stack-callee <" << F->getName()
544                       << ">\n");
545     checkedEmplace(FunctionOwnersInfo, F, &PrimaryEmitter);
546   }
547 
548   for (const auto &CalleeCGNode : CGNode)
549     propagatePrimaryEmitter(*CalleeCGNode.second, PrimaryEmitter);
550 }
551 
extractVisaFunctionsEmitters(VISABuilder & VB,const FunctionGroupAnalysis & FGA,const CallGraph & CG)552 void ModuleToVisaTransformInfo::extractVisaFunctionsEmitters(
553     VISABuilder &VB, const FunctionGroupAnalysis &FGA, const CallGraph &CG) {
554 
555   // We've already collected kernels and indirect functions into
556   // `KernelFunctionsInfo`.
557   for (const auto &[F, VF] : KernelFunctionsInfo) {
558     (void)VF;
559     const auto *KFNode = CG[F];
560     IGC_ASSERT(KFNode);
561     propagatePrimaryEmitter(*KFNode, *F);
562   }
563   // Collect owned functions as a set of unique keys of FunctionOwnersInfo.
564   std::unordered_set<const Function *> OwnedFunctions;
565   std::transform(FunctionOwnersInfo.begin(), FunctionOwnersInfo.end(),
566                  std::inserter(OwnedFunctions, OwnedFunctions.begin()),
567                  [](auto Info) { return Info.first; });
568 
569   for (const Function *F : OwnedFunctions) {
570     // Skip "KernelFunctions" because they have already been processed.
571     if (genx::isReferencedIndirectly(F) || genx::isKernel(F))
572       continue;
573     VISAKernel *VF = VB.GetVISAKernel(F->getName().str());
574     checkedEmplace(VisaSpawnerInfo, F, VF);
575     extractSubroutineInfo(*F, VB, FGA);
576   }
577 }
578 
extractKernelFunctions(VISABuilder & VB,const FunctionGroupAnalysis & FGA)579 void ModuleToVisaTransformInfo::extractKernelFunctions(
580     VISABuilder &VB, const FunctionGroupAnalysis &FGA) {
581   for (const auto *FG : FGA.AllGroups()) {
582     for (const Function *F : *FG) {
583       if (!genx::isReferencedIndirectly(F) && !genx::isKernel(F))
584         continue;
585       VISAKernel *VF = VB.GetVISAKernel(F->getName().str());
586       if (genx::isKernel(F))
587         checkedEmplace(SourceLevelKernels, F);
588       checkedEmplace(KernelFunctionsInfo, F, VF);
589       checkedEmplace(VisaSpawnerInfo, F, VF);
590       checkedEmplace(FunctionOwnersInfo, F, F);
591 
592       extractSubroutineInfo(*F, VB, FGA);
593     }
594   }
595 }
596 
ModuleToVisaTransformInfo(VISABuilder & VB,const FunctionGroupAnalysis & FGA,const CallGraph & CG)597 ModuleToVisaTransformInfo::ModuleToVisaTransformInfo(
598     VISABuilder &VB, const FunctionGroupAnalysis &FGA, const CallGraph &CG) {
599   extractKernelFunctions(VB, FGA);
600   extractVisaFunctionsEmitters(VB, FGA, CG);
601 
602   for (const auto *FG : FGA.AllGroups()) {
603     for (const Function *F : *FG) {
604       if (isSourceLevelKernel(F))
605         IGC_ASSERT(isKernelFunction(F) && isVisaFunctionSpawner(F) &&
606                    !isSubroutine(F));
607       if (isKernelFunction(F))
608         IGC_ASSERT(isVisaFunctionSpawner(F) && !isSubroutine(F));
609       if (isVisaFunctionSpawner(F))
610         IGC_ASSERT(!isSubroutine(F));
611       if (isSubroutine(F))
612         IGC_ASSERT(!isVisaFunctionSpawner(F) && !isKernelFunction(F));
613     }
614   }
615 }
616 
617 namespace {
618 
619 class GenObjectWrapper {
620   FINALIZER_INFO *JitInfo = nullptr;
621   std::unique_ptr<IGC::DbgDecoder> DecodedDebugInfo;
622   // TODO: remove this once DbgDecoder is refactored
623   unsigned GenDbgInfoDataSize = 0;
624   void *GenDbgInfoDataPtr = nullptr;
625 
626   int GenBinaryDataSize = 0;
627   void *GenBinaryDataPtr = nullptr;
628 
629   const Function &EntryPoint;
630 
631   std::string ErrMsg;
632 
setError(const Twine & Msg)633   void setError(const Twine &Msg) {
634     ErrMsg.append((Msg + "<" + EntryPoint.getName().str() + ">").str());
635 
636     LLVM_DEBUG(dbgs() << "GOW creation for <" << EntryPoint.getName()
637                       << "> aborted: " << Msg.str());
638   }
639 
640 public:
getEntryPoint() const641   const Function &getEntryPoint() const { return EntryPoint; }
642 
getGenDebug() const643   ArrayRef<char> getGenDebug() const {
644     IGC_ASSERT(GenDbgInfoDataPtr);
645     return ArrayRef<char>(static_cast<char *>(GenDbgInfoDataPtr),
646                           GenDbgInfoDataSize);
647   }
648 
getGenBinary() const649   ArrayRef<char> getGenBinary() const {
650     IGC_ASSERT(GenBinaryDataPtr);
651     return ArrayRef<char>(static_cast<char *>(GenBinaryDataPtr),
652                           GenBinaryDataSize);
653   }
654 
getDecodedGenDbg() const655   const IGC::DbgDecoder &getDecodedGenDbg() const {
656     IGC_ASSERT(DecodedDebugInfo);
657     return *DecodedDebugInfo;
658   }
659 
getJitInfo() const660   const FINALIZER_INFO &getJitInfo() const {
661     IGC_ASSERT(!hasErrors() && JitInfo);
662     return *JitInfo;
663   };
664 
665   GenObjectWrapper(VISAKernel &VK, const Function &F);
~GenObjectWrapper()666   ~GenObjectWrapper() { releaseDebugInfoResources(); }
667 
hasErrors() const668   bool hasErrors() const { return !ErrMsg.empty(); }
669 
getError() const670   const std::string &getError() const { return ErrMsg; }
671 
releaseDebugInfoResources()672   void releaseDebugInfoResources() {
673     if (!GenDbgInfoDataPtr) {
674       IGC_ASSERT(GenDbgInfoDataSize == 0);
675       return;
676     }
677     freeBlock(GenDbgInfoDataPtr);
678     GenDbgInfoDataPtr = nullptr;
679     GenDbgInfoDataSize = 0;
680   }
681 
printDecodedGenXDebug(raw_ostream & OS)682   void printDecodedGenXDebug(raw_ostream &OS) {
683     IGC_ASSERT(!hasErrors());
684     LLVM_DEBUG(dbgs() << "GenXDebugInfo size: " << GenDbgInfoDataSize << "\n");
685     IGC::DbgDecoder(GenDbgInfoDataPtr).print(OS);
686   }
687 };
688 
GenObjectWrapper(VISAKernel & VK,const Function & F)689 GenObjectWrapper::GenObjectWrapper(VISAKernel &VK, const Function &F)
690     : EntryPoint(F) {
691   if (VK.GetJitInfo(JitInfo) != 0) {
692     setError("could not extract jitter info");
693     return;
694   }
695   IGC_ASSERT(JitInfo);
696 
697   // Extract Gen Binary (will need it for line table generation)
698   VK.GetGenxBinary(GenBinaryDataPtr, GenBinaryDataSize);
699   if (GenBinaryDataSize <= 0) {
700     setError("could not extract gen binary from finalizer");
701     return;
702   }
703 
704   if (VK.GetGenxDebugInfo(GenDbgInfoDataPtr, GenDbgInfoDataSize) != 0) {
705     setError("could not get gen debug information from finalizer");
706     return;
707   }
708   if (!GenDbgInfoDataPtr) {
709     setError("gen debug information reported by finalizer is inconsistent");
710     return;
711   }
712   DecodedDebugInfo = std::make_unique<IGC::DbgDecoder>(GenDbgInfoDataPtr);
713 };
714 
715 class CompiledVisaWrapper {
716 
717   using FinalizedDI = IGC::DbgDecoder::DbgInfoFormat;
718 
719   const GenObjectWrapper &GOW;
720   // underlying data is owned by DecodedDebugInfo, owned by GOW
721   const FinalizedDI *VisaKernelDI = nullptr;
722 
723   std::string ErrMsg;
724 
setErrorForFunction(const std::string & Err,const Function & F)725   void setErrorForFunction(const std::string &Err, const Function &F) {
726     ErrMsg.append(Err).append("<").append(F.getName().str()).append(">");
727 
728     LLVM_DEBUG(dbgs() << "CW creation for <" << F.getName()
729                       << "> aborted: " << ErrMsg);
730   }
731 
732 public:
getJitInfo() const733   const FINALIZER_INFO &getJitInfo() const { return GOW.getJitInfo(); };
734 
getFinalizerDI() const735   const FinalizedDI &getFinalizerDI() const {
736     IGC_ASSERT(ErrMsg.empty() && VisaKernelDI);
737     return *VisaKernelDI;
738   }
739 
getDIDecoder() const740   const IGC::DbgDecoder &getDIDecoder() const { return GOW.getDecodedGenDbg(); }
741 
getGenDebug() const742   ArrayRef<char> getGenDebug() const { return GOW.getGenDebug(); }
getGenBinary() const743   ArrayRef<char> getGenBinary() const { return GOW.getGenBinary(); }
744 
getError() const745   const std::string &getError() const { return ErrMsg; }
746 
hasErrors() const747   bool hasErrors() const { return !getError().empty(); }
748 
749   CompiledVisaWrapper(CompiledVisaWrapper &&Other) = default;
CompiledVisaWrapper(const Function & F,StringRef CompiledObjectName,const GenObjectWrapper & GOWIn)750   CompiledVisaWrapper(const Function &F, StringRef CompiledObjectName,
751                       const GenObjectWrapper &GOWIn)
752       : GOW(GOWIn) {
753     struct Gen2VisaIdx {
754       unsigned GenOffset;
755       unsigned VisaIdx;
756     };
757     LLVM_DEBUG(dbgs() << "creating CW for <" << F.getName() << ">, using <"
758                       << CompiledObjectName
759                       << "> as a CompiledObject moniker\n");
760     IGC_ASSERT(!GOW.hasErrors());
761 
762     const auto &CO = GOW.getDecodedGenDbg().compiledObjs;
763     auto FoundCoIt = std::find_if(
764         CO.begin(), CO.end(), [&CompiledObjectName](const auto &DI) {
765           return CompiledObjectName == StringRef(DI.kernelName);
766         });
767     VisaKernelDI = (FoundCoIt == CO.end()) ? nullptr : &*FoundCoIt;
768     if (!VisaKernelDI) {
769       setErrorForFunction("could not find debug information for", F);
770       return;
771     }
772     if (VisaKernelDI->CISAIndexMap.empty()) {
773       setErrorForFunction("empty CisaIndexMap for", F);
774       return;
775     }
776 
777     std::vector<Gen2VisaIdx> Gen2Visa;
778     std::transform(VisaKernelDI->CISAIndexMap.begin(),
779                    VisaKernelDI->CISAIndexMap.end(),
780                    std::back_inserter(Gen2Visa), [](const auto &V2G) {
781                      return Gen2VisaIdx{V2G.second, V2G.first};
782                    });
783 
784     const auto &GenBinary = GOW.getGenBinary();
785     // Make Sure that gen isa indeces are inside GenBinary
786     const bool InBounds =
787         std::all_of(Gen2Visa.begin(), Gen2Visa.end(), [&](const auto &Idx) {
788           // <= Is because last index can be equal to the binary size
789           return Idx.GenOffset <= GenBinary.size();
790         });
791     if (!InBounds) {
792       setErrorForFunction("fatal error (debug info). inconsistent gen->visa "
793                           "mapping: gen index is out of bounds",
794                           F);
795       return;
796     }
797 
798     // Make Sure that gen isa indeces are unique and sorted
799     const bool Sorted = std::is_sorted(
800         Gen2Visa.begin(), Gen2Visa.end(),
801         [](const auto &L, const auto &R) { return L.GenOffset < R.GenOffset; });
802     const bool Validated =
803         Sorted && (Gen2Visa.end() ==
804                    std::adjacent_find(Gen2Visa.begin(), Gen2Visa.end(),
805                                       [](const auto &L, const auto &R) {
806                                         return L.GenOffset == R.GenOffset;
807                                       }));
808     if (!Validated) {
809       setErrorForFunction("fatal error (debug info). inconsistent gen->visa "
810                           "mapping: gen index are not ordered properly",
811                           F);
812       return;
813     }
814   }
815 };
816 
817 class GenXFunction final : public IGC::VISAModule {
818 
819 public:
GenXFunction(const GenXSubtarget & STIn,const GenXVisaRegAlloc & RAIn,const Function & F,CompiledVisaWrapper && CW,const genx::di::VisaMapping & V2I,const ModuleToVisaTransformInfo & MVTI,bool IsPrimary)820   GenXFunction(const GenXSubtarget &STIn, const GenXVisaRegAlloc &RAIn,
821                const Function &F, CompiledVisaWrapper &&CW,
822                const genx::di::VisaMapping &V2I,
823                const ModuleToVisaTransformInfo &MVTI, bool IsPrimary)
824       : F{F}, ST{STIn}, VisaMapping{V2I}, CompiledVisa{std::move(CW)}, RA{RAIn},
825         MVTI(MVTI), VISAModule(const_cast<Function *>(&F), IsPrimary) {
826 
827     if (MVTI.isSubroutine(&F))
828        SetType(ObjectType::SUBROUTINE);
829     else if (MVTI.isKernelFunction(&F))
830        SetType(ObjectType::KERNEL);
831     else
832        SetType(ObjectType::STACKCALL_FUNC);
833   }
834 
~GenXFunction()835   ~GenXFunction() {
836     LLVM_DEBUG(dbgs() << "~GenXFunction() called for " << F.getName() << "\n");
837   }
838 
839   const IGC::DbgDecoder::DbgInfoFormat*
getCompileUnit(const IGC::DbgDecoder & VD) const840       getCompileUnit(const IGC::DbgDecoder& VD) const override {
841 
842     StringRef CompiledObjectName;
843     if (MVTI.isSubroutine(&F)) {
844       IGC_ASSERT(GetType() == ObjectType::SUBROUTINE);
845       CompiledObjectName = MVTI.getSubroutineOwner(&F)->getName();
846     } else {
847       CompiledObjectName = F.getName();
848     }
849 
850     auto FoundIt = std::find_if(VD.compiledObjs.begin(), VD.compiledObjs.end(),
851                                 [&CompiledObjectName](const auto &CO) {
852                                   return (CO.kernelName == CompiledObjectName);
853                                 });
854     if (FoundIt == VD.compiledObjs.end())
855       return nullptr;
856 
857     return &*FoundIt;
858   }
859 
getUnpaddedProgramSize() const860   unsigned int getUnpaddedProgramSize() const override {
861     return CompiledVisa.getGenBinary().size();
862   }
isLineTableOnly() const863   bool isLineTableOnly() const override {
864     IGC_ASSERT_MESSAGE(0, "isLineTableOnly()");
865     return false;
866   }
getPrivateBaseReg() const867   unsigned getPrivateBaseReg() const override {
868     IGC_ASSERT_MESSAGE(0, "getPrivateBaseReg() - not implemented");
869     return 0;
870   }
getGRFSizeInBytes() const871   unsigned getGRFSizeInBytes() const override {
872     return ST.getGRFByteSize();
873   }
getNumGRFs() const874   unsigned getNumGRFs() const override {
875     return CompiledVisa.getJitInfo().numGRFTotal;
876   }
getPointerSize() const877   unsigned getPointerSize() const override {
878     return F.getParent()->getDataLayout().getPointerSize();
879   }
getTypeSizeInBits(Type * Ty) const880   uint64_t getTypeSizeInBits(Type* Ty) const override {
881     return F.getParent()->getDataLayout().getTypeSizeInBits(Ty);
882   }
getGenDebug() const883   ArrayRef<char> getGenDebug() const override {
884     return CompiledVisa.getGenDebug();
885   }
getGenBinary() const886   ArrayRef<char> getGenBinary() const override {
887     return CompiledVisa.getGenBinary();
888   }
getDIDecoder() const889   const IGC::DbgDecoder &getDIDecoder() const {
890     return CompiledVisa.getDIDecoder();
891   }
getFinalizerDI() const892   const IGC::DbgDecoder::DbgInfoFormat &getFinalizerDI() const {
893     return CompiledVisa.getFinalizerDI();
894   }
895 
getVisaMapping() const896   const genx::di::VisaMapping &getVisaMapping() const { return VisaMapping; }
897 
898   std::vector<IGC::VISAVariableLocation>
GetVariableLocation(const Instruction * DbgInst) const899   GetVariableLocation(const Instruction *DbgInst) const override {
900 
901     using Location = IGC::VISAVariableLocation;
902     auto EmptyLoc = [this](StringRef Reason) {
903       LLVM_DEBUG(dbgs() << "  Empty Location Returned (" << Reason
904                         << ")\n <<<\n");
905       std::vector<Location> Res;
906       Res.emplace_back(this);
907       return Res;
908     };
909     auto ConstantLoc = [this](const Constant *C) {
910       LLVM_DEBUG(dbgs() << "  ConstantLoc\n <<<\n");
911       std::vector<Location> Res;
912       Res.emplace_back(C, this);
913       return Res;
914     };
915 
916     IGC_ASSERT(isa<DbgInfoIntrinsic>(DbgInst));
917 
918     LLVM_DEBUG(dbgs() << " >>>\n  GetVariableLocation for " << *DbgInst << "\n");
919     const Value *DbgValue = nullptr;
920     const DIVariable *VarDescr = nullptr;
921     if (const auto *pDbgAddrInst = dyn_cast<DbgDeclareInst>(DbgInst)) {
922       DbgValue = pDbgAddrInst->getAddress();
923       VarDescr = pDbgAddrInst->getVariable();
924     } else if (const auto *pDbgValInst = dyn_cast<DbgValueInst>(DbgInst)) {
925       DbgValue = pDbgValInst->getValue();
926       VarDescr = pDbgValInst->getVariable();
927     } else {
928       return EmptyLoc("unsupported Debug Intrinsic");
929     }
930 
931     IGC_ASSERT(VarDescr);
932     if (!DbgValue) {
933       if (const auto *LocalVar = dyn_cast<DILocalVariable>(VarDescr))
934         if (LocalVar->isParameter())
935           return EmptyLoc("unsupported parameter description");
936       return EmptyLoc("unsupported DbgInst");
937     }
938     IGC_ASSERT(DbgValue);
939     LLVM_DEBUG(dbgs() << "   Value:" << *DbgValue << "\n");
940     LLVM_DEBUG(dbgs() << "   Var: " << VarDescr->getName()
941                       << "/Type:" << *VarDescr->getType() << "\n");
942     if (isa<UndefValue>(DbgValue)) {
943       return EmptyLoc("UndefValue");
944     }
945     if (auto *ConstVal = dyn_cast<Constant>(DbgValue)) {
946       return ConstantLoc(ConstVal);
947     }
948     auto *Reg = RA.getRegForValueUntyped(&F, const_cast<Value *>(DbgValue));
949     if (!Reg) {
950       return EmptyLoc("could not find virtual register");
951     }
952     const bool IsRegister = true;
953     const bool IsMemory = false;
954     const bool IsGlobalASI = false;
955     auto *VTy = dyn_cast<IGCLLVM::FixedVectorType>(DbgValue->getType());
956     unsigned NumElements = VTy ? VTy->getNumElements() : 1;
957     const bool IsVectorized = false;
958 
959     std::vector<Location> Res;
960     // Source/IGC/DebugInfo/VISAModule.hpp:128
961     Res.emplace_back(GENERAL_REGISTER_BEGIN + Reg->Num, IsRegister,
962                      IsMemory, NumElements, IsVectorized, IsGlobalASI, this);
963     return Res;
964   }
965 
UpdateVisaId()966   void UpdateVisaId() override {
967     // do nothing (the moment we need to advance index is controlled explicitly)
968   }
ValidateVisaId()969   void ValidateVisaId() override {
970     // do nothing (we don't need validation since VISA is built already)
971   }
GetSIMDSize() const972   uint16_t GetSIMDSize() const override { return 1; }
973 
getPrivateBase() const974   void* getPrivateBase() const override { return nullptr; };
setPrivateBase(void *)975   void setPrivateBase(void*) override {};
976 
hasPTO() const977   bool hasPTO() const override { return false; }
getPTOReg() const978   int getPTOReg() const override { return -1; }
getFPReg() const979   int getFPReg() const override { return -1; }
getFPOffset() const980   uint64_t getFPOffset() const override { return 16; }
981 
982 private:
983   const Function &F;
984   const GenXSubtarget &ST;
985   const genx::di::VisaMapping &VisaMapping;
986   CompiledVisaWrapper CompiledVisa;
987   const GenXVisaRegAlloc &RA;
988   const ModuleToVisaTransformInfo &MVTI;
989 };
990 
processGenXFunction(IGC::IDebugEmitter & Emitter,GenXFunction & GF)991 static void processGenXFunction(IGC::IDebugEmitter &Emitter, GenXFunction &GF) {
992   Emitter.setCurrentVISA(&GF);
993   const auto &V2I = GF.getVisaMapping().V2I;
994   const auto &FDI = GF.getFinalizerDI();
995   for (auto MappingIt = V2I.cbegin(); MappingIt != V2I.cend(); ++MappingIt) {
996 
997     // "NextIndex" is an index in vISA stream which points to an end
998     // of instructions sequence generated by a particular llvm instruction
999     // For istructions which do not produce any visa instructions
1000     // (like llvm.dbg.*) "NextIndex" should point to the "CurrentIndex"
1001     auto FindNextIndex = [&FDI, &V2I](decltype(MappingIt) ItCur) {
1002       auto *Inst = ItCur->Inst;
1003       if (isa<DbgInfoIntrinsic>(Inst)) {
1004         return ItCur->VisaIdx;
1005       }
1006       auto NextIt = std::next(ItCur);
1007       if (NextIt == V2I.end()) {
1008         IGC_ASSERT(!FDI.CISAIndexMap.empty());
1009         return FDI.CISAIndexMap.back().first;
1010       }
1011       return NextIt->VisaIdx;
1012     };
1013     auto VisaIndexCurr = MappingIt->VisaIdx;
1014     auto VisaIndexNext = FindNextIndex(MappingIt);
1015 
1016     // Note: "index - 1" is because we mimic index values as if they were
1017     // before corresponding instructions were inserted
1018     GF.SetVISAId(VisaIndexCurr - 1);
1019     // we need this const_cast because of the flawed VISA Emitter API
1020     auto *Inst = const_cast<Instruction *>(MappingIt->Inst);
1021     Emitter.BeginInstruction(Inst);
1022     GF.SetVISAId(VisaIndexNext - 1);
1023     Emitter.EndInstruction(Inst);
1024 
1025     LLVM_DEBUG(dbgs() << "  VisaMapping: [" << VisaIndexCurr << ";"
1026                       << VisaIndexNext << "):" << *Inst << "\n");
1027   }
1028 }
1029 
1030 using GenXObjectHolder = std::unique_ptr<GenXFunction>;
buildGenXFunctionObject(const ModuleToVisaTransformInfo & MVTI,const GenObjectWrapper & GOW,const ProgramInfo::FunctionInfo & FI,const GenXSubtarget & ST,const GenXVisaRegAlloc & RA)1031 GenXObjectHolder buildGenXFunctionObject(const ModuleToVisaTransformInfo &MVTI,
1032                                          const GenObjectWrapper &GOW,
1033                                          const ProgramInfo::FunctionInfo &FI,
1034                                          const GenXSubtarget &ST,
1035                                          const GenXVisaRegAlloc &RA) {
1036   StringRef CompiledObjectName = FI.F.getName();
1037   if (MVTI.isSubroutine(&FI.F))
1038     CompiledObjectName = MVTI.getSubroutineOwner(&FI.F)->getName();
1039 
1040   CompiledVisaWrapper CW(FI.F, CompiledObjectName, GOW);
1041   if (CW.hasErrors())
1042     vc::diagnose(FI.F.getContext(), "GenXDebugInfo", CW.getError());
1043 
1044   bool IsPrimaryFunction = &GOW.getEntryPoint() == &FI.F;
1045   return std::make_unique<GenXFunction>(
1046       ST, RA, FI.F, std::move(CW), FI.VisaMapping, MVTI, IsPrimaryFunction);
1047 }
1048 
1049 using GenXObjectHolderList = std::vector<GenXObjectHolder>;
translateProgramInfoToGenXFunctionObjects(const GenObjectWrapper & GOW,const ProgramInfo & PI,const GenXSubtarget & ST,const GenXVisaRegAlloc & RA)1050 GenXObjectHolderList translateProgramInfoToGenXFunctionObjects(
1051     const GenObjectWrapper &GOW, const ProgramInfo &PI, const GenXSubtarget &ST,
1052     const GenXVisaRegAlloc &RA) {
1053   const auto &MVTI = PI.MVTI;
1054   GenXObjectHolderList GenXFunctionHolders;
1055   std::transform(PI.FIs.begin(), PI.FIs.end(),
1056                  std::back_inserter(GenXFunctionHolders),
1057                  [&ST, &RA, &MVTI, &GOW](const auto &FI) {
1058                    return buildGenXFunctionObject(MVTI, GOW, FI, ST, RA);
1059                  });
1060   return GenXFunctionHolders;
1061 }
1062 
1063 using GenXFunctionPtrList = std::vector<GenXFunction *>;
initializeDebugEmitter(IGC::IDebugEmitter & Emitter,const IGC::DebugEmitterOpts & DebugOpts,const ProgramInfo & PI,GenXObjectHolderList && GFsHolderIn)1064 GenXFunctionPtrList initializeDebugEmitter(
1065     IGC::IDebugEmitter &Emitter, const IGC::DebugEmitterOpts &DebugOpts,
1066     const ProgramInfo &PI, GenXObjectHolderList &&GFsHolderIn) {
1067 
1068   GenXFunctionPtrList GFPointers;
1069   for (auto &&GF : GFsHolderIn) {
1070     GFPointers.push_back(GF.get());
1071 
1072     if (GF->isPrimaryFunc()) {
1073       Emitter.Initialize(std::move(GF), DebugOpts);
1074     } else {
1075       Emitter.registerVISA(GFPointers.back());
1076       Emitter.resetModule(std::move(GF));
1077     }
1078   }
1079   // Currently Debug Info Emitter expects that GenXFunctions are
1080   // processed in the same order as they appear in the visa object
1081   // (in terms of genisa instructions order)
1082   std::sort(GFPointers.begin(), GFPointers.end(), [](auto *LGF, auto *RGF) {
1083     const auto &LDI = LGF->getFinalizerDI();
1084     const auto &RDI = RGF->getFinalizerDI();
1085     return LDI.relocOffset < RDI.relocOffset;
1086   });
1087   return GFPointers;
1088 }
1089 
1090 } // namespace
1091 
1092 namespace llvm {
1093 
dumpDebugInfo(const GenXBackendConfig & BC,const StringRef KernelName,const ArrayRef<char> ElfBin,const ArrayRef<char> GenDbgBlob,const ArrayRef<char> ErrLog)1094 static void dumpDebugInfo(const GenXBackendConfig &BC,
1095                           const StringRef KernelName,
1096                           const ArrayRef<char> ElfBin,
1097                           const ArrayRef<char> GenDbgBlob,
1098                           const ArrayRef<char> ErrLog) {
1099   std::string Prefix = "dbginfo_";
1100   if (!BC.dbgInfoDumpsNameOverride().empty())
1101     Prefix.append(BC.dbgInfoDumpsNameOverride()).append("_");
1102 
1103   vc::produceAuxiliaryShaderDumpFile(BC, Prefix + KernelName + "_dwarf.elf",
1104                                      ElfBin);
1105   vc::produceAuxiliaryShaderDumpFile(BC, Prefix + KernelName + "_gen.dump",
1106                                      GenDbgBlob);
1107   if (!ErrLog.empty())
1108     vc::produceAuxiliaryShaderDumpFile(BC, Prefix + KernelName + ".dbgerr",
1109                                        ErrLog);
1110 }
1111 
processKernel(const IGC::DebugEmitterOpts & DebugOpts,const ProgramInfo & PI)1112 void GenXDebugInfo::processKernel(const IGC::DebugEmitterOpts &DebugOpts,
1113                                   const ProgramInfo &PI) {
1114 
1115   IGC_ASSERT_MESSAGE(!PI.FIs.empty(),
1116                      "Program must include at least one function");
1117   IGC_ASSERT_MESSAGE(PI.MVTI.getPrimaryEmittersForVisa(&PI.getEntryPoint())
1118                              .count(&PI.getEntryPoint()) == 1,
1119                      "The head of ProgramInfo is expected to be a kernel");
1120 
1121   GenObjectWrapper GOW(PI.CompiledKernel, PI.getEntryPoint());
1122   if (GOW.hasErrors())
1123     vc::diagnose(GOW.getEntryPoint().getContext(), "GenXDebugInfo",
1124                  GOW.getError());
1125 
1126   LLVM_DEBUG(GOW.printDecodedGenXDebug(dbgs()));
1127 
1128   auto Deleter = [](IGC::IDebugEmitter *Emitter) {
1129     IGC::IDebugEmitter::Release(Emitter);
1130   };
1131   using EmitterHolder = std::unique_ptr<IGC::IDebugEmitter, decltype(Deleter)>;
1132   EmitterHolder Emitter(IGC::IDebugEmitter::Create(), Deleter);
1133 
1134   const auto &ST = getAnalysis<TargetPassConfig>()
1135       .getTM<GenXTargetMachine>()
1136       .getGenXSubtarget();
1137   auto *FGA = &getAnalysis<FunctionGroupAnalysis>();
1138   FunctionGroup *currentFG = FGA->getAnyGroup(&PI.FIs.front().F);
1139   auto &RA = (getAnalysis<GenXVisaRegAllocWrapper>().getFGPassImpl(currentFG));
1140 
1141   GenXFunctionPtrList GFPointers = initializeDebugEmitter(
1142       *Emitter, DebugOpts, PI,
1143       translateProgramInfoToGenXFunctionObjects(GOW, PI, ST, RA));
1144 
1145   auto &KF = GOW.getEntryPoint();
1146   IGC_ASSERT(ElfOutputs.count(&KF) == 0);
1147   auto &ElfBin = ElfOutputs[&KF];
1148 
1149   for (auto *GF : GFPointers) {
1150     LLVM_DEBUG(dbgs() << "--- Processing GenXFunction:  "
1151                       << GF->getFunction()->getName().str() << " ---\n");
1152     processGenXFunction(*Emitter, *GF);
1153     bool ExpectMore = GF != GFPointers.back();
1154     LLVM_DEBUG(dbgs() << "--- Starting Debug Info Finalization (final:  "
1155                       << !ExpectMore << ") ---\n");
1156     auto Out = Emitter->Finalize(!ExpectMore, &GF->getDIDecoder());
1157     if (!ExpectMore) {
1158       ElfBin = std::move(Out);
1159     } else {
1160       IGC_ASSERT(Out.empty());
1161     }
1162     LLVM_DEBUG(dbgs() << "---     \\ Debug Info Finalized /     ---\n");
1163   }
1164 
1165   const auto &KernelName = KF.getName();
1166   LLVM_DEBUG(dbgs() << "got Debug Info for <" << KernelName.str() << "> "
1167                     << "- " << ElfBin.size() << " bytes\n");
1168 
1169   const auto &BC = getAnalysis<GenXBackendConfig>();
1170   if (BC.dbgInfoDumpsEnabled()) {
1171     const auto &ErrLog = Emitter->getErrors();
1172     dumpDebugInfo(BC, KernelName, ElfBin, GOW.getGenDebug(),
1173                   {ErrLog.data(), ErrLog.size()});
1174   }
1175 
1176   return;
1177 }
1178 
cleanup()1179 void GenXDebugInfo::cleanup() {
1180   ElfOutputs.clear();
1181 }
1182 
getAnalysisUsage(AnalysisUsage & AU) const1183 void GenXDebugInfo::getAnalysisUsage(AnalysisUsage &AU) const {
1184   AU.addRequired<FunctionGroupAnalysis>();
1185   AU.addRequired<GenXBackendConfig>();
1186   AU.addRequired<GenXModule>();
1187   AU.addRequired<TargetPassConfig>();
1188   AU.addRequired<GenXVisaRegAllocWrapper>();
1189   AU.addRequired<CallGraphWrapperPass>();
1190   AU.setPreservesAll();
1191 }
1192 
processPrimaryFunction(const IGC::DebugEmitterOpts & Opts,const ModuleToVisaTransformInfo & MVTI,const GenXModule & GM,VISABuilder & VB,const Function & PF)1193 void GenXDebugInfo::processPrimaryFunction(
1194     const IGC::DebugEmitterOpts &Opts, const ModuleToVisaTransformInfo &MVTI,
1195     const GenXModule &GM, VISABuilder &VB, const Function &PF) {
1196   LLVM_DEBUG(dbgs() << "DbgInfo: processing <" << PF.getName() << ">\n");
1197   IGC_ASSERT(MVTI.isKernelFunction(&PF));
1198   VISAKernel *VKEntry = MVTI.getSpawnedVISAKernel(&PF);
1199   IGC_ASSERT(VKEntry);
1200 
1201   using FunctionInfo = ProgramInfo::FunctionInfo;
1202   std::vector<FunctionInfo> FIs;
1203   FIs.push_back(FunctionInfo{*GM.getVisaMapping(&PF), PF});
1204   const auto &SecondaryFunctions = MVTI.getSecondaryFunctions(&PF);
1205   std::transform(SecondaryFunctions.begin(), SecondaryFunctions.end(),
1206                  std::back_inserter(FIs), [&GM](const Function *F) {
1207                    const auto &Mapping = *GM.getVisaMapping(F);
1208                    return FunctionInfo{Mapping, *F};
1209                  });
1210   processKernel(Opts, ProgramInfo{MVTI, *VKEntry, std::move(FIs)});
1211 }
1212 
fillDbgInfoOptions(const GenXBackendConfig & BC,IGC::DebugEmitterOpts & DebugOpts)1213 static void fillDbgInfoOptions(const GenXBackendConfig &BC,
1214                                IGC::DebugEmitterOpts &DebugOpts) {
1215   DebugOpts.DebugEnabled = true;
1216   DebugOpts.EmitDebugLoc = true;
1217 
1218   if (BC.emitDebugInfoForZeBin() || DbgOpt_ZeBinCompatible) {
1219     DebugOpts.ZeBinCompatible = true;
1220     DebugOpts.EnableRelocation = true;
1221     DebugOpts.EnforceAMD64Machine = true;
1222   }
1223   if (BC.enableDebugInfoValidation() || DbgOpt_ValidationEnable) {
1224     DebugOpts.EnableDebugInfoValidation = true;
1225   }
1226 }
1227 
runOnModule(Module & M)1228 bool GenXDebugInfo::runOnModule(Module &M) {
1229   auto &GM = getAnalysis<GenXModule>();
1230   // Note: we check that MVTI dumps were not requested here,
1231   // since it is possible to request those without the presence of
1232   // debug information
1233   if (!GM.emitDebugInformation() && DbgOpt_VisaTransformInfoPath.empty())
1234     return false;
1235 
1236   const auto &BC = getAnalysis<GenXBackendConfig>();
1237   const FunctionGroupAnalysis &FGA = getAnalysis<FunctionGroupAnalysis>();
1238 
1239   VISABuilder *VB = GM.GetCisaBuilder();
1240   if (GM.HasInlineAsm())
1241     VB = GM.GetVISAAsmReader();
1242   IGC_ASSERT(VB);
1243 
1244   const auto &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
1245   ModuleToVisaTransformInfo MVTI(*VB, FGA, CG);
1246   if (!DbgOpt_VisaTransformInfoPath.empty()) {
1247     std::string SerializedMVTI;
1248     llvm::raw_string_ostream OS(SerializedMVTI);
1249     MVTI.print(OS);
1250     vc::produceAuxiliaryShaderDumpFile(BC, DbgOpt_VisaTransformInfoPath,
1251                                        OS.str());
1252   }
1253   LLVM_DEBUG(MVTI.print(dbgs()); dbgs() << "\n");
1254 
1255   if (!GM.emitDebugInformation())
1256     return false;
1257 
1258   IGC::DebugEmitterOpts DebugInfoOpts;
1259   fillDbgInfoOptions(BC, DebugInfoOpts);
1260 
1261   for (const Function *PF : MVTI.getPrimaryFunctions())
1262     processPrimaryFunction(DebugInfoOpts, MVTI, GM, *VB, *PF);
1263 
1264   return false;
1265 }
1266 
1267 char GenXDebugInfo::ID = 0;
1268 
createGenXDebugInfoPass()1269 ModulePass *createGenXDebugInfoPass() {
1270   initializeGenXDebugInfoPass(*PassRegistry::getPassRegistry());
1271   return new GenXDebugInfo;
1272 }
1273 
1274 } // namespace llvm
1275 
1276 INITIALIZE_PASS_BEGIN(GenXDebugInfo, "GenXDebugInfo", "GenXDebugInfo", false,
1277                       true /*analysis*/)
1278 INITIALIZE_PASS_DEPENDENCY(FunctionGroupAnalysis)
1279 INITIALIZE_PASS_DEPENDENCY(GenXBackendConfig)
1280 INITIALIZE_PASS_DEPENDENCY(GenXModule)
1281 INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
1282 INITIALIZE_PASS_DEPENDENCY(GenXVisaRegAllocWrapper)
1283 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
1284 INITIALIZE_PASS_END(GenXDebugInfo, "GenXDebugInfo", "GenXDebugInfo", false,
1285                     true /*analysis*/)
1286