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