summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo/CodeView
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/DebugInfo/CodeView')
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp165
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/Line.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp31
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp35
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp49
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp113
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp217
7 files changed, 632 insertions, 0 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
new file mode 100644
index 0000000..91b71cc
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
@@ -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();
+} \ No newline at end of file
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp b/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp
new file mode 100644
index 0000000..4cb766b
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp
@@ -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;
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
new file mode 100644
index 0000000..69c7e87
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
@@ -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);
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
new file mode 100644
index 0000000..9afce92
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
@@ -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;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
new file mode 100644
index 0000000..8893025
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
@@ -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());
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
new file mode 100644
index 0000000..cbf464f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
@@ -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));
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
new file mode 100644
index 0000000..4af5dca
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -0,0 +1,217 @@
+//===-- 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 int PointerKindShift = 0;
+const int PointerModeShift = 5;
+const int PointerSizeShift = 13;
+
+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());
+}
OpenPOWER on IntegriCloud