1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 /*========================== begin_copyright_notice ============================
10
11 This file is distributed under the University of Illinois Open Source License.
12 See LICENSE.TXT for details.
13
14 ============================= end_copyright_notice ===========================*/
15
16 #include "llvm/Config/llvm-config.h"
17 #include "common/LLVMWarningsPush.hpp"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/DIBuilder.h"
20 #include "llvm/IR/Verifier.h"
21 #include "llvm/MC/MCDwarf.h"
22 #include "llvm/MC/MCSymbol.h"
23 #include "llvm/BinaryFormat/ELF.h"
24 #include "common/LLVMWarningsPop.hpp"
25
26 #include "VISADebugEmitter.hpp"
27 #include "DwarfDebug.hpp"
28 #include "StreamEmitter.hpp"
29 #include "VISAModule.hpp"
30
31 #include "Probe/Assertion.h"
32 #include "secure_mem.h"
33
34 #include "CLElfLib/CLElfTypes.h"
35
36 #define DEBUG_TYPE "dwarfdebug"
37
38 using namespace llvm;
39 using namespace IGC;
40 using namespace CLElfLib; // ElfReader related typedefs
41
Create()42 IDebugEmitter* IDebugEmitter::Create()
43 {
44 return new DebugEmitter();
45 }
46
Release(IDebugEmitter * pDebugEmitter)47 void IDebugEmitter::Release(IDebugEmitter* pDebugEmitter)
48 {
49 delete pDebugEmitter;
50 }
51
DebugEmitter()52 DebugEmitter::DebugEmitter() : IDebugEmitter(), m_outStream(m_str)
53 {
54 }
~DebugEmitter()55 DebugEmitter::~DebugEmitter()
56 {
57 Reset();
58 }
59
Reset()60 void DebugEmitter::Reset()
61 {
62 m_str.clear();
63 m_pVISAModule = nullptr;
64
65 m_pStreamEmitter.reset();
66 m_pDwarfDebug.reset();
67
68 m_initialized = false;
69 }
70
71
Initialize(std::unique_ptr<VISAModule> VM,const DebugEmitterOpts & Opts)72 void DebugEmitter::Initialize(std::unique_ptr<VISAModule> VM,
73 const DebugEmitterOpts& Opts)
74 {
75 IGC_ASSERT_MESSAGE(false == m_initialized, "DebugEmitter is already initialized!");
76 // IGC_ASSERT(!doneOnce);
77 m_initialized = true;
78
79 m_pVISAModule = VM.get();
80 m_debugEnabled = Opts.DebugEnabled;
81 // VISA module will be initialized even when debugger is disabled.
82 // Its overhead is minimum and it will be used in debug mode to
83 // assertion test on calling DebugEmitter in the right order.
84 toFree.push_back(std::move(VM));
85
86 if (!m_debugEnabled)
87 {
88 return;
89 }
90
91 const auto &dataLayout = m_pVISAModule->GetDataLayout();
92 m_pStreamEmitter = std::make_unique<StreamEmitter>(
93 m_outStream, dataLayout, m_pVISAModule->GetTargetTriple(), Opts);
94 m_pDwarfDebug = std::make_unique<DwarfDebug>(m_pStreamEmitter.get(), m_pVISAModule);
95
96 registerVISA(m_pVISAModule);
97 }
98
processCurrentFunction(bool finalize,const DbgDecoder * decodedDbg)99 void DebugEmitter::processCurrentFunction(bool finalize, const DbgDecoder* decodedDbg) {
100
101 auto EmitIpLabel = [&](unsigned int ip)
102 {
103 // Emit label before %ip
104 if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
105 {
106 auto instLabel = m_pDwarfDebug->GetLabelBeforeIp(ip);
107 m_pStreamEmitter->EmitLabel(instLabel);
108 }
109 };
110
111 m_pVISAModule->buildDirectElfMaps(*decodedDbg);
112 auto co = m_pVISAModule->getCompileUnit(*decodedDbg);
113
114 // Emit src line mapping directly instead of
115 // relying on dbgmerge. elf generated will have
116 // text section and debug_line sections populated.
117 const auto& VISAIndexToInst = m_pVISAModule->VISAIndexToInst;
118 const auto& VISAIndexToSize = m_pVISAModule->VISAIndexToSize;
119 decltype(m_pVISAModule->GenISAToVISAIndex) GenISAToVISAIndex;
120 unsigned int subEnd = m_pVISAModule->GetCurrentVISAId();
121 unsigned int prevLastGenOff = lastGenOff;
122 m_pDwarfDebug->lowPc = lastGenOff;
123
124 // SIMD width
125 m_pDwarfDebug->simdWidth = m_pVISAModule->GetSIMDSize();
126
127 if (co->subs.size() == 0)
128 {
129 GenISAToVISAIndex = m_pVISAModule->GenISAToVISAIndex;
130 if (GenISAToVISAIndex.size() > 0)
131 lastGenOff = GenISAToVISAIndex.back().GenOffset;
132 m_pDwarfDebug->lowPc = co->relocOffset;
133 }
134 else
135 {
136 for (auto item : m_pVISAModule->GenISAToVISAIndex)
137 {
138 if ((item.GenOffset >= lastGenOff) || ((item.GenOffset | lastGenOff) == 0))
139 {
140 if (item.VisaOffset <= subEnd || item.VisaOffset == 0xffffffff)
141 {
142 GenISAToVISAIndex.push_back(item);
143 auto size = m_pVISAModule->GenISAInstSizeBytes[item.GenOffset];
144 lastGenOff = item.GenOffset + size;
145 continue;
146 }
147
148 if (item.VisaOffset > subEnd)
149 break;
150 }
151 }
152 }
153
154 auto genxISA = m_pVISAModule->getGenBinary();
155 DebugLoc prevSrcLoc = DebugLoc();
156 unsigned int pc = prevLastGenOff;
157
158 if (!GenISAToVISAIndex.empty()) {
159 IGC_ASSERT(GenISAToVISAIndex.rbegin()->GenOffset <= genxISA.size());
160 IGC_ASSERT(pc < genxISA.size());
161 IGC_ASSERT(GenISAToVISAIndex.begin()->GenOffset >= pc);
162 }
163 for (auto item : GenISAToVISAIndex)
164 {
165 for (unsigned int i = pc; i != item.GenOffset; i++)
166 {
167 EmitIpLabel(i);
168 m_pStreamEmitter->EmitInt8(genxISA[i]);
169 }
170
171 pc = item.GenOffset;
172
173 auto instIt = VISAIndexToInst.end();
174 auto sizeIt = VISAIndexToSize.find(item.VisaOffset);
175 if (sizeIt != VISAIndexToSize.end())
176 {
177 // Lookup all VISA instructions that may
178 // map to an llvm::Instruction. This is useful
179 // when an llvm::Instruction leads to multiple
180 // VISA instructions, and VISA optimizer
181 // optimizes some of those away. Src line
182 // mapping for all VISA instructions is the
183 // same. So lookup any one that still exists.
184 auto startIdx = sizeIt->second.VisaOffset;
185 auto numVISAInsts = sizeIt->second.VisaInstrNum;
186 // Loop till at least one VISA instruction
187 // is found.
188 for (unsigned int visaId = startIdx;
189 visaId != (startIdx + numVISAInsts); visaId++)
190 {
191 instIt = VISAIndexToInst.find(visaId);
192 if (instIt != VISAIndexToInst.end())
193 break;
194 }
195 }
196
197 if (instIt == VISAIndexToInst.end())
198 continue;
199 if (!m_pVISAModule->IsExecutableInst(*instIt->second))
200 continue;
201
202 const auto& loc = instIt->second->getDebugLoc();
203 if (!loc || loc == prevSrcLoc)
204 continue;
205
206 const auto* scope = loc->getScope();
207 auto src = m_pDwarfDebug->getOrCreateSourceID(scope->getFilename(), scope->getDirectory(), m_pStreamEmitter->GetDwarfCompileUnitID());
208
209 unsigned int Flags = 0;
210 if (!m_pDwarfDebug->isStmtExists(loc.getLine(), loc.getInlinedAt(), true))
211 {
212 Flags |= DWARF2_FLAG_IS_STMT;
213 }
214
215 if (!m_pDwarfDebug->prologueEndExists(loc.get()->getScope()->getSubprogram(),
216 loc.getInlinedAt(), true))
217 {
218 Flags |= DWARF2_FLAG_PROLOGUE_END;
219 }
220 m_pStreamEmitter->EmitDwarfLocDirective(src, loc.getLine(), loc.getCol(), Flags, 0, 0, scope->getFilename());
221
222 prevSrcLoc = loc;
223 }
224
225 if (finalize)
226 {
227 size_t unpaddedSize = m_pVISAModule->getUnpaddedProgramSize();
228
229 IGC_ASSERT(unpaddedSize <= genxISA.size());
230 IGC_ASSERT((pc < genxISA.size() && pc < unpaddedSize) || pc == unpaddedSize);
231
232 for (unsigned int i = pc; i != unpaddedSize; i++)
233 {
234 m_pStreamEmitter->EmitInt8(genxISA[i]);
235 lastGenOff++;
236 }
237 }
238 else if (pc != lastGenOff)
239 {
240 IGC_ASSERT(lastGenOff <= genxISA.size());
241 IGC_ASSERT((pc < genxISA.size() && pc < lastGenOff) || pc == lastGenOff);
242 // for subroutines
243 for (unsigned int i = pc; i != lastGenOff; i++)
244 {
245 EmitIpLabel(i);
246 m_pStreamEmitter->EmitInt8(genxISA[i]);
247 }
248 }
249
250 m_pDwarfDebug->highPc = lastGenOff;
251 }
252
SetDISPCache(DwarfDISubprogramCache * DISPCache)253 void DebugEmitter::SetDISPCache(DwarfDISubprogramCache *DISPCache) {
254 IGC_ASSERT(m_pDwarfDebug);
255 m_pDwarfDebug->setDISPCache(DISPCache);
256 }
257
Finalize(bool finalize,const DbgDecoder * decodedDbg)258 std::vector<char> DebugEmitter::Finalize(bool finalize,
259 const DbgDecoder* decodedDbg)
260 {
261 if (!m_debugEnabled)
262 {
263 return {};
264 }
265
266 IGC_ASSERT_MESSAGE(m_pVISAModule, "active visa object must be selected before finalization");
267 IGC_ASSERT(m_pDwarfDebug);
268 m_pDwarfDebug->setDecodedDbg(decodedDbg);
269
270 if (!doneOnce)
271 {
272 m_pDwarfDebug->beginModule();
273 doneOnce = true;
274 }
275
276 const Function* pFunc = m_pVISAModule->GetEntryFunction();
277 // Collect debug information for given function.
278 m_pStreamEmitter->SwitchSection(m_pStreamEmitter->GetTextSection());
279
280 LLVM_DEBUG(dbgs() << "[DwarfDebug] beginFunction called for <" <<
281 pFunc->getName() << "> ---\n");
282 m_pDwarfDebug->beginFunction(pFunc, m_pVISAModule);
283 LLVM_DEBUG(dbgs() << "[DwarfDebug] beginFunction end ***\n");
284
285 processCurrentFunction(finalize, decodedDbg);
286
287 // Emit post-function debug information
288 LLVM_DEBUG(dbgs() << "[DwarfDebug] endFunction start ---\n");
289 m_pDwarfDebug->endFunction(pFunc);
290 LLVM_DEBUG(dbgs() << "[DwarfDebug] endFunction done ***\n");
291
292 if (!finalize)
293 {
294 LLVM_DEBUG(dbgs() << "[DwarfDebug] non-finalized exit ***\n");
295 return {};
296 }
297 LLVM_DEBUG(dbgs() << "[DwarfDebug] starting finalization ---\n");
298
299 IGC_ASSERT(doneOnce);
300
301 // Finalize debug information.
302 m_pDwarfDebug->endModule();
303
304 m_pStreamEmitter->Finalize();
305 LLVM_DEBUG(dbgs() << "[DwarfDebug] finalized***\n");
306
307 LLVM_DEBUG(dbgs() << "Finalized Visa Module:\n");
308 LLVM_DEBUG(m_pVISAModule->dump());
309
310 // Add program header table to satisfy latest gdb
311 bool is64Bit = m_pVISAModule->getPointerSize() == 8;
312 unsigned int phtSize = sizeof(llvm::ELF::Elf32_Phdr);
313 if (is64Bit)
314 phtSize = sizeof(llvm::ELF::Elf64_Phdr);
315
316 const Function* PrimaryEntry = m_pDwarfDebug->GetPrimaryEntry();
317 std::string EntryNameWithDot = ("." + PrimaryEntry->getName()).str();
318 size_t ContentSize = m_str.size();
319 if (m_pStreamEmitter->GetEmitterSettings().ZeBinCompatible)
320 ContentSize += EntryNameWithDot.size();
321
322 size_t elfWithProgramHeaderSize = phtSize + ContentSize;
323 std::vector<char> Result(elfWithProgramHeaderSize);
324
325 if (!m_pStreamEmitter->GetEmitterSettings().ZeBinCompatible)
326 {
327 // Text section remains with its standard name .text
328 std::copy(m_str.begin(), m_str.end(), Result.begin());
329 }
330 else
331 {
332 // Text section's name to be extended by a kernel name.
333 size_t endOfDotTextNameOffset = 0;
334 prepareElfForZeBinary(is64Bit, m_str.begin(), m_str.size(),
335 EntryNameWithDot.size(), &endOfDotTextNameOffset);
336
337 // First copy ELF binary from the beginning to the .text name (included) located in the .str.tab
338 std::copy(m_str.begin(), m_str.begin() + endOfDotTextNameOffset, Result.begin());
339 // Next concatenate .text with a kernel name (a dot joining both names also added).
340 std::copy(EntryNameWithDot.begin(), EntryNameWithDot.end(),
341 Result.begin() + endOfDotTextNameOffset);
342 // Finally copy remaining part of ELF binary.
343 std::copy(m_str.begin() + endOfDotTextNameOffset + 1, m_str.end(),
344 Result.begin() + endOfDotTextNameOffset + 1 + EntryNameWithDot.size());
345 }
346
347 writeProgramHeaderTable(is64Bit, Result.data(), ContentSize);
348 setElfType(is64Bit, Result.data());
349
350 m_errs = m_pStreamEmitter->getErrors();
351 Reset();
352
353 return std::move(Result);
354 }
355
prepareElfForZeBinary(bool is64Bit,char * pElfBuffer,size_t elfBufferSize,size_t kernelNameWithDotSize,size_t * pEndOfDotTextNameInStrtab)356 void DebugEmitter::prepareElfForZeBinary(bool is64Bit, char* pElfBuffer, size_t elfBufferSize, size_t kernelNameWithDotSize,
357 size_t* pEndOfDotTextNameInStrtab)
358 {
359 // ELF binary header contains 'SectionHeadersOffset' (e_shoff in ELF spec.), which is an offset
360 // to section headers placed one by one. A location (index) of the header with names (including section name)
361 // is stored in the ELF binary header at 'SectionNameTableIndex' (e_shstrndx). A section header under this index
362 // contains an offset to location of the String Table data, which may look as showed in the line below:
363 // .debug_abbrev .text.stackcall .debug_ranges .debug_str .debug_info
364 // ^NULL ^NULL ^NULL ^NULL ^NULL ^NULL
365 //
366 // Each section header contain 'Name' (sh_name) fields which is a byte offset to this data showed above.
367 // The String Table is a simple chunk of memory, where the names are placed one by one and separated by NULL (\0).
368 // String Table contains NULL (\0) also at the beginning (i.e. 'Name' equal 0 means no name).
369
370 if (is64Bit)
371 {
372 SElf64Header* pElf64Header = (SElf64Header*)pElfBuffer;
373
374 // First simply validate ELF binary
375 IGC_ASSERT_MESSAGE(pElf64Header &&
376 (pElf64Header->Identity[ID_IDX_MAGIC0] == ELF_MAG0) &&
377 (pElf64Header->Identity[ID_IDX_MAGIC1] == ELF_MAG1) &&
378 (pElf64Header->Identity[ID_IDX_MAGIC2] == ELF_MAG2) &&
379 (pElf64Header->Identity[ID_IDX_MAGIC3] == ELF_MAG3) &&
380 (pElf64Header->Identity[ID_IDX_CLASS] == EH_CLASS_64), "ELF file header incorrect");
381
382 // Using the Section Name Table Index, calculate the offset to the String Table (.strtab) header.
383 size_t entrySize = pElf64Header->SectionHeaderEntrySize;
384 size_t nameSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (pElf64Header->SectionNameTableIndex * entrySize);
385 IGC_ASSERT_MESSAGE(pElf64Header->SectionNameTableIndex < pElf64Header->NumSectionHeaderEntries, "ELF header incorrect");
386 IGC_ASSERT_MESSAGE(nameSectionHeaderOffset < elfBufferSize, "ELF header incorrect");
387
388 // Using the offset found above get a header of the String Table section
389 SElf64SectionHeader* pNamesSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + nameSectionHeaderOffset);
390 SElf64SectionHeader* pSectionHeader = NULL;
391 size_t indexedSectionHeaderOffset = 0;
392 Elf64_Word textSectionHeaderName = 0;
393 char* pSectionName = NULL;
394 size_t sectionNameOffset = 0;
395 size_t textSectionNameOffset = 0;
396
397 // Scan section headers to find the Text section using simple section name comparison.
398 for (unsigned int elfSectionIdx = 1; elfSectionIdx < pElf64Header->NumSectionHeaderEntries; elfSectionIdx++)
399 {
400 // Calculate a byte offset to the current section's header
401 indexedSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (elfSectionIdx * entrySize);
402
403 // Get a header of the current section
404 pSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + indexedSectionHeaderOffset);
405
406 // Using the byte offset from the current section's header, find the current section's name
407 // in the String Table.
408 sectionNameOffset = (size_t)pNamesSectionHeader->DataOffset + pSectionHeader->Name;
409 pSectionName = (char*)pElf64Header + sectionNameOffset;
410
411 // Check if the Text section is found.
412 if (pSectionName && (strcmp(pSectionName, ".text") == 0))
413 {
414 textSectionHeaderName = pSectionHeader->Name; // Remember for the next loop over sections.
415 textSectionNameOffset = sectionNameOffset; // Remember for the next loop over sections.
416 pNamesSectionHeader->DataSize += kernelNameWithDotSize; //.strtab size increases not .text section
417
418 // Return an offset (from the beginning of ELF binary) to the first character after '.text'
419 *pEndOfDotTextNameInStrtab = sectionNameOffset + sizeof(".text") - 1;
420 break; // Text section found, its location saved.
421 }
422 }
423
424 // Update headers of ELF sections due to a longer Text section name
425 // (i.e. in strtab .text will be replaced with .text.kernelName).
426 // - change location of each section name located after the Text section name in .strtab
427 // - change data offset of each section located after the .strtab section
428 for (unsigned int elfSectionIdx = 1; elfSectionIdx < pElf64Header->NumSectionHeaderEntries; elfSectionIdx++)
429 {
430 indexedSectionHeaderOffset = (size_t)pElf64Header->SectionHeadersOffset + (elfSectionIdx * entrySize);
431
432 pSectionHeader = (SElf64SectionHeader*)((char*)pElf64Header + indexedSectionHeaderOffset);
433 if (pSectionHeader->Name > textSectionHeaderName)
434 {
435 pSectionHeader->Name += kernelNameWithDotSize;
436 }
437 if (pSectionHeader->DataOffset > textSectionNameOffset)
438 {
439 pSectionHeader->DataOffset += kernelNameWithDotSize;
440 // This data offset update may be not enough if such a section contains elf global offsets
441 // (i.e. relative to the beginning of the elf binary).
442 // However, as long as .strtab is the last section in our ELF binary then there is no side-effects.
443 // If location of this section changes in the future, then a copy (or move) of this section content
444 // will be required. This future need must be verified if the assertion below hits (then
445 // assertion below must be changed based on results of such verification).
446 IGC_ASSERT(0);
447 }
448 }
449
450 if (pSectionHeader)
451 {
452 // ELF binary header also must be updated to reflect offsets changes.
453 if (pElf64Header->SectionHeadersOffset > pSectionHeader->DataOffset)
454 {
455 pElf64Header->SectionHeadersOffset += kernelNameWithDotSize;
456 }
457 if (pElf64Header->ProgramHeadersOffset > pSectionHeader->DataOffset)
458 {
459 pElf64Header->ProgramHeadersOffset += kernelNameWithDotSize;
460 }
461 }
462 }
463 else
464 {
465 IGC_ASSERT_MESSAGE(is64Bit, "64-bit ELF file only supported");
466 }
467 }
468
setElfType(bool is64Bit,void * pBuffer)469 void DebugEmitter::setElfType(bool is64Bit, void* pBuffer)
470 {
471 // Set 1-step elf's e_type to ET_EXEC
472 if (!pBuffer)
473 return;
474
475 if (is64Bit)
476 {
477 void* etypeOff = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf64_Ehdr, e_type));
478 if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
479 {
480 *((llvm::ELF::Elf64_Half*)etypeOff) = llvm::ELF::ET_REL;
481 }
482 else
483 {
484 *((llvm::ELF::Elf64_Half*)etypeOff) = llvm::ELF::ET_EXEC;
485 }
486 }
487 else
488 {
489 void* etypeOff = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf32_Ehdr, e_type));
490 if (m_pStreamEmitter->GetEmitterSettings().EnableRelocation)
491 {
492 *((llvm::ELF::Elf32_Half*)etypeOff) = llvm::ELF::ET_REL;
493 }
494 else
495 {
496 *((llvm::ELF::Elf32_Half*)etypeOff) = llvm::ELF::ET_EXEC;
497 }
498 }
499 }
500
writeProgramHeaderTable(bool is64Bit,void * pBuffer,unsigned int size)501 void DebugEmitter::writeProgramHeaderTable(bool is64Bit, void* pBuffer, unsigned int size)
502 {
503 // Write program header table at end of elf
504 if (is64Bit)
505 {
506 llvm::ELF::Elf64_Phdr hdr;
507 hdr.p_type = llvm::ELF::PT_LOAD;
508 hdr.p_flags = 0;
509 hdr.p_offset = 0;
510 hdr.p_vaddr = 0;
511 hdr.p_paddr = 0;
512 hdr.p_filesz = size;
513 hdr.p_memsz = size;
514 hdr.p_align = 4;
515 void* phOffAddr = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf64_Ehdr, e_phoff));
516 *(llvm::ELF::Elf64_Off*)(phOffAddr) = size;
517 ((char*)pBuffer)[offsetof(llvm::ELF::Elf64_Ehdr, e_phentsize)] = sizeof(llvm::ELF::Elf64_Phdr);
518 ((char*)pBuffer)[offsetof(llvm::ELF::Elf64_Ehdr, e_phnum)] = 1;
519 memcpy_s((char*)pBuffer + size, sizeof(llvm::ELF::Elf64_Phdr), &hdr, sizeof(hdr));
520 }
521 else
522 {
523 llvm::ELF::Elf32_Phdr hdr;
524 hdr.p_type = llvm::ELF::PT_LOAD;
525 hdr.p_offset = 0;
526 hdr.p_vaddr = 0;
527 hdr.p_paddr = 0;
528 hdr.p_filesz = size;
529 hdr.p_memsz = size;
530 hdr.p_flags = 0;
531 hdr.p_align = 4;
532 void* phOffAddr = ((char*)pBuffer) + (offsetof(llvm::ELF::Elf32_Ehdr, e_phoff));
533 *(llvm::ELF::Elf32_Off*)(phOffAddr) = size;
534 ((char*)pBuffer)[offsetof(llvm::ELF::Elf32_Ehdr, e_phentsize)] = sizeof(llvm::ELF::Elf32_Phdr);
535 ((char*)pBuffer)[offsetof(llvm::ELF::Elf32_Ehdr, e_phnum)] = 1;
536 memcpy_s((char*)pBuffer + size, sizeof(llvm::ELF::Elf32_Phdr), &hdr, sizeof(hdr));
537 }
538 }
539
BeginInstruction(Instruction * pInst)540 void DebugEmitter::BeginInstruction(Instruction* pInst)
541 {
542 BeginEncodingMark();
543 if (!m_debugEnabled)
544 {
545 return;
546 }
547 m_pVISAModule->BeginInstruction(pInst);
548 }
549
EndInstruction(Instruction * pInst)550 void DebugEmitter::EndInstruction(Instruction* pInst)
551 {
552 EndEncodingMark();
553 if (!m_debugEnabled)
554 {
555 return;
556 }
557 m_pVISAModule->EndInstruction(pInst);
558 }
559
BeginEncodingMark()560 void DebugEmitter::BeginEncodingMark()
561 {
562 m_pVISAModule->BeginEncodingMark();
563 }
564
EndEncodingMark()565 void DebugEmitter::EndEncodingMark()
566 {
567 m_pVISAModule->EndEncodingMark();
568 }
569 // TODO: do we really need it?
registerVISA(IGC::VISAModule * VM)570 void DebugEmitter::registerVISA(IGC::VISAModule* VM)
571 {
572 m_pDwarfDebug->registerVISA(VM);
573 }
setCurrentVISA(IGC::VISAModule * VM)574 void DebugEmitter::setCurrentVISA(IGC::VISAModule* VM) {
575 // TODO: add assertion statement to check that this module is registered/owned
576 m_pVISAModule = VM;
577 }
resetModule(std::unique_ptr<IGC::VISAModule> VM)578 void DebugEmitter::resetModule(std::unique_ptr<IGC::VISAModule> VM) {
579 m_pVISAModule = VM.get();
580 toFree.push_back(std::move(VM));
581 }
582
getErrors() const583 const std::string& DebugEmitter::getErrors() const {
584 return m_errs;
585 }
586