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
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2023 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "DwarfDebug.hpp"
#include "StreamEmitter.hpp"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include <cassert>
#include <cstdint>
#include <iterator>
#include <optional>
using namespace llvm;
namespace IGC {
/// Holds a DIExpression and keeps track of how many operands have been consumed
/// so far.
class DIExpressionCursor {
DIExpression::expr_op_iterator Start, End;
public:
DIExpressionCursor(const DIExpression *Expr) {
if (!Expr) {
assert(Start == End);
return;
}
Start = Expr->expr_op_begin();
End = Expr->expr_op_end();
}
DIExpressionCursor(ArrayRef<uint64_t> Expr) : Start(Expr.begin()), End(Expr.end()) {}
DIExpressionCursor(const DIExpressionCursor &) = default;
/// Consume one operation.
std::optional<DIExpression::ExprOperand> take() {
if (Start == End)
return std::nullopt;
return *(Start++);
}
/// Consume N operations.
void consume(unsigned N) { std::advance(Start, N); }
/// Return the current operation.
std::optional<DIExpression::ExprOperand> peek() const {
if (Start == End)
return std::nullopt;
return *(Start);
}
/// Return the next operation.
std::optional<DIExpression::ExprOperand> peekNext() const {
if (Start == End)
return std::nullopt;
auto Next = Start.getNext();
if (Next == End)
return std::nullopt;
return *Next;
}
/// Determine whether there are any operations left in this expression.
operator bool() const { return Start != End; }
DIExpression::expr_op_iterator begin() const { return Start; }
DIExpression::expr_op_iterator end() const { return End; }
/// Retrieve the fragment information, if any.
Optional<DIExpression::FragmentInfo> getFragmentInfo() const { return DIExpression::getFragmentInfo(Start, End); }
};
class DwarfExpression {
protected:
CompileUnit &CU;
/// Output a dwarf operand and an optional assembler comment.
virtual void emitOp(uint8_t Op, const char *Comment = nullptr) = 0;
/// Emit a raw signed value.
virtual void emitSigned(int64_t Value) = 0;
/// Emit a raw unsigned value.
virtual void emitUnsigned(uint64_t Value) = 0;
virtual void emitData1(uint8_t Value) = 0;
/// Emit a normalized unsigned constant.
void emitConstu(uint64_t Value);
public:
DwarfExpression(CompileUnit &CU) : CU(CU) {};
/// This needs to be called last to commit any pending changes.
void finalize();
/// Emit all remaining operations in the DIExpressionCursor. The
/// cursor must not contain any DW_OP_LLVM_arg operations.
void addExpression(DIExpressionCursor &&Expr);
/// Emit all remaining operations in the DIExpressionCursor.
/// DW_OP_LLVM_arg operations are resolved by calling (\p InsertArg).
//
/// \return false if any call to (\p InsertArg) returns false.
bool addExpression(DIExpressionCursor &&Expr, llvm::function_ref<bool(unsigned, DIExpressionCursor &)> InsertArg);
~DwarfExpression() = default;
};
class DIEDwarfExpression final : public DwarfExpression {
const StreamEmitter &AP;
DIEBlock &OutDIE;
DIEBlock TmpDIE;
bool IsBuffering = false;
/// Return the DIE that currently is being emitted to.
DIEBlock &getActiveDIE() { return IsBuffering ? TmpDIE : OutDIE; }
void emitOp(uint8_t Op, const char *Comment = nullptr) override;
void emitSigned(int64_t Value) override;
void emitUnsigned(uint64_t Value) override;
void emitData1(uint8_t Value) override;
public:
DIEDwarfExpression(const StreamEmitter &AP, CompileUnit &CU, DIEBlock &DIE);
DIEBlock *finalize() {
DwarfExpression::finalize();
return &OutDIE;
}
};
} // namespace IGC
|