1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-21 03:53:04 +02:00
llvm-mirror/include/llvm/MC/MCCodeView.h
David Majnemer 4bcb5f2151 [MC] Add support for encoding CodeView variable definition ranges
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
2016-02-05 01:55:49 +00:00

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