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() == &section), "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