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/DataLayout.h"
19 #include "llvm/IR/GlobalValue.h"
20 #include "llvm/MC/MCAsmBackend.h"
21 #include "llvmWrapper/ADT/STLExtras.h"
22 #include "llvm/MC/MCAsmInfoELF.h"
23 #include "llvm/MC/MCCodeEmitter.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCExpr.h"
26 #include "llvm/MC/MCELFObjectWriter.h"
27 #include "llvm/MC/MCObjectFileInfo.h"
28 #include "llvm/MC/MCObjectWriter.h"
29 #include "llvm/MC/MCRegisterInfo.h"
30 #include "llvm/MC/MCSection.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/MC/MCValue.h"
34 #include "llvm/Support/TargetRegistry.h"
35 #include "llvm/Support/SourceMgr.h"
36 #include "common/LLVMWarningsPop.hpp"
37
38 #include "DIE.hpp"
39 #include "StreamEmitter.hpp"
40 #include "DwarfDebug.hpp"
41
42 #include "Probe/Assertion.h"
43
44 #define DEBUG_TYPE "dwarfdebug"
45
46 using namespace llvm;
47 using namespace IGC;
48
49 namespace IGC
50 {
51 ///////////////////////////////////////////////////////////////////////////////
52 // Following classes extend abstract MC classes.
53 // These classes are needed to create concrete instance of MCStreamer.
54 ///////////////////////////////////////////////////////////////////////////////
55
56 class VISAMCAsmInfo : public MCAsmInfoELF
57 {
58 public:
VISAMCAsmInfo(unsigned int pointerSize)59 VISAMCAsmInfo(unsigned int pointerSize) : MCAsmInfoELF()
60 {
61 DwarfUsesRelocationsAcrossSections = true;
62 CodePointerSize = pointerSize;
63 }
64 };
65
66 class VISAELFObjectWriter : public MCELFObjectTargetWriter
67 {
68 public:
VISAELFObjectWriter(bool is64Bit,uint8_t osABI,uint16_t eMachine,bool hasRelocationAddend)69 VISAELFObjectWriter(bool is64Bit, uint8_t osABI,
70 uint16_t eMachine, bool hasRelocationAddend) :
71 MCELFObjectTargetWriter(is64Bit, osABI, eMachine, hasRelocationAddend)
72 {
73 }
74
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const75 unsigned getRelocType(MCContext& Ctx, const MCValue& Target,
76 const MCFixup& Fixup, bool IsPCRel) const {
77 MCSymbolRefExpr::VariantKind modifier = Target.isAbsolute() ?
78 MCSymbolRefExpr::VK_None : Target.getSymA()->getKind();
79 unsigned type = ELF::R_X86_64_NONE;
80 if (is64Bit())
81 {
82 if (IsPCRel)
83 {
84 switch ((unsigned)Fixup.getKind())
85 {
86 default: IGC_ASSERT_EXIT_MESSAGE(0, "invalid fixup kind!");
87
88 case FK_Data_8: type = ELF::R_X86_64_PC64; break;
89 case FK_Data_4: type = ELF::R_X86_64_PC32; break;
90 case FK_Data_2: type = ELF::R_X86_64_PC16; break;
91
92 case FK_PCRel_8:
93 IGC_ASSERT(modifier == MCSymbolRefExpr::VK_None);
94 type = ELF::R_X86_64_PC64;
95 break;
96 case FK_PCRel_4:
97 switch (modifier)
98 {
99 default:
100 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
101 case MCSymbolRefExpr::VK_None:
102 type = ELF::R_X86_64_PC32;
103 break;
104 case MCSymbolRefExpr::VK_PLT:
105 type = ELF::R_X86_64_PLT32;
106 break;
107 case MCSymbolRefExpr::VK_GOTPCREL:
108 type = ELF::R_X86_64_GOTPCREL;
109 break;
110 case MCSymbolRefExpr::VK_GOTTPOFF:
111 type = ELF::R_X86_64_GOTTPOFF;
112 break;
113 case MCSymbolRefExpr::VK_TLSGD:
114 type = ELF::R_X86_64_TLSGD;
115 break;
116 case MCSymbolRefExpr::VK_TLSLD:
117 type = ELF::R_X86_64_TLSLD;
118 break;
119 }
120 break;
121 case FK_PCRel_2:
122 IGC_ASSERT(modifier == MCSymbolRefExpr::VK_None);
123 type = ELF::R_X86_64_PC16;
124 break;
125 case FK_PCRel_1:
126 IGC_ASSERT(modifier == MCSymbolRefExpr::VK_None);
127 type = ELF::R_X86_64_PC8;
128 break;
129 }
130 }
131 else
132 {
133 switch ((unsigned)Fixup.getKind())
134 {
135 default: IGC_ASSERT_EXIT_MESSAGE(0, "invalid fixup kind!");
136 case FK_Data_8:
137 switch (modifier)
138 {
139 default:
140 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
141 case MCSymbolRefExpr::VK_None:
142 type = ELF::R_X86_64_64;
143 break;
144 case MCSymbolRefExpr::VK_GOT:
145 type = ELF::R_X86_64_GOT64;
146 break;
147 case MCSymbolRefExpr::VK_GOTOFF:
148 type = ELF::R_X86_64_GOTOFF64;
149 break;
150 case MCSymbolRefExpr::VK_TPOFF:
151 type = ELF::R_X86_64_TPOFF64;
152 break;
153 case MCSymbolRefExpr::VK_DTPOFF:
154 type = ELF::R_X86_64_DTPOFF64;
155 break;
156 }
157 break;
158 case FK_Data_4:
159 type = ELF::R_X86_64_32;
160 break;
161 case FK_Data_2: type = ELF::R_X86_64_16; break;
162 case FK_PCRel_1:
163 case FK_Data_1: type = ELF::R_X86_64_8; break;
164 }
165 }
166 }
167 else
168 {
169 if (IsPCRel)
170 {
171 switch ((unsigned)Fixup.getKind())
172 {
173 default: IGC_ASSERT_EXIT_MESSAGE(0, "invalid fixup kind!");
174
175 case FK_PCRel_4:
176 case FK_Data_4:
177 switch (modifier)
178 {
179 default:
180 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
181 case MCSymbolRefExpr::VK_None:
182 type = ELF::R_386_PC32;
183 break;
184 case MCSymbolRefExpr::VK_PLT:
185 type = ELF::R_386_PLT32;
186 break;
187 }
188 break;
189 }
190 }
191 else
192 {
193 switch ((unsigned)Fixup.getKind())
194 {
195 default: IGC_ASSERT_EXIT_MESSAGE(0, "invalid fixup kind!");
196
197 case FK_PCRel_4:
198 case FK_Data_4:
199 switch (modifier)
200 {
201 default:
202 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
203 case MCSymbolRefExpr::VK_None:
204 type = ELF::R_386_32;
205 break;
206 case MCSymbolRefExpr::VK_GOT:
207 type = ELF::R_386_GOT32;
208 break;
209 case MCSymbolRefExpr::VK_GOTOFF:
210 type = ELF::R_386_GOTOFF;
211 break;
212 case MCSymbolRefExpr::VK_TLSGD:
213 type = ELF::R_386_TLS_GD;
214 break;
215 case MCSymbolRefExpr::VK_TPOFF:
216 type = ELF::R_386_TLS_LE_32;
217 break;
218 case MCSymbolRefExpr::VK_INDNTPOFF:
219 type = ELF::R_386_TLS_IE;
220 break;
221 case MCSymbolRefExpr::VK_NTPOFF:
222 type = ELF::R_386_TLS_LE;
223 break;
224 case MCSymbolRefExpr::VK_GOTNTPOFF:
225 type = ELF::R_386_TLS_GOTIE;
226 break;
227 case MCSymbolRefExpr::VK_TLSLDM:
228 type = ELF::R_386_TLS_LDM;
229 break;
230 case MCSymbolRefExpr::VK_DTPOFF:
231 type = ELF::R_386_TLS_LDO_32;
232 break;
233 case MCSymbolRefExpr::VK_GOTTPOFF:
234 type = ELF::R_386_TLS_IE_32;
235 break;
236 }
237 break;
238 case FK_Data_2: type = ELF::R_386_16; break;
239 case FK_PCRel_1:
240 case FK_Data_1: type = ELF::R_386_8; break;
241 }
242 }
243 }
244
245 return type;
246 }
247 };
248
249 class VISAAsmBackend : public MCAsmBackend
250 {
251 StringRef m_targetTriple;
252 bool m_is64Bit;
253 public:
VISAAsmBackend(StringRef targetTriple,bool is64Bit)254 VISAAsmBackend(StringRef targetTriple, bool is64Bit)
255 : MCAsmBackend(support::endianness::little),
256 m_targetTriple(targetTriple), m_is64Bit(is64Bit) {}
257
getNumFixupKinds() const258 unsigned getNumFixupKinds() const override
259 {
260 return 0;
261 }
262
getFixupKindLog2Size(unsigned Kind)263 static unsigned getFixupKindLog2Size(unsigned Kind)
264 {
265 switch (Kind)
266 {
267 default: IGC_ASSERT_EXIT_MESSAGE(0, "invalid fixup kind!");
268 case FK_PCRel_1:
269 case FK_SecRel_1:
270 case FK_Data_1: return 0;
271 case FK_PCRel_2:
272 case FK_SecRel_2:
273 case FK_Data_2: return 1;
274 case FK_PCRel_4:
275 case FK_SecRel_4:
276 case FK_Data_4: return 2;
277 case FK_PCRel_8:
278 case FK_SecRel_8:
279 case FK_Data_8: return 3;
280 }
281 }
282
applyFixup(const MCAssembler & Asm,const MCFixup & fixup,const MCValue & Target,MutableArrayRef<char> Data,uint64_t value,bool IsResolved,const MCSubtargetInfo * STI) const283 void applyFixup(const MCAssembler & Asm, const MCFixup & fixup,
284 const MCValue & Target, MutableArrayRef<char> Data,
285 uint64_t value, bool IsResolved,
286 const MCSubtargetInfo * STI) const override
287 {
288 unsigned size = 1 << getFixupKindLog2Size(fixup.getKind());
289
290 IGC_ASSERT_MESSAGE(fixup.getOffset() + size <= Data.size(), "Invalid fixup offset!");
291
292 // Check that uppper bits are either all zeros or all ones.
293 // Specifically ignore overflow/underflow as long as the leakage is
294 // limited to the lower bits. This is to remain compatible with
295 // other assemblers.
296 IGC_ASSERT_MESSAGE(isIntN(size * 8 + 1, value), "value does not fit in the fixup field");
297
298 for (unsigned i = 0; i != size; ++i)
299 {
300 Data[fixup.getOffset() + i] = uint8_t(value >> (i * 8));
301 }
302 }
303
mayNeedRelaxation(const MCInst & inst,const MCSubtargetInfo & STI) const304 bool mayNeedRelaxation(const MCInst & inst, const MCSubtargetInfo & STI) const override
305 {
306 // TODO: implement this
307 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
308 return false;
309 }
310
fixupNeedsRelaxation(const MCFixup & fixup,uint64_t value,const MCRelaxableFragment * pDF,const MCAsmLayout & layout) const311 bool fixupNeedsRelaxation(const MCFixup& fixup,
312 uint64_t value,
313 const MCRelaxableFragment* pDF,
314 const MCAsmLayout& layout) const override
315 {
316 // TODO: implement this
317 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
318 return false;
319 }
320
321 #if LLVM_VERSION_MAJOR <= 10
relaxInstruction(const MCInst & inst,const MCSubtargetInfo & STI,MCInst & res) const322 void relaxInstruction(const MCInst& inst, const MCSubtargetInfo& STI,
323 MCInst& res) const override
324 {
325 // TODO: implement this
326 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
327 }
328 #endif
329
writeNopData(raw_ostream & OS,uint64_t Count) const330 bool writeNopData(raw_ostream & OS, uint64_t Count) const override
331 {
332 const char nop = (char)0x90;
333 for (uint64_t i = 0; i < Count; ++i)
334 {
335 OS.write(&nop, 1);
336 }
337 return true;
338 }
339
340 /// createObjectWriter - Create a new MCObjectWriter instance for use by the
341 /// assembler backend to emit the final object file.
createObjectWriter(llvm::raw_pwrite_stream & os) const342 std::unique_ptr<MCObjectWriter> createObjectWriter(llvm::raw_pwrite_stream & os) const
343 {
344 Triple triple(m_targetTriple);
345 uint8_t osABI = MCELFObjectTargetWriter::getOSABI(triple.getOS());
346 uint16_t eMachine = m_is64Bit ? ELF::EM_X86_64 : ELF::EM_386;
347 // Only i386 uses Rel instead of RelA.
348 bool hasRelocationAddend = eMachine != ELF::EM_386;
349 std::unique_ptr<MCELFObjectTargetWriter> pMOTW
350 = IGCLLVM::make_unique<VISAELFObjectWriter>(m_is64Bit, osABI, eMachine, hasRelocationAddend);
351 return createELFObjectWriter(std::move(pMOTW), os, /*IsLittleEndian=*/true);
352 }
353
createObjectTargetWriter() const354 std::unique_ptr<MCObjectTargetWriter> createObjectTargetWriter() const override
355 {
356 // TODO: implement this
357 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
358 }
359 };
360
361 class VISAMCCodeEmitter : public MCCodeEmitter
362 {
363 /// EncodeInstruction - Encode the given \p inst to bytes on the output
364 /// stream \p OS.
encodeInstruction(const MCInst & inst,raw_ostream & os,SmallVectorImpl<MCFixup> & fixups,const MCSubtargetInfo & m) const365 virtual void encodeInstruction(const MCInst& inst, raw_ostream& os, SmallVectorImpl<MCFixup>& fixups,
366 const MCSubtargetInfo& m) const
367 {
368 // TODO: implement this
369 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
370 }
371
operator =(const VISAMCCodeEmitter &)372 void operator=(const VISAMCCodeEmitter&)
373 {
374 // TODO: implement this
375 IGC_ASSERT_EXIT_MESSAGE(0, "Unimplemented");
376 }
377
378 };
379
380 } // namespace IGC
381
StreamEmitter(raw_pwrite_stream & outStream,const std::string & dataLayout,const std::string & targetTriple,const StreamEmitter::Settings & Options)382 StreamEmitter::StreamEmitter(raw_pwrite_stream& outStream,
383 const std::string& dataLayout,
384 const std::string& targetTriple,
385 const StreamEmitter::Settings &Options) :
386 m_targetTriple(targetTriple), m_setCounter(0),
387 StreamOptions(Options)
388 {
389 m_pDataLayout = new DataLayout(dataLayout);
390 m_pSrcMgr = new SourceMgr();
391 m_pAsmInfo = new VISAMCAsmInfo(GetPointerSize());
392 m_pObjFileInfo = new IGCLLVM::MCObjectFileInfo();
393
394 MCRegisterInfo* regInfo = nullptr;
395 Triple triple = Triple(GetTargetTriple());
396
397 // Create new MC context
398 m_pContext = IGCLLVM::CreateMCContext(triple, (const llvm::MCAsmInfo*)m_pAsmInfo, regInfo, m_pObjFileInfo, m_pSrcMgr);
399
400 m_pObjFileInfo->InitMCObjectFileInfo(triple, false, *m_pContext);
401
402 bool is64Bit = GetPointerSize() == 8;
403 uint8_t osABI = MCELFObjectTargetWriter::getOSABI(triple.getOS());
404 // Earlier eMachine was set to ELF::EM_X86_64 or ELF::EM_386
405 // This creates a problem for gdb so it is now set to 182
406 // which is an encoding reserved for Intel. It is not part of
407 // the enum so its value in inlined.
408 #define EM_INTEL_GEN 182
409 uint16_t eMachine = EM_INTEL_GEN;
410 if (StreamOptions.EnforceAMD64Machine)
411 eMachine = ELF::EM_X86_64;
412 bool hasRelocationAddend = is64Bit;
413 std::unique_ptr<MCAsmBackend> pAsmBackend
414 = IGCLLVM::make_unique<VISAAsmBackend>(GetTargetTriple(), is64Bit);
415 std::unique_ptr<MCELFObjectTargetWriter> pTargetObjectWriter
416 = IGCLLVM::make_unique<VISAELFObjectWriter>(is64Bit, osABI, eMachine, hasRelocationAddend);
417 std::unique_ptr<MCObjectWriter> pObjectWriter
418 = createELFObjectWriter(std::move(pTargetObjectWriter), outStream, true);
419 std::unique_ptr<MCCodeEmitter> pCodeEmitter
420 = IGCLLVM::make_unique<VISAMCCodeEmitter>();
421
422 bool isRelaxAll = false;
423 bool isNoExecStack = false;
424 m_pMCStreamer = createELFStreamer(*m_pContext,
425 std::move(pAsmBackend), std::move(pObjectWriter), std::move(pCodeEmitter), isRelaxAll);
426
427 m_pMCStreamer->InitSections(isNoExecStack);
428 }
429
~StreamEmitter()430 StreamEmitter::~StreamEmitter()
431 {
432 delete m_pMCStreamer;
433 delete m_pContext;
434 delete m_pSrcMgr;
435 delete m_pAsmInfo;
436 delete m_pObjFileInfo;
437 delete m_pDataLayout;
438 }
439
GetPointerSize() const440 unsigned int StreamEmitter::GetPointerSize() const
441 {
442 return m_pDataLayout->getPointerSize();
443 }
444
IsLittleEndian() const445 bool StreamEmitter::IsLittleEndian() const
446 {
447 return m_pDataLayout->isLittleEndian();
448 }
449
GetTextSection() const450 const MCSection* StreamEmitter::GetTextSection() const
451 {
452 return GetObjFileLowering().getTextSection();
453 }
454
GetDataSection() const455 const MCSection* StreamEmitter::GetDataSection() const
456 {
457 return GetObjFileLowering().getDataSection();
458 }
459
GetDwarfAbbrevSection() const460 const MCSection* StreamEmitter::GetDwarfAbbrevSection() const
461 {
462 return GetObjFileLowering().getDwarfAbbrevSection();
463 }
464
GetDwarfInfoSection() const465 const MCSection* StreamEmitter::GetDwarfInfoSection() const
466 {
467 return GetObjFileLowering().getDwarfInfoSection();
468 }
469
GetDwarfLineSection() const470 const MCSection* StreamEmitter::GetDwarfLineSection() const
471 {
472 return GetObjFileLowering().getDwarfLineSection();
473 }
474
GetDwarfLocSection() const475 const MCSection* StreamEmitter::GetDwarfLocSection() const
476 {
477 return GetObjFileLowering().getDwarfLocSection();
478 }
479
GetDwarfMacroInfoSection() const480 const MCSection* StreamEmitter::GetDwarfMacroInfoSection() const
481 {
482 //return GetObjFileLowering().getDwarfMacroInfoSection();
483 return nullptr;
484 }
485
GetDwarfRangesSection() const486 const MCSection* StreamEmitter::GetDwarfRangesSection() const
487 {
488 return GetObjFileLowering().getDwarfRangesSection();
489 }
490
GetDwarfStrSection() const491 const MCSection* StreamEmitter::GetDwarfStrSection() const
492 {
493 return GetObjFileLowering().getDwarfStrSection();
494 }
495
GetDwarfFrameSection() const496 const MCSection* StreamEmitter::GetDwarfFrameSection() const
497 {
498 return GetObjFileLowering().getDwarfFrameSection();
499 }
500
SwitchSection(const MCSection * pSection,const MCExpr * pSubsection) const501 void StreamEmitter::SwitchSection(const MCSection* pSection, const MCExpr* pSubsection) const
502 {
503 m_pMCStreamer->SwitchSection(const_cast<MCSection*>(pSection), pSubsection);
504 }
505
GetSymbol(const GlobalValue * pGV) const506 MCSymbol* StreamEmitter::GetSymbol(const GlobalValue* pGV) const
507 {
508 /*
509 //Original code (as reference)
510 SmallString<60> NameStr;
511 M.getNameWithPrefix(NameStr, pGV, false);
512 return m_pContext->GetOrCreateSymbol(NameStr.str());
513 */
514 IGC_ASSERT_MESSAGE(pGV->hasName(), "TODO: fix this case");
515 return m_pContext->getOrCreateSymbol(Twine(m_pAsmInfo->getPrivateGlobalPrefix()) + pGV->getName());
516 }
517
GetTempSymbol(StringRef name,uint64_t id) const518 MCSymbol* StreamEmitter::GetTempSymbol(StringRef name, uint64_t id) const
519 {
520 return m_pContext->getOrCreateSymbol(Twine(m_pAsmInfo->getPrivateGlobalPrefix()) + name + Twine(id));
521 }
522
GetTempSymbol(StringRef name) const523 MCSymbol* StreamEmitter::GetTempSymbol(StringRef name) const
524 {
525 return m_pContext->getOrCreateSymbol(Twine(m_pAsmInfo->getPrivateGlobalPrefix()) + name);
526 }
527
CreateTempSymbol() const528 MCSymbol* StreamEmitter::CreateTempSymbol() const
529 {
530 return m_pContext->createTempSymbol();
531 }
532
GetDwarfCompileUnitID() const533 unsigned StreamEmitter::GetDwarfCompileUnitID() const
534 {
535 return m_pContext->getDwarfCompileUnitID();
536 }
537
SetDwarfCompileUnitID(unsigned cuIndex) const538 void StreamEmitter::SetDwarfCompileUnitID(unsigned cuIndex) const
539 {
540 m_pContext->setDwarfCompileUnitID(cuIndex);
541 }
542
EmitBytes(StringRef data,unsigned addrSpace) const543 void StreamEmitter::EmitBytes(StringRef data, unsigned addrSpace) const
544 {
545 #if LLVM_VERSION_MAJOR <= 10
546 m_pMCStreamer->EmitBytes(data);
547 #else
548 m_pMCStreamer->emitBytes(data);
549 #endif
550 }
551
EmitValue(const MCExpr * value,unsigned size,unsigned addrSpace) const552 void StreamEmitter::EmitValue(const MCExpr* value, unsigned size, unsigned addrSpace) const
553 {
554
555 #if LLVM_VERSION_MAJOR <= 10
556 m_pMCStreamer->EmitValue(value, size);
557 #else
558 m_pMCStreamer->emitValue(value, size);
559 #endif
560 }
561
EmitIntValue(uint64_t value,unsigned size,unsigned addrSpace) const562 void StreamEmitter::EmitIntValue(uint64_t value, unsigned size, unsigned addrSpace) const
563 {
564 #if LLVM_VERSION_MAJOR <= 10
565 m_pMCStreamer->EmitIntValue(value, size);
566 #else
567 m_pMCStreamer->emitIntValue(value, size);
568 #endif
569 }
570
EmitInt8(int value) const571 void StreamEmitter::EmitInt8(int value) const
572 {
573 EmitIntValue(value, 1);
574 }
575
EmitInt16(int value) const576 void StreamEmitter::EmitInt16(int value) const
577 {
578 EmitIntValue(value, 2);
579 }
580
EmitInt32(int value) const581 void StreamEmitter::EmitInt32(int value) const
582 {
583 EmitIntValue(value, 4);
584 }
585
EmitSLEB128(int64_t value,const char *) const586 void StreamEmitter::EmitSLEB128(int64_t value, const char* /*desc*/) const
587 {
588 #if LLVM_VERSION_MAJOR <= 10
589 m_pMCStreamer->EmitSLEB128IntValue(value);
590 #else
591 m_pMCStreamer->emitSLEB128IntValue(value);
592 #endif
593 }
594
EmitULEB128(uint64_t value,llvm::StringRef,unsigned padTo) const595 void StreamEmitter::EmitULEB128(uint64_t value, llvm::StringRef /*desc*/, unsigned padTo) const
596 {
597 #if LLVM_VERSION_MAJOR <= 10
598 m_pMCStreamer->EmitULEB128IntValue(value);
599 #else
600 m_pMCStreamer->emitULEB128IntValue(value);
601 #endif
602 }
603
EmitLabel(MCSymbol * pLabel) const604 void StreamEmitter::EmitLabel(MCSymbol* pLabel) const
605 {
606 #if LLVM_VERSION_MAJOR <= 10
607 m_pMCStreamer->EmitLabel(pLabel);
608 #else
609 m_pMCStreamer->emitLabel(pLabel);
610 #endif
611 }
612
EmitLabelDifference(const MCSymbol * pHi,const MCSymbol * pLo,unsigned size) const613 void StreamEmitter::EmitLabelDifference(const MCSymbol* pHi, const MCSymbol* pLo, unsigned size) const
614 {
615 const MCExpr* hiExpr = MCSymbolRefExpr::create(pHi, *m_pContext);
616 const MCExpr* loExpr = MCSymbolRefExpr::create(pLo, *m_pContext);
617
618 // Get the pHi-pLo expression.
619 const MCExpr* pDiff = MCBinaryExpr::createSub(hiExpr, loExpr, *m_pContext);
620
621 if (!m_pAsmInfo->doesSetDirectiveSuppressReloc())
622 {
623 #if LLVM_VERSION_MAJOR <= 10
624 m_pMCStreamer->EmitValue(pDiff, size);
625 #else
626 m_pMCStreamer->emitValue(pDiff, size);
627 #endif
628 return;
629 }
630
631 // Otherwise, emit with .set (aka assignment).
632 MCSymbol* pSetLabel = GetTempSymbol("set", m_setCounter++);
633
634 #if LLVM_VERSION_MAJOR <= 10
635 m_pMCStreamer->EmitAssignment(pSetLabel, pDiff);
636 #else
637 m_pMCStreamer->emitAssignment(pSetLabel, pDiff);
638 #endif
639
640 #if LLVM_VERSION_MAJOR <= 10
641 m_pMCStreamer->EmitSymbolValue(pSetLabel, size);
642 #else
643 m_pMCStreamer->emitSymbolValue(pSetLabel, size);
644 #endif
645 }
646
EmitLabelOffsetDifference(const MCSymbol * pHi,uint64_t Offset,const MCSymbol * pLo,unsigned size) const647 void StreamEmitter::EmitLabelOffsetDifference(const MCSymbol* pHi, uint64_t Offset, const MCSymbol* pLo, unsigned size) const
648 {
649 const MCExpr* pHiExpr = MCSymbolRefExpr::create(pHi, *m_pContext);
650 const MCExpr* pLoExpr = MCSymbolRefExpr::create(pLo, *m_pContext);
651 const MCExpr* pOffsetExpr = MCConstantExpr::create(Offset, *m_pContext);
652
653 // Emit pHi+Offset - pLo
654 // Get the pHi+Offset expression.
655 const MCExpr* pPlus = MCBinaryExpr::createAdd(pHiExpr, pOffsetExpr, *m_pContext);
656
657 // Get the pHi+Offset-pLo expression.
658 const MCExpr* pDiff = MCBinaryExpr::createSub(pPlus, pLoExpr, *m_pContext);
659
660 if (!m_pAsmInfo->doesSetDirectiveSuppressReloc())
661 {
662 #if LLVM_VERSION_MAJOR <= 10
663 m_pMCStreamer->EmitValue(pDiff, size);
664 #else
665 m_pMCStreamer->emitValue(pDiff, size);
666 #endif
667 return;
668 }
669 // Otherwise, emit with .set (aka assignment).
670 MCSymbol* pSetLabel = GetTempSymbol("set", m_setCounter++);
671
672 #if LLVM_VERSION_MAJOR <= 10
673 m_pMCStreamer->EmitAssignment(pSetLabel, pDiff);
674 #else
675 m_pMCStreamer->emitAssignment(pSetLabel, pDiff);
676 #endif
677
678 #if LLVM_VERSION_MAJOR <= 10
679 m_pMCStreamer->EmitSymbolValue(pSetLabel, size);
680 #else
681 m_pMCStreamer->emitSymbolValue(pSetLabel, size);
682 #endif
683 }
684
EmitLabelPlusOffset(const MCSymbol * pLabel,uint64_t Offset,unsigned size,bool) const685 void StreamEmitter::EmitLabelPlusOffset(const MCSymbol* pLabel, uint64_t Offset, unsigned size, bool /*isSectionRelative*/) const
686 {
687 // Emit pLabel+Offset (or just pLabel if Offset is zero)
688 const MCExpr* pLabelExpr = MCSymbolRefExpr::create(pLabel, *m_pContext);
689 const MCExpr* pOffsetExpr = MCConstantExpr::create(Offset, *m_pContext);
690
691 const MCExpr* pExpr = (Offset) ? MCBinaryExpr::createAdd(pLabelExpr, pOffsetExpr, *m_pContext) : pLabelExpr;
692
693 #if LLVM_VERSION_MAJOR <= 10
694 m_pMCStreamer->EmitValue(pExpr, size);
695 #else
696 m_pMCStreamer->emitValue(pExpr, size);
697 #endif
698 }
699
EmitLabelReference(const MCSymbol * pLabel,unsigned size,bool isSectionRelative) const700 void StreamEmitter::EmitLabelReference(const MCSymbol* pLabel, unsigned size, bool isSectionRelative) const
701 {
702 EmitLabelPlusOffset(pLabel, 0, size, isSectionRelative);
703 }
704
EmitELFDiffSize(MCSymbol * pLabel,const MCSymbol * pHi,const MCSymbol * pLo) const705 void StreamEmitter::EmitELFDiffSize(MCSymbol* pLabel, const MCSymbol* pHi, const MCSymbol* pLo) const
706 {
707 const MCExpr* hiExpr = MCSymbolRefExpr::create(pHi, *m_pContext);
708 const MCExpr* loExpr = MCSymbolRefExpr::create(pLo, *m_pContext);
709
710 // Get the pHi-pLo expression.
711 const MCExpr* pDiff = MCBinaryExpr::createSub(hiExpr, loExpr, *m_pContext);
712
713 m_pMCStreamer->emitELFSize(pLabel, pDiff);
714 }
715
EmitSymbolValue(const MCSymbol * pSym,unsigned size,unsigned addrSpace) const716 void StreamEmitter::EmitSymbolValue(const MCSymbol* pSym, unsigned size, unsigned addrSpace) const
717 {
718 #if LLVM_VERSION_MAJOR <= 10
719 m_pMCStreamer->EmitSymbolValue(pSym, size);
720 #else
721 m_pMCStreamer->emitSymbolValue(pSym, size);
722 #endif
723 }
724
EmitSectionOffset(const MCSymbol * pLabel,const MCSymbol * pSectionLabel) const725 void StreamEmitter::EmitSectionOffset(const MCSymbol* pLabel, const MCSymbol* pSectionLabel) const
726 {
727 // Get the section that we're referring to, based on pSectionLabel.
728 const MCSection& section = pSectionLabel->getSection();
729
730 // If pLabel has already been emitted, verify that it is in the same section as
731 // section label for sanity.
732 IGC_ASSERT_MESSAGE((!pLabel->isInSection() || &pLabel->getSection() == §ion), "section offset using wrong section base for label");
733
734 // If the section in question will end up with an address of 0 anyway, we can
735 // just emit an absolute reference to save a relocation.
736 #if 0
737 if (section.isBaseAddressKnownZero())
738 {
739 m_pMCStreamer->EmitSymbolValue(pLabel, 4);
740 return;
741 }
742 #endif
743
744 // Otherwise, emit it as a label difference from the start of the section.
745 EmitLabelDifference(pLabel, pSectionLabel, 4);
746 }
747
EmitDwarfRegOp(unsigned reg,unsigned offset,bool indirect) const748 void StreamEmitter::EmitDwarfRegOp(unsigned reg, unsigned offset, bool indirect) const
749 {
750 auto regEncoded = GetEncodedRegNum<RegisterNumbering::GRFBase>(reg);
751 if (indirect)
752 {
753 if (regEncoded < 32)
754 {
755 EmitInt8(dwarf::DW_OP_breg0 + regEncoded);
756 }
757 else
758 {
759 // Emit ("DW_OP_bregx");
760 EmitInt8(dwarf::DW_OP_bregx);
761 EmitULEB128(regEncoded);
762 }
763 EmitSLEB128(offset);
764 }
765 else
766 {
767 if (regEncoded < 32)
768 {
769 EmitInt8(dwarf::DW_OP_reg0 + regEncoded);
770 }
771 else
772 {
773 // Emit ("DW_OP_regx");
774 EmitInt8(dwarf::DW_OP_regx);
775 EmitULEB128(regEncoded);
776 }
777 }
778 }
779
EmitDwarfFileDirective(unsigned fileNo,StringRef directory,StringRef filename,unsigned cuID) const780 bool StreamEmitter::EmitDwarfFileDirective(unsigned fileNo, StringRef directory, StringRef filename, unsigned cuID) const
781 {
782 #if LLVM_VERSION_MAJOR <= 10
783 return (m_pMCStreamer->EmitDwarfFileDirective(fileNo, directory, filename, llvm::None, llvm::None, cuID) != 0);
784 #else
785 return (m_pMCStreamer->emitDwarfFileDirective(fileNo, directory, filename, llvm::None, llvm::None, cuID) != 0);
786 #endif
787 }
788
EmitDwarfLocDirective(unsigned fileNo,unsigned line,unsigned column,unsigned flags,unsigned isa,unsigned discriminator,StringRef fileName) const789 void StreamEmitter::EmitDwarfLocDirective(unsigned fileNo, unsigned line, unsigned column, unsigned flags,
790 unsigned isa, unsigned discriminator, StringRef fileName) const
791 {
792 #if LLVM_VERSION_MAJOR <= 10
793 m_pMCStreamer->EmitDwarfLocDirective(fileNo, line, column, flags, isa, discriminator, fileName);
794 #else
795 m_pMCStreamer->emitDwarfLocDirective(fileNo, line, column, flags, isa, discriminator, fileName);
796 #endif
797 }
798
SetMCLineTableSymbol(MCSymbol * pSym,unsigned id) const799 void StreamEmitter::SetMCLineTableSymbol(MCSymbol* pSym, unsigned id) const
800 {
801 // m_pContext->setMCLineTableSymbol(pSym, id);
802 }
803
Finalize() const804 void StreamEmitter::Finalize() const
805 {
806 m_pMCStreamer->Finish();
807 m_pMCStreamer->reset();
808 }
809
GetObjFileLowering() const810 const MCObjectFileInfo& StreamEmitter::GetObjFileLowering() const
811 {
812 IGC_ASSERT_MESSAGE(m_pObjFileInfo, "Object File Lowering was not initialized");
813 return *m_pObjFileInfo;
814 }
815
verifyRegisterLocationSize(const IGC::DbgVariable & VarVal,const IGC::DwarfDebug & DD,unsigned MaxGRFSpaceInBits,uint64_t ExpectedSize)816 void StreamEmitter::verifyRegisterLocationSize(const IGC::DbgVariable& VarVal,
817 const IGC::DwarfDebug& DD,
818 unsigned MaxGRFSpaceInBits,
819 uint64_t ExpectedSize)
820 {
821 if (!GetEmitterSettings().EnableDebugInfoValidation)
822 return;
823
824 auto* DbgInst = VarVal.getDbgInst();
825 IGC_ASSERT(DbgInst);
826 Value* IRLoc = IGCLLVM::getVariableLocation(DbgInst);
827 auto* Ty = IRLoc->getType();
828 IGC_ASSERT(Ty->isSingleValueType());
829
830 if (Ty->isPointerTy())
831 return; // no validation for pointers (for now)
832
833 auto* Expr = DbgInst->getExpression();
834 if (Expr->isFragment() || Expr->isImplicit())
835 {
836 // TODO: implement some sanity checks
837 return;
838 }
839 DiagnosticBuff Diag;
840 auto DwarfTypeSize = VarVal.getBasicSize(&DD);
841 if (DwarfTypeSize != ExpectedSize) {
842 Diag.out() << "ValidationFailure [regLocSize] -- DWARF Type Size: " <<
843 DwarfTypeSize << ", expected: " << ExpectedSize << "\n";
844 }
845 if (ExpectedSize > MaxGRFSpaceInBits) {
846 Diag.out() << "ValidationFailure [GRFSpace] -- Available GRF space: " <<
847 MaxGRFSpaceInBits << ", while expected value size: " <<
848 ExpectedSize << "\n";
849 }
850
851 // Dump DbgVariable if errors were reported
852 verificationReport(VarVal, Diag);
853 }
854
verifyRegisterLocationExpr(const DbgVariable & DV,const DwarfDebug & DD)855 void StreamEmitter::verifyRegisterLocationExpr(const DbgVariable& DV,
856 const DwarfDebug& DD)
857 {
858 if (!GetEmitterSettings().EnableDebugInfoValidation)
859 return;
860
861 // TODO: add checks for locations other than llvm.dbg.value
862 if (DV.currentLocationIsMemoryAddress())
863 return;
864
865 auto* DbgInst = DV.getDbgInst();
866 if (!isa<llvm::DbgValueInst>(DbgInst))
867 return;
868
869 DiagnosticBuff Diag;
870 if (!DV.currentLocationIsImplicit() &&
871 !DV.currentLocationIsSimpleIndirectValue())
872 {
873 if (DbgInst->getExpression()->isComplex())
874 {
875 Diag.out() << "ValidationFailure [UnexpectedComlexExpression]" <<
876 " for a simple register location\n";
877 }
878 }
879 verificationReport(DV, Diag);
880 }
881
reportUsabilityIssue(llvm::StringRef Msg,const llvm::Value * Ctx)882 void StreamEmitter::reportUsabilityIssue(llvm::StringRef Msg,
883 const llvm::Value* Ctx)
884 {
885 if (!GetEmitterSettings().EnableDebugInfoValidation)
886 return;
887
888 DiagnosticBuff Diag;
889 Diag.out() << "ValidationFailure [UsabilityIssue] " <<
890 Msg << "\n";
891
892 if (Ctx)
893 {
894 Ctx->print(Diag.out());
895 Diag.out() << "\n";
896 }
897
898 verificationReport(Diag);
899 }
900
verificationReport(const DbgVariable & VarVal,DiagnosticBuff & Diag)901 void StreamEmitter::verificationReport(const DbgVariable& VarVal,
902 DiagnosticBuff& Diag)
903 {
904 if (Diag.out().tell() == 0)
905 return;
906
907 VarVal.print(Diag.out());
908 Diag.out() << "==============\n";
909
910 verificationReport(Diag);
911 }
912
verificationReport(DiagnosticBuff & Diag)913 void StreamEmitter::verificationReport(DiagnosticBuff& Diag)
914 {
915 if (Diag.out().tell() == 0)
916 return;
917
918 const auto& ErrMsg = Diag.out().str();
919
920 ErrorLog.append(ErrMsg);
921 LLVM_DEBUG(dbgs() << ErrMsg);
922 }
923
924