39 changes: 39 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/CodeViewOStream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//===- CodeViewOStream.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_CODEVIEWOSTREAM_H
#define LLVM_DEBUGINFO_CODEVIEW_CODEVIEWOSTREAM_H

#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"

namespace llvm {
namespace codeview {

template <typename Writer> class CodeViewOStream {
private:
CodeViewOStream(const CodeViewOStream &) = delete;
CodeViewOStream &operator=(const CodeViewOStream &) = delete;

public:
typedef typename Writer::LabelType LabelType;

public:
explicit CodeViewOStream(Writer &W);

private:
uint64_t size() const { return W.tell(); }

private:
Writer &W;
};
}
}

#endif
78 changes: 78 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===- FieldListRecordBuilder.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_FIELDLISTRECORDBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_FIELDLISTRECORDBUILDER_H

#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"

namespace llvm {
namespace codeview {

class MethodInfo {
public:
MethodInfo() : Access(), Kind(), Options(), Type(), VTableSlotOffset(-1) {}

MethodInfo(MemberAccess Access, MethodKind Kind, MethodOptions Options,
TypeIndex Type, int32_t VTableSlotOffset)
: Access(Access), Kind(Kind), Options(Options), Type(Type),
VTableSlotOffset(VTableSlotOffset) {}

MemberAccess getAccess() const { return Access; }
MethodKind getKind() const { return Kind; }
MethodOptions getOptions() const { return Options; }
TypeIndex getType() const { return Type; }
int32_t getVTableSlotOffset() const { return VTableSlotOffset; }

private:
MemberAccess Access;
MethodKind Kind;
MethodOptions Options;
TypeIndex Type;
int32_t VTableSlotOffset;
};

class FieldListRecordBuilder : public ListRecordBuilder {
private:
FieldListRecordBuilder(const FieldListRecordBuilder &) = delete;
void operator=(const FieldListRecordBuilder &) = delete;

public:
FieldListRecordBuilder();

void writeBaseClass(MemberAccess Access, TypeIndex Type, uint64_t Offset);
void writeEnumerate(MemberAccess Access, uint64_t Value, StringRef Name);
void writeIndirectVirtualBaseClass(MemberAccess Access, TypeIndex Type,
TypeIndex VirtualBasePointerType,
int64_t VirtualBasePointerOffset,
uint64_t SlotIndex);
void writeMember(MemberAccess Access, TypeIndex Type, uint64_t Offset,
StringRef Name);
void writeOneMethod(MemberAccess Access, MethodKind Kind,
MethodOptions Options, TypeIndex Type,
int32_t VTableSlotOffset, StringRef Name);
void writeOneMethod(const MethodInfo &Method, StringRef Name);
void writeMethod(uint16_t OverloadCount, TypeIndex MethodList,
StringRef Name);
void writeNestedType(TypeIndex Type, StringRef Name);
void writeStaticMember(MemberAccess Access, TypeIndex Type, StringRef Name);
void writeVirtualBaseClass(MemberAccess Access, TypeIndex Type,
TypeIndex VirtualBasePointerType,
int64_t VirtualBasePointerOffset,
uint64_t SlotIndex);
void writeVirtualBaseClass(TypeRecordKind Kind, MemberAccess Access,
TypeIndex Type, TypeIndex VirtualBasePointerType,
int64_t VirtualBasePointerOffset,
uint64_t SlotIndex);
void writeVirtualFunctionTablePointer(TypeIndex Type);
};
}
}

#endif
56 changes: 56 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/FunctionId.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//===- FunctionId.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_FUNCTIONID_H
#define LLVM_DEBUGINFO_CODEVIEW_FUNCTIONID_H

#include <cinttypes>

namespace llvm {
namespace codeview {

class FunctionId {
public:
FunctionId() : Index(0) {}

explicit FunctionId(uint32_t Index) : Index(Index) {}

uint32_t getIndex() const { return Index; }

private:
uint32_t Index;
};

inline bool operator==(const FunctionId &A, const FunctionId &B) {
return A.getIndex() == B.getIndex();
}

inline bool operator!=(const FunctionId &A, const FunctionId &B) {
return A.getIndex() != B.getIndex();
}

inline bool operator<(const FunctionId &A, const FunctionId &B) {
return A.getIndex() < B.getIndex();
}

inline bool operator<=(const FunctionId &A, const FunctionId &B) {
return A.getIndex() <= B.getIndex();
}

inline bool operator>(const FunctionId &A, const FunctionId &B) {
return A.getIndex() > B.getIndex();
}

inline bool operator>=(const FunctionId &A, const FunctionId &B) {
return A.getIndex() >= B.getIndex();
}
}
}

#endif
124 changes: 124 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/Line.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//===- Line.h ---------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_LINE_H
#define LLVM_DEBUGINFO_CODEVIEW_LINE_H

#include <cinttypes>

namespace llvm {
namespace codeview {

class LineInfo {
public:
static const int32_t AlwaysStepIntoLineNumber = 0xfeefee;
static const int32_t NeverStepIntoLineNumber = 0xf00f00;

private:
static const uint32_t StartLineMask = 0x00ffffff;
static const uint32_t EndLineDeltaMask = 0x7f000000;
static const int EndLineDeltaShift = 24;
static const uint32_t StatementFlag = 0x80000000u;

public:
LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement);

uint32_t getStartLine() const { return LineData & StartLineMask; }

uint32_t getLineDelta() const {
return (LineData & EndLineDeltaMask) >> EndLineDeltaShift;
}

uint32_t getEndLine() const { return getStartLine() + getLineDelta(); }

bool isStatement() const { return (LineData & StatementFlag) != 0; }

uint32_t getRawData() const { return LineData; }

bool isAlwaysStepInto() const {
return getStartLine() == AlwaysStepIntoLineNumber;
}

bool isNeverStepInto() const {
return getStartLine() == NeverStepIntoLineNumber;
}

private:
uint32_t LineData;
};

class ColumnInfo {
private:
static const uint32_t StartColumnMask = 0x0000ffffu;
static const uint32_t EndColumnMask = 0xffff0000u;
static const int EndColumnShift = 16;

public:
ColumnInfo(uint16_t StartColumn, uint16_t EndColumn) {
ColumnData =
(static_cast<uint32_t>(StartColumn) & StartColumnMask) |
((static_cast<uint32_t>(EndColumn) << EndColumnShift) & EndColumnMask);
}

uint16_t getStartColumn() const {
return static_cast<uint16_t>(ColumnData & StartColumnMask);
}

uint16_t getEndColumn() const {
return static_cast<uint16_t>((ColumnData & EndColumnMask) >>
EndColumnShift);
}

uint32_t getRawData() const { return ColumnData; }

private:
uint32_t ColumnData;
};

class Line {
private:
int32_t CodeOffset;
LineInfo LineInf;
ColumnInfo ColumnInf;

public:
Line(int32_t CodeOffset, uint32_t StartLine, uint32_t EndLine,
uint16_t StartColumn, uint16_t EndColumn, bool IsStatement)
: CodeOffset(CodeOffset), LineInf(StartLine, EndLine, IsStatement),
ColumnInf(StartColumn, EndColumn) {}

Line(int32_t CodeOffset, LineInfo LineInf, ColumnInfo ColumnInf)
: CodeOffset(CodeOffset), LineInf(LineInf), ColumnInf(ColumnInf) {}

LineInfo getLineInfo() const { return LineInf; }

ColumnInfo getColumnInfo() const { return ColumnInf; }

int32_t getCodeOffset() const { return CodeOffset; }

uint32_t getStartLine() const { return LineInf.getStartLine(); }

uint32_t getLineDelta() const { return LineInf.getLineDelta(); }

uint32_t getEndLine() const { return LineInf.getEndLine(); }

uint16_t getStartColumn() const { return ColumnInf.getStartColumn(); }

uint16_t getEndColumn() const { return ColumnInf.getEndColumn(); }

bool isStatement() const { return LineInf.isStatement(); }

bool isAlwaysStepInto() const { return LineInf.isAlwaysStepInto(); }

bool isNeverStepInto() const { return LineInf.isNeverStepInto(); }
};
}
}

#endif
43 changes: 43 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===- ListRecordBuilder.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_LISTRECORDBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_LISTRECORDBUILDER_H

#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"

namespace llvm {
namespace codeview {

class ListRecordBuilder {
private:
ListRecordBuilder(const ListRecordBuilder &) = delete;
ListRecordBuilder &operator=(const ListRecordBuilder &) = delete;

protected:
const int MethodKindShift = 2;

explicit ListRecordBuilder(TypeRecordKind Kind);

public:
llvm::StringRef str() { return Builder.str(); }

protected:
void finishSubRecord();

TypeRecordBuilder &getBuilder() { return Builder; }

private:
TypeRecordBuilder Builder;
SmallVector<size_t, 4> ContinuationOffsets;
};
}
}

#endif
68 changes: 68 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//===- MemoryTypeTableBuilder.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_MEMORYTYPETABLEBUILDER_H

#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include <functional>
#include <memory>
#include <unordered_map>
#include <vector>

namespace llvm {
namespace codeview {

class MemoryTypeTableBuilder : public TypeTableBuilder {
public:
class Record {
public:
explicit Record(llvm::StringRef RData);

const char *data() const { return Data.get(); }
uint16_t size() const { return Size; }

private:
uint16_t Size;
std::unique_ptr<char[]> Data;
};

private:
class RecordHash : std::unary_function<llvm::StringRef, size_t> {
public:
size_t operator()(llvm::StringRef Val) const {
return static_cast<size_t>(llvm::hash_value(Val));
}
};

public:
MemoryTypeTableBuilder() {}

template <typename TFunc> void ForEachRecord(TFunc Func) {
uint32_t Index = TypeIndex::FirstNonSimpleIndex;

for (const std::unique_ptr<Record> &R : Records) {
Func(TypeIndex(Index), R.get());
++Index;
}
}

private:
virtual TypeIndex writeRecord(llvm::StringRef Data) override;

private:
std::vector<std::unique_ptr<Record>> Records;
std::unordered_map<llvm::StringRef, TypeIndex, RecordHash> HashedRecords;
};
}
}

#endif
35 changes: 35 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/MethodListRecordBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===- MethodListRecordBuilder.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_METHODLISTRECORDBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_METHODLISTRECORDBUILDER_H

#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"

namespace llvm {
namespace codeview {

class MethodInfo;

class MethodListRecordBuilder : public ListRecordBuilder {
private:
MethodListRecordBuilder(const MethodListRecordBuilder &) = delete;
MethodListRecordBuilder &operator=(const MethodListRecordBuilder &) = delete;

public:
MethodListRecordBuilder();

void writeMethod(MemberAccess Access, MethodKind Kind, MethodOptions Options,
TypeIndex Type, int32_t VTableSlotOffset);
void writeMethod(const MethodInfo &Method);
};
}
}

#endif
176 changes: 176 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
//===- TypeIndex.h ----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H

#include <cassert>
#include <cinttypes>

namespace llvm {
namespace codeview {

enum class SimpleTypeKind : uint32_t {
None = 0x0000, // uncharacterized type (no type)
Void = 0x0003, // void
NotTranslated = 0x0007, // type not translated by cvpack
HResult = 0x0008, // OLE/COM HRESULT

SignedCharacter = 0x0010, // 8 bit signed
UnsignedCharacter = 0x0020, // 8 bit unsigned
NarrowCharacter = 0x0070, // really a char
WideCharacter = 0x0071, // wide char

SByte = 0x0068, // 8 bit signed int
Byte = 0x0069, // 8 bit unsigned int
Int16Short = 0x0011, // 16 bit signed
UInt16Short = 0x0021, // 16 bit unsigned
Int16 = 0x0072, // 16 bit signed int
UInt16 = 0x0073, // 16 bit unsigned int
Int32Long = 0x0012, // 32 bit signed
UInt32Long = 0x0022, // 32 bit unsigned
Int32 = 0x0074, // 32 bit signed int
UInt32 = 0x0075, // 32 bit unsigned int
Int64Quad = 0x0013, // 64 bit signed
UInt64Quad = 0x0023, // 64 bit unsigned
Int64 = 0x0076, // 64 bit signed int
UInt64 = 0x0077, // 64 bit unsigned int
Int128 = 0x0078, // 128 bit signed int
UInt128 = 0x0079, // 128 bit unsigned int

Float16 = 0x0046, // 16 bit real
Float32 = 0x0040, // 32 bit real
Float32PartialPrecision = 0x0045, // 32 bit PP real
Float48 = 0x0044, // 48 bit real
Float64 = 0x0041, // 64 bit real
Float80 = 0x0042, // 80 bit real
Float128 = 0x0043, // 128 bit real

Complex32 = 0x0050, // 32 bit complex
Complex64 = 0x0051, // 64 bit complex
Complex80 = 0x0052, // 80 bit complex
Complex128 = 0x0053, // 128 bit complex

Boolean8 = 0x0030, // 8 bit boolean
Boolean16 = 0x0031, // 16 bit boolean
Boolean32 = 0x0032, // 32 bit boolean
Boolean64 = 0x0033 // 64 bit boolean
};

enum class SimpleTypeMode : uint32_t {
Direct = 0x00000000, // Not a pointer
NearPointer = 0x00000100, // Near pointer
FarPointer = 0x00000200, // Far pointer
HugePointer = 0x00000300, // Huge pointer
NearPointer32 = 0x00000400, // 32 bit near pointer
FarPointer32 = 0x00000500, // 32 bit far pointer
NearPointer64 = 0x00000600, // 64 bit near pointer
NearPointer128 = 0x00000700 // 128 bit near pointer
};

class TypeIndex {
public:
static const uint32_t FirstNonSimpleIndex = 0x1000;
static const uint32_t SimpleKindMask = 0x000000ff;
static const uint32_t SimpleModeMask = 0x00000700;

public:
TypeIndex() : Index(0) {}
explicit TypeIndex(uint32_t Index) : Index(Index) {}
explicit TypeIndex(SimpleTypeKind Kind)
: Index(static_cast<uint32_t>(Kind)) {}
TypeIndex(SimpleTypeKind Kind, SimpleTypeMode Mode)
: Index(static_cast<uint32_t>(Kind) | static_cast<uint32_t>(Mode)) {}

uint32_t getIndex() const { return Index; }
bool isSimple() const { return Index < FirstNonSimpleIndex; }

SimpleTypeKind getSimpleKind() const {
assert(isSimple());
return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
}

SimpleTypeMode getSimpleMode() const {
assert(isSimple());
return static_cast<SimpleTypeMode>(Index & SimpleModeMask);
}

static TypeIndex Void() { return TypeIndex(SimpleTypeKind::Void); }
static TypeIndex VoidPointer32() {
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer32);
}
static TypeIndex VoidPointer64() {
return TypeIndex(SimpleTypeKind::Void, SimpleTypeMode::NearPointer64);
}

static TypeIndex SignedCharacter() {
return TypeIndex(SimpleTypeKind::SignedCharacter);
}
static TypeIndex UnsignedCharacter() {
return TypeIndex(SimpleTypeKind::UnsignedCharacter);
}
static TypeIndex NarrowCharacter() {
return TypeIndex(SimpleTypeKind::NarrowCharacter);
}
static TypeIndex WideCharacter() {
return TypeIndex(SimpleTypeKind::WideCharacter);
}
static TypeIndex Int16Short() {
return TypeIndex(SimpleTypeKind::Int16Short);
}
static TypeIndex UInt16Short() {
return TypeIndex(SimpleTypeKind::UInt16Short);
}
static TypeIndex Int32() { return TypeIndex(SimpleTypeKind::Int32); }
static TypeIndex UInt32() { return TypeIndex(SimpleTypeKind::UInt32); }
static TypeIndex Int32Long() { return TypeIndex(SimpleTypeKind::Int32Long); }
static TypeIndex UInt32Long() {
return TypeIndex(SimpleTypeKind::UInt32Long);
}
static TypeIndex Int64() { return TypeIndex(SimpleTypeKind::Int64); }
static TypeIndex UInt64() { return TypeIndex(SimpleTypeKind::UInt64); }
static TypeIndex Int64Quad() { return TypeIndex(SimpleTypeKind::Int64Quad); }
static TypeIndex UInt64Quad() {
return TypeIndex(SimpleTypeKind::UInt64Quad);
}

static TypeIndex Float32() { return TypeIndex(SimpleTypeKind::Float32); }
static TypeIndex Float64() { return TypeIndex(SimpleTypeKind::Float64); }

private:
uint32_t Index;
};

inline bool operator==(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() == B.getIndex();
}

inline bool operator!=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() != B.getIndex();
}

inline bool operator<(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() < B.getIndex();
}

inline bool operator<=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() <= B.getIndex();
}

inline bool operator>(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() > B.getIndex();
}

inline bool operator>=(const TypeIndex &A, const TypeIndex &B) {
return A.getIndex() >= B.getIndex();
}
}
}

#endif
270 changes: 270 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
//===- TypeRecord.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include <cinttypes>

namespace llvm {
namespace codeview {

class TypeRecord {
protected:
explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}

public:
TypeRecordKind getKind() const { return Kind; }

private:
TypeRecordKind Kind;
};

class ModifierRecord : public TypeRecord {
public:
ModifierRecord(TypeIndex ModifiedType, ModifierOptions Options)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
Options(Options) {}

TypeIndex getModifiedType() const { return ModifiedType; }
ModifierOptions getOptions() const { return Options; }

private:
TypeIndex ModifiedType;
ModifierOptions Options;
};

class ProcedureRecord : public TypeRecord {
public:
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
TypeIndex ArgumentList)
: TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType),
CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
ArgumentList(ArgumentList) {}

TypeIndex getReturnType() const { return ReturnType; }
CallingConvention getCallConv() const { return CallConv; }
FunctionOptions getOptions() const { return Options; }
uint16_t getParameterCount() const { return ParameterCount; }
TypeIndex getArgumentList() const { return ArgumentList; }

private:
TypeIndex ReturnType;
CallingConvention CallConv;
FunctionOptions Options;
uint16_t ParameterCount;
TypeIndex ArgumentList;
};

class MemberFunctionRecord : public TypeRecord {
public:
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
TypeIndex ThisType, CallingConvention CallConv,
FunctionOptions Options, uint16_t ParameterCount,
TypeIndex ArgumentList, int32_t ThisPointerAdjustment)
: TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType),
ClassType(ClassType), ThisType(ThisType), CallConv(CallConv),
Options(Options), ParameterCount(ParameterCount),
ArgumentList(ArgumentList),
ThisPointerAdjustment(ThisPointerAdjustment) {}

TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; }
TypeIndex getThisType() const { return ThisType; }
CallingConvention getCallConv() const { return CallConv; }
FunctionOptions getOptions() const { return Options; }
uint16_t getParameterCount() const { return ParameterCount; }
TypeIndex getArgumentList() const { return ArgumentList; }
int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }

private:
TypeIndex ReturnType;
TypeIndex ClassType;
TypeIndex ThisType;
CallingConvention CallConv;
FunctionOptions Options;
uint16_t ParameterCount;
TypeIndex ArgumentList;
int32_t ThisPointerAdjustment;
};

class ArgumentListRecord : public TypeRecord {
public:
explicit ArgumentListRecord(llvm::ArrayRef<TypeIndex> ArgumentTypes)
: TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) {
}

llvm::ArrayRef<TypeIndex> getArgumentTypes() const { return ArgumentTypes; }

private:
llvm::ArrayRef<TypeIndex> ArgumentTypes;
};

class PointerRecordBase : public TypeRecord {
public:
PointerRecordBase(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
PointerOptions Options, uint8_t Size)
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
PtrKind(Kind), Mode(Mode), Options(Options), Size(Size) {}

TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const { return PtrKind; }
PointerMode getMode() const { return Mode; }
PointerOptions getOptions() const { return Options; }
uint8_t getSize() const { return Size; }

private:
TypeIndex ReferentType;
PointerKind PtrKind;
PointerMode Mode;
PointerOptions Options;
uint8_t Size;
};

class PointerRecord : public PointerRecordBase {
public:
PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
PointerOptions Options, uint8_t Size)
: PointerRecordBase(ReferentType, Kind, Mode, Options, Size) {}
};

class PointerToMemberRecord : public PointerRecordBase {
public:
PointerToMemberRecord(TypeIndex ReferentType, PointerKind Kind,
PointerMode Mode, PointerOptions Options, uint8_t Size,
TypeIndex ContainingType,
PointerToMemberRepresentation Representation)
: PointerRecordBase(ReferentType, Kind, Mode, Options, Size),
ContainingType(ContainingType), Representation(Representation) {}

TypeIndex getContainingType() const { return ContainingType; }
PointerToMemberRepresentation getRepresentation() const {
return Representation;
}

private:
TypeIndex ContainingType;
PointerToMemberRepresentation Representation;
};

class ArrayRecord : public TypeRecord {
public:
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
llvm::StringRef Name)
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
IndexType(IndexType), Size(Size), Name(Name) {}

TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; }
uint64_t getSize() const { return Size; }
llvm::StringRef getName() const { return Name; }

private:
TypeIndex ElementType;
TypeIndex IndexType;
uint64_t Size;
llvm::StringRef Name;
};

class TagRecord : public TypeRecord {
protected:
TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
TypeIndex FieldList, StringRef Name, StringRef UniqueName)
: TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}

public:
uint16_t getMemberCount() const { return MemberCount; }
ClassOptions getOptions() const { return Options; }
TypeIndex getFieldList() const { return FieldList; }
StringRef getName() const { return Name; }
StringRef getUniqueName() const { return UniqueName; }

private:
uint16_t MemberCount;
ClassOptions Options;
TypeIndex FieldList;
StringRef Name;
StringRef UniqueName;
};

class AggregateRecord : public TagRecord {
public:
AggregateRecord(TypeRecordKind Kind, uint16_t MemberCount,
ClassOptions Options, HfaKind Hfa,
WindowsRTClassKind WinRTKind, TypeIndex FieldList,
TypeIndex DerivationList, TypeIndex VTableShape,
uint64_t Size, StringRef Name, StringRef UniqueName)
: TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList),
VTableShape(VTableShape), Size(Size) {}

HfaKind getHfa() const { return Hfa; }
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
TypeIndex getDerivationList() const { return DerivationList; }
TypeIndex getVTableShape() const { return VTableShape; }
uint64_t getSize() const { return Size; }

private:
HfaKind Hfa;
WindowsRTClassKind WinRTKind;
TypeIndex DerivationList;
TypeIndex VTableShape;
uint64_t Size;
};

class EnumRecord : public TagRecord {
public:
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
: TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
UniqueName),
UnderlyingType(UnderlyingType) {}

TypeIndex getUnderlyingType() const { return UnderlyingType; }

private:
TypeIndex UnderlyingType;
};

class BitFieldRecord : TypeRecord {
public:
BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
: TypeRecord(TypeRecordKind::BitField), Type(Type), BitOffset(BitOffset),
BitSize(BitSize) {}

TypeIndex getType() const { return Type; }
uint8_t getBitOffset() const { return BitOffset; }
uint8_t getBitSize() const { return BitSize; }

private:
TypeIndex Type;
uint8_t BitSize;
uint8_t BitOffset;
};

class VirtualTableShapeRecord : TypeRecord {
public:
explicit VirtualTableShapeRecord(ArrayRef<VirtualTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VirtualTableShape), Slots(Slots) {}

ArrayRef<VirtualTableSlotKind> getSlots() const { return Slots; }

private:
ArrayRef<VirtualTableSlotKind> Slots;
};
}
}

#endif
57 changes: 57 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//===- TypeRecordBuilder.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H

#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/raw_ostream.h"

namespace llvm {
namespace codeview {

class TypeRecordBuilder {
private:
TypeRecordBuilder(const TypeRecordBuilder &) = delete;
TypeRecordBuilder &operator=(const TypeRecordBuilder &) = delete;

public:
explicit TypeRecordBuilder(TypeRecordKind Kind);

void writeUInt8(uint8_t Value);
void writeInt16(int16_t Value);
void writeUInt16(uint16_t Value);
void writeInt32(int32_t Value);
void writeUInt32(uint32_t Value);
void writeInt64(int64_t Value);
void writeUInt64(uint64_t Value);
void writeTypeIndex(TypeIndex TypeInd);
void writeTypeRecordKind(TypeRecordKind Kind);
void writeEncodedInteger(int64_t Value);
void writeEncodedSignedInteger(int64_t Value);
void writeEncodedUnsignedInteger(uint64_t Value);
void writeNullTerminatedString(const char *Value);
void writeNullTerminatedString(StringRef Value);

llvm::StringRef str();

uint64_t size() const { return Stream.tell(); }

private:
llvm::SmallVector<char, 256> Buffer;
llvm::raw_svector_ostream Stream;
llvm::support::endian::Writer<llvm::support::endianness::little> Writer;
};
}
}

#endif
37 changes: 37 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//===- TypeSymbolEmitter.h --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H

#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"

namespace llvm {
namespace codeview {

class TypeSymbolEmitter {
private:
TypeSymbolEmitter(const TypeSymbolEmitter &) = delete;
TypeSymbolEmitter &operator=(const TypeSymbolEmitter &) = delete;

protected:
TypeSymbolEmitter() {}

public:
virtual ~TypeSymbolEmitter() {}

public:
virtual void writeUserDefinedType(TypeIndex TI, StringRef Name) = 0;
};
}
}

#endif
60 changes: 60 additions & 0 deletions llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H

#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Compiler.h"

namespace llvm {
namespace codeview {

class FieldListRecordBuilder;
class MethodListRecordBuilder;
class TypeRecordBuilder;

class TypeTableBuilder {
private:
TypeTableBuilder(const TypeTableBuilder &) = delete;
TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;

protected:
TypeTableBuilder();

public:
virtual ~TypeTableBuilder();

public:
TypeIndex writeModifier(const ModifierRecord &Record);
TypeIndex writeProcedure(const ProcedureRecord &Record);
TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
TypeIndex writeArgumentList(const ArgumentListRecord &Record);
TypeIndex writeRecord(TypeRecordBuilder &builder);
TypeIndex writePointer(const PointerRecord &Record);
TypeIndex writePointerToMember(const PointerToMemberRecord &Record);
TypeIndex writeArray(const ArrayRecord &Record);
TypeIndex writeAggregate(const AggregateRecord &Record);
TypeIndex writeEnum(const EnumRecord &Record);
TypeIndex writeBitField(const BitFieldRecord &Record);
TypeIndex writeVirtualTableShape(const VirtualTableShapeRecord &Record);

TypeIndex writeFieldList(FieldListRecordBuilder &FieldList);
TypeIndex writeMethodList(MethodListRecordBuilder &MethodList);

private:
virtual TypeIndex writeRecord(llvm::StringRef record) = 0;
};
}
}

#endif
1 change: 1 addition & 0 deletions llvm/lib/DebugInfo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
add_subdirectory(CodeView)
add_subdirectory(DWARF)
add_subdirectory(PDB)
add_subdirectory(Symbolize)
9 changes: 9 additions & 0 deletions llvm/lib/DebugInfo/CodeView/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
add_llvm_library(LLVMCodeView
FieldListRecordBuilder.cpp
Line.cpp
ListRecordBuilder.cpp
MemoryTypeTableBuilder.cpp
MethodListRecordBuilder.cpp
TypeRecordBuilder.cpp
TypeTableBuilder.cpp
)
165 changes: 165 additions & 0 deletions llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
//===-- FieldListRecordBuilder.cpp ----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"

using namespace llvm;
using namespace codeview;

FieldListRecordBuilder::FieldListRecordBuilder()
: ListRecordBuilder(TypeRecordKind::FieldList) {}

void FieldListRecordBuilder::writeBaseClass(MemberAccess Access, TypeIndex Type,
uint64_t Offset) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
Builder.writeUInt16(static_cast<uint16_t>(Access));
Builder.writeTypeIndex(Type);
Builder.writeEncodedUnsignedInteger(Offset);

finishSubRecord();
}

void FieldListRecordBuilder::writeEnumerate(MemberAccess Access, uint64_t Value,
StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::Enumerate);
Builder.writeUInt16(static_cast<uint16_t>(Access));
Builder.writeEncodedUnsignedInteger(Value);
Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeMember(MemberAccess Access, TypeIndex Type,
uint64_t Offset, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::Member);
Builder.writeUInt16(static_cast<uint16_t>(Access));
Builder.writeTypeIndex(Type);
Builder.writeEncodedUnsignedInteger(Offset);
Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeMethod(uint16_t OverloadCount,
TypeIndex MethodList, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::Method);
Builder.writeUInt16(OverloadCount);
Builder.writeTypeIndex(MethodList);
Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeOneMethod(
MemberAccess Access, MethodKind Kind, MethodOptions Options, TypeIndex Type,
int32_t VTableSlotOffset, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

uint16_t Flags = static_cast<uint16_t>(Access);
Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
Flags |= static_cast<uint16_t>(Options);

Builder.writeTypeRecordKind(TypeRecordKind::OneMethod);
Builder.writeUInt16(Flags);
Builder.writeTypeIndex(Type);
switch (Kind) {
case MethodKind::IntroducingVirtual:
case MethodKind::PureIntroducingVirtual:
assert(VTableSlotOffset >= 0);
Builder.writeInt32(VTableSlotOffset);
break;

default:
assert(VTableSlotOffset == -1);
break;
}

Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeOneMethod(const MethodInfo &Method,
StringRef Name) {
writeOneMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
Method.getType(), Method.getVTableSlotOffset(), Name);
}

void FieldListRecordBuilder::writeNestedType(TypeIndex Type, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::NestedType);
Builder.writeUInt16(0);
Builder.writeTypeIndex(Type);
Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeStaticMember(MemberAccess Access,
TypeIndex Type, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::StaticMember);
Builder.writeUInt16(static_cast<uint16_t>(Access));
Builder.writeTypeIndex(Type);
Builder.writeNullTerminatedString(Name);

finishSubRecord();
}

void FieldListRecordBuilder::writeIndirectVirtualBaseClass(
MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
writeVirtualBaseClass(TypeRecordKind::IndirectVirtualBaseClass, Access, Type,
VirtualBasePointerType, VirtualBasePointerOffset,
SlotIndex);
}

void FieldListRecordBuilder::writeVirtualBaseClass(
MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
writeVirtualBaseClass(TypeRecordKind::VirtualBaseClass, Access, Type,
VirtualBasePointerType, VirtualBasePointerOffset,
SlotIndex);
}

void FieldListRecordBuilder::writeVirtualBaseClass(
TypeRecordKind Kind, MemberAccess Access, TypeIndex Type,
TypeIndex VirtualBasePointerType, int64_t VirtualBasePointerOffset,
uint64_t SlotIndex) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(Kind);
Builder.writeUInt16(static_cast<uint16_t>(Access));
Builder.writeTypeIndex(Type);
Builder.writeTypeIndex(VirtualBasePointerType);
Builder.writeEncodedInteger(VirtualBasePointerOffset);
Builder.writeEncodedUnsignedInteger(SlotIndex);

finishSubRecord();
}

void FieldListRecordBuilder::writeVirtualFunctionTablePointer(TypeIndex Type) {
TypeRecordBuilder &Builder = getBuilder();

Builder.writeTypeRecordKind(TypeRecordKind::VirtualFunctionTablePointer);
Builder.writeUInt16(0);
Builder.writeTypeIndex(Type);

finishSubRecord();
}
22 changes: 22 additions & 0 deletions llvm/lib/DebugInfo/CodeView/LLVMBuild.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
;===- ./lib/CodeView/LLVMBuild.txt -------------------------------*- Conf -*--===;
;
; The LLVM Compiler Infrastructure
;
; This file is distributed under the University of Illinois Open Source
; License. See LICENSE.TXT for details.
;
;===------------------------------------------------------------------------===;
;
; This is an LLVMBuild description file for the components in this subdirectory.
;
; For more information on the LLVMBuild system, please see:
;
; http://llvm.org/docs/LLVMBuild.html
;
;===------------------------------------------------------------------------===;

[component_0]
type = Library
name = CodeView
parent = Libraries
required_libraries = Support
22 changes: 22 additions & 0 deletions llvm/lib/DebugInfo/CodeView/Line.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Line.cpp ----------------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/Line.h"

using namespace llvm;
using namespace codeview;

LineInfo::LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement) {
LineData = StartLine & StartLineMask;
uint32_t LineDelta = EndLine - StartLine;
LineData |= (LineDelta << EndLineDeltaShift) & EndLineDeltaMask;
if (IsStatement) {
LineData |= StatementFlag;
}
}
31 changes: 31 additions & 0 deletions llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- ListRecordBuilder.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"

using namespace llvm;
using namespace codeview;

ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Builder(Kind) {}

void ListRecordBuilder::finishSubRecord() {
// The builder starts at offset 2 in the actual CodeView buffer, so add an
// additional offset of 2 before computing the alignment.
uint32_t Remainder = (Builder.size() + 2) % 4;
if (Remainder != 0) {
for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
--PaddingBytesLeft) {
Builder.writeUInt8(0xf0 + PaddingBytesLeft);
}
}

// TODO: Split the list into multiple records if it's longer than 64KB, using
// a subrecord of TypeRecordKind::Index to chain the records together.
assert(Builder.size() < 65536);
}
35 changes: 35 additions & 0 deletions llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===-- MemoryTypeTableBuilder.cpp ----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"

using namespace llvm;
using namespace codeview;

MemoryTypeTableBuilder::Record::Record(StringRef RData)
: Size(RData.size()), Data(new char[RData.size()]) {
memcpy(Data.get(), RData.data(), RData.size());
}

TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) {
auto I = HashedRecords.find(Data);
if (I != HashedRecords.end()) {
return I->second;
}

std::unique_ptr<Record> R(new Record(Data));

TypeIndex TI(static_cast<uint32_t>(Records.size()) +
TypeIndex::FirstNonSimpleIndex);
HashedRecords.insert(std::make_pair(StringRef(R->data(), R->size()), TI));
Records.push_back(std::move(R));

return TI;
}
49 changes: 49 additions & 0 deletions llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===-- MethodListRecordBuilder.cpp ---------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"

using namespace llvm;
using namespace codeview;

MethodListRecordBuilder::MethodListRecordBuilder()
: ListRecordBuilder(TypeRecordKind::MethodList) {}

void MethodListRecordBuilder::writeMethod(MemberAccess Access, MethodKind Kind,
MethodOptions Options, TypeIndex Type,
int32_t VTableSlotOffset) {
TypeRecordBuilder &Builder = getBuilder();

uint16_t Flags = static_cast<uint16_t>(Access);
Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
Flags |= static_cast<uint16_t>(Options);

Builder.writeUInt16(Flags);
Builder.writeUInt16(0);
Builder.writeTypeIndex(Type);
switch (Kind) {
case MethodKind::IntroducingVirtual:
case MethodKind::PureIntroducingVirtual:
assert(VTableSlotOffset >= 0);
Builder.writeInt32(VTableSlotOffset);
break;

default:
assert(VTableSlotOffset == -1);
break;
}

// TODO: Fail if too big?
}

void MethodListRecordBuilder::writeMethod(const MethodInfo &Method) {
writeMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
Method.getType(), Method.getVTableSlotOffset());
}
113 changes: 113 additions & 0 deletions llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//===-- TypeRecordBuilder.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"

using namespace llvm;
using namespace codeview;

TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind) : Stream(Buffer),
Writer(Stream) {
writeTypeRecordKind(Kind);
}

StringRef TypeRecordBuilder::str() {
return StringRef(Buffer.data(), Buffer.size());
}

void TypeRecordBuilder::writeUInt8(uint8_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeInt16(int16_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeUInt16(uint16_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeInt32(int32_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeUInt32(uint32_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeInt64(int64_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeUInt64(uint64_t Value) {
Writer.write(Value);
}

void TypeRecordBuilder::writeEncodedInteger(int64_t Value) {
if (Value >= 0) {
writeEncodedUnsignedInteger(static_cast<uint64_t>(Value));
} else {
writeEncodedSignedInteger(Value);
}
}

void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) {
if (Value >= std::numeric_limits<int8_t>::min() &&
Value <= std::numeric_limits<int8_t>::max()) {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::SByte));
writeInt16(static_cast<int8_t>(Value));
} else if (Value >= std::numeric_limits<int16_t>::min() &&
Value <= std::numeric_limits<int16_t>::max()) {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int16));
writeInt16(static_cast<int16_t>(Value));
} else if (Value >= std::numeric_limits<int32_t>::min() &&
Value <= std::numeric_limits<int32_t>::max()) {
writeUInt16(static_cast<uint32_t>(TypeRecordKind::Int32));
writeInt32(static_cast<int32_t>(Value));
} else {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int64));
writeInt64(Value);
}
}

void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) {
if (Value < static_cast<uint16_t>(TypeRecordKind::SByte)) {
writeUInt16(static_cast<uint16_t>(Value));
} else if (Value <= std::numeric_limits<uint16_t>::max()) {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt16));
writeUInt16(static_cast<uint16_t>(Value));
} else if (Value <= std::numeric_limits<uint32_t>::max()) {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt32));
writeUInt32(static_cast<uint32_t>(Value));
} else {
writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt64));
writeUInt64(Value);
}
}

void TypeRecordBuilder::writeNullTerminatedString(const char *Value) {
assert(Value != nullptr);

size_t Length = strlen(Value);
Stream.write(Value, Length);
writeUInt8(0);
}

void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) {
Stream.write(Value.data(), Value.size());
writeUInt8(0);
}

void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) {
writeUInt32(TypeInd.getIndex());
}

void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) {
writeUInt16(static_cast<uint16_t>(Kind));
}
221 changes: 221 additions & 0 deletions llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
//===-- TypeTableBuilder.cpp ----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
#include "llvm/support/raw_ostream.h"

using namespace llvm;
using namespace codeview;

namespace {

const uint32_t PointerKindMask = 0x0000001f;
const int PointerKindShift = 0;
const uint32_t PointerModeMask = 0x000000e0;
const int PointerModeShift = 5;
const uint32_t PointerSizeMask = 0x0007e000;
const int PointerSizeShift = 13;
const uint32_t PointerOptionsMask = 0x00081f00;

const int ClassHfaKindShift = 11;
const int ClassWindowsRTClassKindShift = 14;

void writePointerBase(TypeRecordBuilder &Builder,
const PointerRecordBase &Record) {
Builder.writeTypeIndex(Record.getReferentType());
uint32_t flags =
static_cast<uint32_t>(Record.getOptions()) |
(Record.getSize() << PointerSizeShift) |
(static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
(static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
Builder.writeUInt32(flags);
}
}

TypeTableBuilder::TypeTableBuilder() {}

TypeTableBuilder::~TypeTableBuilder() {}

TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Modifier);

Builder.writeTypeIndex(Record.getModifiedType());
Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Procedure);

Builder.writeTypeIndex(Record.getReturnType());
Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
Builder.writeUInt16(Record.getParameterCount());
Builder.writeTypeIndex(Record.getArgumentList());

return writeRecord(Builder);
}

TypeIndex
TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);

Builder.writeTypeIndex(Record.getReturnType());
Builder.writeTypeIndex(Record.getClassType());
Builder.writeTypeIndex(Record.getThisType());
Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
Builder.writeUInt16(Record.getParameterCount());
Builder.writeTypeIndex(Record.getArgumentList());
Builder.writeInt32(Record.getThisPointerAdjustment());

return writeRecord(Builder);
}

TypeIndex
TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);

Builder.writeUInt32(Record.getArgumentTypes().size());
for (TypeIndex TI : Record.getArgumentTypes()) {
Builder.writeTypeIndex(TI);
}

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Pointer);

writePointerBase(Builder, Record);

return writeRecord(Builder);
}

TypeIndex
TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Pointer);

writePointerBase(Builder, Record);

Builder.writeTypeIndex(Record.getContainingType());
Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Array);

Builder.writeTypeIndex(Record.getElementType());
Builder.writeTypeIndex(Record.getIndexType());
Builder.writeEncodedUnsignedInteger(Record.getSize());
Builder.writeNullTerminatedString(Record.getName());

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
assert((Record.getKind() == TypeRecordKind::Structure) ||
(Record.getKind() == TypeRecordKind::Class) ||
(Record.getKind() == TypeRecordKind::Union));

TypeRecordBuilder Builder(Record.getKind());

Builder.writeUInt16(Record.getMemberCount());
uint16_t Flags =
static_cast<uint16_t>(Record.getOptions()) |
(static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
(static_cast<uint16_t>(Record.getWinRTKind())
<< ClassWindowsRTClassKindShift);
Builder.writeUInt16(Flags);
Builder.writeTypeIndex(Record.getFieldList());
if (Record.getKind() != TypeRecordKind::Union) {
Builder.writeTypeIndex(Record.getDerivationList());
Builder.writeTypeIndex(Record.getVTableShape());
} else {
assert(Record.getDerivationList() == TypeIndex());
assert(Record.getVTableShape() == TypeIndex());
}
Builder.writeEncodedUnsignedInteger(Record.getSize());
Builder.writeNullTerminatedString(Record.getName());
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
ClassOptions::None) {
Builder.writeNullTerminatedString(Record.getUniqueName());
}

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Enum);

Builder.writeUInt16(Record.getMemberCount());
Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
Builder.writeTypeIndex(Record.getUnderlyingType());
Builder.writeTypeIndex(Record.getFieldList());
Builder.writeNullTerminatedString(Record.getName());
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
ClassOptions::None) {
Builder.writeNullTerminatedString(Record.getUniqueName());
}

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::BitField);

Builder.writeTypeIndex(Record.getType());
Builder.writeUInt8(Record.getBitSize());
Builder.writeUInt8(Record.getBitOffset());

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeVirtualTableShape(
const VirtualTableShapeRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);

ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();

Builder.writeUInt16(Slots.size());
for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
if ((SlotIndex + 1) < Slots.size()) {
Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
}
Builder.writeUInt8(Byte);
}

return writeRecord(Builder);
}

TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
return writeRecord(Builder.str());
}

TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
// TODO: Split the list into multiple records if it's longer than 64KB, using
// a subrecord of TypeRecordKind::Index to chain the records together.
return writeRecord(FieldList.str());
}

TypeIndex
TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
// TODO: Split the list into multiple records if it's longer than 64KB, using
// a subrecord of TypeRecordKind::Index to chain the records together.
return writeRecord(MethodList.str());
}
2 changes: 1 addition & 1 deletion llvm/lib/DebugInfo/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;

[common]
subdirectories = DWARF PDB Symbolize
subdirectories = CodeView DWARF PDB Symbolize

[component_0]
type = Group
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/DebugInfo/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ LEVEL = ../..

include $(LEVEL)/Makefile.config

PARALLEL_DIRS := DWARF PDB Symbolize
PARALLEL_DIRS := CodeView DWARF PDB Symbolize

include $(LEVEL)/Makefile.common