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 #pragma once
17 
18 #include "llvm/Config/llvm-config.h"
19 #include "common/LLVMWarningsPush.hpp"
20 #include "llvm/Support/DataTypes.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvmWrapper/MC/MCContext.h"
23 #include "llvmWrapper/MC/MCObjectFileInfo.h"
24 #include "llvm/MC/MCSection.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "common/LLVMWarningsPop.hpp"
27 
28 #include <string>
29 
30 #include "EmitterOpts.hpp"
31 
32 namespace llvm
33 {
34     class MCStreamer;
35     class SourceMgr;
36     class MCAsmInfo;
37 }
38 
39 namespace IGC
40 {
41     class DbgVariable;
42     class DwarfDebug;
43     struct VISAVariableLocation;
44 
45     /// @brief StreamEmitter provides API methods for emitting elf object.
46     ///        It will be used to emit the debug info sections in dwarf format.
47     class StreamEmitter
48     {
49     public:
50         typedef DebugEmitterOpts Settings;
51         /// @brief Constructor.
52         /// @param raw_ostream instance of raw_ostream to emit all bitcode into.
53         /// @param dataLayout data layout string.
54         /// @param targetTriple target triple string.
55         StreamEmitter(llvm::raw_pwrite_stream&, const std::string& dataLayout,
56                       const std::string& targetTriple,
57                       const Settings& EmitterOptions);
58 
59         /// @brief Destructor.
60         ~StreamEmitter();
61 
GetEmitterSettings() const62         const Settings& GetEmitterSettings() const { return StreamOptions; };
63 
64         /// @brief Get pointer size.
65         /// @return pointer size in bits.
66         unsigned int GetPointerSize() const;
67 
68         /// @brief Get endianness data stored in memory.
69         /// @return true for Little-endian, and false for Big-endian.
70         bool IsLittleEndian() const;
71 
72         /// @brief Section getter methods
73         const llvm::MCSection* GetTextSection() const;
74         const llvm::MCSection* GetDataSection() const;
75         const llvm::MCSection* GetDwarfAbbrevSection() const;
76         const llvm::MCSection* GetDwarfInfoSection() const;
77         const llvm::MCSection* GetDwarfLineSection() const;
78         const llvm::MCSection* GetDwarfLocSection() const;
79         const llvm::MCSection* GetDwarfMacroInfoSection() const;
80         const llvm::MCSection* GetDwarfRangesSection() const;
81         const llvm::MCSection* GetDwarfStrSection() const;
82         const llvm::MCSection* GetDwarfFrameSection() const;
83 
84         /// @brief Set the current section where code is being emitted to.
85         /// @param pSection section to switch to
86         /// @param pSubsection subsiction to switch to (optional)
87         void SwitchSection(const llvm::MCSection* pSection, const llvm::MCExpr* pSubsection = 0) const;
88 
89         /// @brief sympol getters
90         /// @param pGV Global Variable
91         /// @return Machine Code symbol
92         llvm::MCSymbol* GetSymbol(const llvm::GlobalValue* pGV) const;
93 
94         /// @brief Return the MCSymbol corresponding to the assembler
95         ///        temporary label with the specified stem and unique ID.
96         /// @param name symbol name
97         /// @param id symbol id
98         /// @return Machine Code symbol
99         llvm::MCSymbol* GetTempSymbol(llvm::StringRef name, uint64_t id) const;
100 
101         /// @brief Return an assembler temporary label with the specified stem.
102         /// @param name symbol name
103         /// @return Machine Code symbol
104         llvm::MCSymbol* GetTempSymbol(llvm::StringRef name) const;
105 
106         /// @brief Return an assembler temporary label with the specified stem.
107         /// @return Machine Code symbol
108         llvm::MCSymbol* CreateTempSymbol() const;
109 
110 
111         /// @brief Dwarf CU getter & setter
112         unsigned GetDwarfCompileUnitID() const;
113         void SetDwarfCompileUnitID(unsigned cuIndex) const;
114 
115         //===------------------------------------------------------------------===//
116         // Dwarf Emission Helper Routines
117         //===------------------------------------------------------------------===//
118 
119         /// @brief Emit the bytes in \p Data into the output.
120         void EmitBytes(llvm::StringRef data, unsigned addrSpace = 0) const;
121 
122         /// @brief Emit the expression @p value into the output as a native
123         ///        integer of the given @p size bytes.
124         void EmitValue(const llvm::MCExpr* pValue, unsigned size, unsigned addrSpace = 0) const;
125 
126         /// @brief Special case of EmitValue that avoids the client having
127         ///        to pass in a MCExpr for constant integers.
128         void EmitIntValue(uint64_t value, unsigned size, unsigned addrSpace = 0) const;
129 
130         /// @brief Emit a byte directive and value.
131         void EmitInt8(int value) const;
132 
133         /// @brief Emit a short directive and value.
134         void EmitInt16(int value) const;
135 
136         /// @brief Emit a long directive and value.
137         void EmitInt32(int value) const;
138 
139         /// @brief emit the specified signed leb128 value.
140         void EmitSLEB128(int64_t value, const char* pDesc = 0) const;
141 
142         /// @brief emit the specified unsigned leb128 value.
143         void EmitULEB128(uint64_t value, llvm::StringRef desc = "", unsigned padTo = 0) const;
144 
145         /// @brief Emit a label
146         void EmitLabel(llvm::MCSymbol* pLabel) const;
147 
148         /// @brief Emit something like ".long pHi-pLo" where the size in bytes
149         ///        of the directive is specified by size and pHi/pLo specify the
150         ///        labels.  This implicitly uses .set if it is available.
151         void EmitLabelDifference(const llvm::MCSymbol* pHi, const llvm::MCSymbol* pLo, unsigned size) const;
152 
153         /// @brief Emit something like ".long pHi+offset-pLo" where the size in bytes
154         ///        of the directive is specified by size and pHi/pLo specify the
155         ///        labels.  This implicitly uses .set if it is available.
156         void EmitLabelOffsetDifference(const llvm::MCSymbol* pHi, uint64_t offset, const llvm::MCSymbol* pLo, unsigned size) const;
157 
158         /// @brief Emit something like ".long pLabel+offset" where the size in bytes
159         ///        of the directive is specified by size and pLabel specifies the
160         ///        label.  This implicitly uses .set if it is available.
161         void EmitLabelPlusOffset(const llvm::MCSymbol* pLabel, uint64_t offset, unsigned size, bool isSectionRelative = false) const;
162 
163         /// @brief Emit something like ".long pLabel" where the size in bytes of the
164         ///        directive is specified by size and pLabel specifies the label.
165         void EmitLabelReference(const llvm::MCSymbol* pLabel, unsigned size, bool isSectionRelative = false) const;
166 
167         void EmitELFDiffSize(llvm::MCSymbol* pLabel, const llvm::MCSymbol* pHi, const llvm::MCSymbol* pLo) const;
168 
169         /// @brief Special case of EmitValue that avoids the client
170         ///        having to pass in a MCExpr for MCSymbols.
171         void EmitSymbolValue(const llvm::MCSymbol* pSym, unsigned size, unsigned addrSpace = 0) const;
172 
173         /// @brief Emit the 4-byte offset of pLabel from the start of its section.
174         ///        This can be done with a special directive if the target supports
175         ///        it (e.g. cygwin) or by emitting it as an offset from a label at
176         ///        the start of the section.
177         ///
178         ///        SectionLabel is a temporary label emitted at the start of the
179         ///        section that pLabel lives in.
180         void EmitSectionOffset(const llvm::MCSymbol* pLabel, const llvm::MCSymbol* pSectionLabel) const;
181 
182         /// @brief Emit dwarf register operation.
183         void EmitDwarfRegOp(unsigned reg, unsigned offset = 0, bool indirect = 0) const;
184 
185         /// @brief Associate a filename with a specified logical file number.
186         ///        This implements the DWARF2 '.file 4 "foo.c"' assembler directive.
187         bool EmitDwarfFileDirective(unsigned fileNo, llvm::StringRef directory, llvm::StringRef filename, unsigned cuID = 0) const;
188 
189         /// @brief This implements the DWARF2 '.loc fileno lineno ...' assembler directive.
190         void EmitDwarfLocDirective(unsigned fileNo, unsigned line, unsigned column, unsigned flags,
191             unsigned isa, unsigned discriminator, llvm::StringRef fileName) const;
192 
193         /// @brief Maps given line table symbol to given ID
194         void SetMCLineTableSymbol(llvm::MCSymbol* pSym, unsigned id) const;
195 
196         /// @brief Finalize the streamer, flush all written bytes.
197         void Finalize() const;
198 
getErrors() const199         const std::string& getErrors() const { return ErrorLog; }
200 
201         void reportUsabilityIssue(llvm::StringRef Msg,
202                                   const llvm::Value* Ctx = nullptr);
203         void verifyRegisterLocationSize(const DbgVariable& VarVal,
204                                         const DwarfDebug& DD,
205                                         unsigned MaxGRFSpaceInBits,
206                                         uint64_t ExpectedSize);
207         void verifyRegisterLocationExpr(const DbgVariable& VarVal,
208                                         const DwarfDebug& DD);
209 
210     private:
211 
212         class DiagnosticBuff
213         {
214             std::string Buff;
215             llvm::raw_string_ostream OS;
216         public:
DiagnosticBuff()217             DiagnosticBuff(): OS(Buff) {}
out()218             llvm::raw_string_ostream &out() { return OS; }
219         };
220 
221         void verificationReport(const DbgVariable& VarVal,
222                                 DiagnosticBuff& DiagBuff);
223         void verificationReport(DiagnosticBuff& DiagBuff);
224 
225         /// @brief Return information about object file lowering.
226         const llvm::MCObjectFileInfo& GetObjFileLowering() const;
227 
228         /// @brief Return the target triple string.
GetTargetTriple() const229         const std::string& GetTargetTriple() const { return m_targetTriple; }
230 
231     private:
232 
233         llvm::MCStreamer* m_pMCStreamer;
234         llvm::MCContext* m_pContext;
235         llvm::SourceMgr* m_pSrcMgr;
236         llvm::MCAsmInfo* m_pAsmInfo;
237         IGCLLVM::MCObjectFileInfo* m_pObjFileInfo;
238         const llvm::DataLayout* m_pDataLayout;
239         const std::string& m_targetTriple;
240         Settings StreamOptions;
241         std::string ErrorLog;
242 
243         mutable unsigned int m_setCounter;
244     };
245 
246 } // namespace IGC
247