mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-21 03:53:04 +02:00
4bcb5f2151
CodeView, like most other debug formats, represents the live range of a variable so that debuggers might print them out. They use a variety of records to represent how a particular variable might be available (in a register, in a frame pointer, etc.) along with a set of ranges where this debug information is relevant. However, the format only allows us to use ranges which are limited to a maximum of 0xF000 in size. This means that we need to split our debug information into chunks of 0xF000. Because the layout of code is not known until *very* late, we must use a new fragment to record the information we need until we can know *exactly* what the range is. llvm-svn: 259868
211 lines
6.7 KiB
C++
211 lines
6.7 KiB
C++
//===- MCCodeView.h - Machine Code CodeView support -------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Holds state from .cv_file and .cv_loc directives for later emission.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_MC_MCCODEVIEW_H
|
|
#define LLVM_MC_MCCODEVIEW_H
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/MC/MCObjectStreamer.h"
|
|
#include "llvm/MC/MCFragment.h"
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
namespace llvm {
|
|
class MCContext;
|
|
class MCObjectStreamer;
|
|
class MCStreamer;
|
|
|
|
/// \brief Instances of this class represent the information from a
|
|
/// .cv_loc directive.
|
|
class MCCVLoc {
|
|
uint32_t FunctionId;
|
|
uint32_t FileNum;
|
|
uint32_t Line;
|
|
uint16_t Column;
|
|
uint16_t PrologueEnd : 1;
|
|
uint16_t IsStmt : 1;
|
|
|
|
private: // MCContext manages these
|
|
friend class MCContext;
|
|
MCCVLoc(unsigned functionid, unsigned fileNum, unsigned line, unsigned column,
|
|
bool prologueend, bool isstmt)
|
|
: FunctionId(functionid), FileNum(fileNum), Line(line), Column(column),
|
|
PrologueEnd(prologueend), IsStmt(isstmt) {}
|
|
|
|
// Allow the default copy constructor and assignment operator to be used
|
|
// for an MCCVLoc object.
|
|
|
|
public:
|
|
unsigned getFunctionId() const { return FunctionId; }
|
|
|
|
/// \brief Get the FileNum of this MCCVLoc.
|
|
unsigned getFileNum() const { return FileNum; }
|
|
|
|
/// \brief Get the Line of this MCCVLoc.
|
|
unsigned getLine() const { return Line; }
|
|
|
|
/// \brief Get the Column of this MCCVLoc.
|
|
unsigned getColumn() const { return Column; }
|
|
|
|
bool isPrologueEnd() const { return PrologueEnd; }
|
|
bool isStmt() const { return IsStmt; }
|
|
|
|
void setFunctionId(unsigned FID) { FunctionId = FID; }
|
|
|
|
/// \brief Set the FileNum of this MCCVLoc.
|
|
void setFileNum(unsigned fileNum) { FileNum = fileNum; }
|
|
|
|
/// \brief Set the Line of this MCCVLoc.
|
|
void setLine(unsigned line) { Line = line; }
|
|
|
|
/// \brief Set the Column of this MCCVLoc.
|
|
void setColumn(unsigned column) {
|
|
assert(column <= UINT16_MAX);
|
|
Column = column;
|
|
}
|
|
|
|
void setPrologueEnd(bool PE) { PrologueEnd = PE; }
|
|
void setIsStmt(bool IS) { IsStmt = IS; }
|
|
};
|
|
|
|
/// \brief Instances of this class represent the line information for
|
|
/// the CodeView line table entries. Which is created after a machine
|
|
/// instruction is assembled and uses an address from a temporary label
|
|
/// created at the current address in the current section and the info from
|
|
/// the last .cv_loc directive seen as stored in the context.
|
|
class MCCVLineEntry : public MCCVLoc {
|
|
const MCSymbol *Label;
|
|
|
|
private:
|
|
// Allow the default copy constructor and assignment operator to be used
|
|
// for an MCCVLineEntry object.
|
|
|
|
public:
|
|
// Constructor to create an MCCVLineEntry given a symbol and the dwarf loc.
|
|
MCCVLineEntry(const MCSymbol *Label, const MCCVLoc loc)
|
|
: MCCVLoc(loc), Label(Label) {}
|
|
|
|
const MCSymbol *getLabel() const { return Label; }
|
|
|
|
// This is called when an instruction is assembled into the specified
|
|
// section and if there is information from the last .cv_loc directive that
|
|
// has yet to have a line entry made for it is made.
|
|
static void Make(MCObjectStreamer *MCOS);
|
|
};
|
|
|
|
/// Holds state from .cv_file and .cv_loc directives for later emission.
|
|
class CodeViewContext {
|
|
public:
|
|
CodeViewContext();
|
|
~CodeViewContext();
|
|
|
|
bool isValidFileNumber(unsigned FileNumber) const;
|
|
bool addFile(unsigned FileNumber, StringRef Filename);
|
|
ArrayRef<StringRef> getFilenames() { return Filenames; }
|
|
|
|
/// \brief Add a line entry.
|
|
void addLineEntry(const MCCVLineEntry &LineEntry) {
|
|
size_t Offset = MCCVLines.size();
|
|
auto I = MCCVLineStartStop.insert(
|
|
{LineEntry.getFunctionId(), {Offset, Offset + 1}});
|
|
if (!I.second)
|
|
I.first->second.second = Offset + 1;
|
|
MCCVLines.push_back(LineEntry);
|
|
}
|
|
|
|
std::vector<MCCVLineEntry> getFunctionLineEntries(unsigned FuncId) {
|
|
std::vector<MCCVLineEntry> FilteredLines;
|
|
|
|
auto I = MCCVLineStartStop.find(FuncId);
|
|
if (I != MCCVLineStartStop.end())
|
|
for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
|
|
++Idx)
|
|
if (MCCVLines[Idx].getFunctionId() == FuncId)
|
|
FilteredLines.push_back(MCCVLines[Idx]);
|
|
return FilteredLines;
|
|
}
|
|
|
|
std::pair<size_t, size_t> getLineExtent(unsigned FuncId) {
|
|
auto I = MCCVLineStartStop.find(FuncId);
|
|
// Return an empty extent if there are no cv_locs for this function id.
|
|
if (I == MCCVLineStartStop.end())
|
|
return {~0ULL, 0};
|
|
return I->second;
|
|
}
|
|
|
|
ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) {
|
|
if (R <= L)
|
|
return None;
|
|
if (L >= MCCVLines.size())
|
|
return None;
|
|
return makeArrayRef(&MCCVLines[L], R - L);
|
|
}
|
|
|
|
/// Emits a line table substream.
|
|
void emitLineTableForFunction(MCObjectStreamer &OS, unsigned FuncId,
|
|
const MCSymbol *FuncBegin,
|
|
const MCSymbol *FuncEnd);
|
|
|
|
void emitInlineLineTableForFunction(
|
|
MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
|
|
unsigned SourceLineNum, const MCSymbol *FnStartSym,
|
|
const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds);
|
|
|
|
/// Encodes the binary annotations once we have a layout.
|
|
void encodeInlineLineTable(MCAsmLayout &Layout,
|
|
MCCVInlineLineTableFragment &F);
|
|
|
|
void
|
|
emitDefRange(MCObjectStreamer &OS,
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
|
StringRef FixedSizePortion);
|
|
|
|
void encodeDefRange(MCAsmLayout &Layout, MCCVDefRangeFragment &F);
|
|
|
|
/// Emits the string table substream.
|
|
void emitStringTable(MCObjectStreamer &OS);
|
|
|
|
/// Emits the file checksum substream.
|
|
void emitFileChecksums(MCObjectStreamer &OS);
|
|
|
|
private:
|
|
/// Map from string to string table offset.
|
|
StringMap<unsigned> StringTable;
|
|
|
|
/// The fragment that ultimately holds our strings.
|
|
MCDataFragment *StrTabFragment = nullptr;
|
|
bool InsertedStrTabFragment = false;
|
|
|
|
MCDataFragment *getStringTableFragment();
|
|
|
|
/// Add something to the string table.
|
|
StringRef addToStringTable(StringRef S);
|
|
|
|
/// Get a string table offset.
|
|
unsigned getStringTableOffset(StringRef S);
|
|
|
|
/// An array of absolute paths. Eventually this may include the file checksum.
|
|
SmallVector<StringRef, 4> Filenames;
|
|
|
|
/// The offset of the first and last .cv_loc directive for a given function
|
|
/// id.
|
|
std::map<unsigned, std::pair<size_t, size_t>> MCCVLineStartStop;
|
|
|
|
/// A collection of MCCVLineEntry for each section.
|
|
std::vector<MCCVLineEntry> MCCVLines;
|
|
};
|
|
|
|
} // end namespace llvm
|
|
#endif
|