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