1 //===-- TypeTableBuilder.cpp ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
13 #include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
14 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
16 #include "llvm/support/raw_ostream.h"
19 using namespace codeview;
23 const uint32_t PointerKindMask = 0x0000001f;
24 const int PointerKindShift = 0;
25 const uint32_t PointerModeMask = 0x000000e0;
26 const int PointerModeShift = 5;
27 const uint32_t PointerSizeMask = 0x0007e000;
28 const int PointerSizeShift = 13;
29 const uint32_t PointerOptionsMask = 0x00081f00;
31 const int ClassHfaKindShift = 11;
32 const int ClassWindowsRTClassKindShift = 14;
34 void writePointerBase(TypeRecordBuilder &Builder,
35 const PointerRecordBase &Record) {
36 Builder.writeTypeIndex(Record.getReferentType());
38 static_cast<uint32_t>(Record.getOptions()) |
39 (Record.getSize() << PointerSizeShift) |
40 (static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
41 (static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
42 Builder.writeUInt32(flags);
46 TypeTableBuilder::TypeTableBuilder() {}
48 TypeTableBuilder::~TypeTableBuilder() {}
50 TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
51 TypeRecordBuilder Builder(TypeRecordKind::Modifier);
53 Builder.writeTypeIndex(Record.getModifiedType());
54 Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
56 return writeRecord(Builder);
59 TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
60 TypeRecordBuilder Builder(TypeRecordKind::Procedure);
62 Builder.writeTypeIndex(Record.getReturnType());
63 Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
64 Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
65 Builder.writeUInt16(Record.getParameterCount());
66 Builder.writeTypeIndex(Record.getArgumentList());
68 return writeRecord(Builder);
72 TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
73 TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);
75 Builder.writeTypeIndex(Record.getReturnType());
76 Builder.writeTypeIndex(Record.getClassType());
77 Builder.writeTypeIndex(Record.getThisType());
78 Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
79 Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
80 Builder.writeUInt16(Record.getParameterCount());
81 Builder.writeTypeIndex(Record.getArgumentList());
82 Builder.writeInt32(Record.getThisPointerAdjustment());
84 return writeRecord(Builder);
88 TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
89 TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
91 Builder.writeUInt32(Record.getArgumentTypes().size());
92 for (TypeIndex TI : Record.getArgumentTypes()) {
93 Builder.writeTypeIndex(TI);
96 return writeRecord(Builder);
99 TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
100 TypeRecordBuilder Builder(TypeRecordKind::Pointer);
102 writePointerBase(Builder, Record);
104 return writeRecord(Builder);
108 TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
109 TypeRecordBuilder Builder(TypeRecordKind::Pointer);
111 writePointerBase(Builder, Record);
113 Builder.writeTypeIndex(Record.getContainingType());
114 Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
116 return writeRecord(Builder);
119 TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
120 TypeRecordBuilder Builder(TypeRecordKind::Array);
122 Builder.writeTypeIndex(Record.getElementType());
123 Builder.writeTypeIndex(Record.getIndexType());
124 Builder.writeEncodedUnsignedInteger(Record.getSize());
125 Builder.writeNullTerminatedString(Record.getName());
127 return writeRecord(Builder);
130 TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
131 assert((Record.getKind() == TypeRecordKind::Structure) ||
132 (Record.getKind() == TypeRecordKind::Class) ||
133 (Record.getKind() == TypeRecordKind::Union));
135 TypeRecordBuilder Builder(Record.getKind());
137 Builder.writeUInt16(Record.getMemberCount());
139 static_cast<uint16_t>(Record.getOptions()) |
140 (static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
141 (static_cast<uint16_t>(Record.getWinRTKind())
142 << ClassWindowsRTClassKindShift);
143 Builder.writeUInt16(Flags);
144 Builder.writeTypeIndex(Record.getFieldList());
145 if (Record.getKind() != TypeRecordKind::Union) {
146 Builder.writeTypeIndex(Record.getDerivationList());
147 Builder.writeTypeIndex(Record.getVTableShape());
149 assert(Record.getDerivationList() == TypeIndex());
150 assert(Record.getVTableShape() == TypeIndex());
152 Builder.writeEncodedUnsignedInteger(Record.getSize());
153 Builder.writeNullTerminatedString(Record.getName());
154 if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
155 ClassOptions::None) {
156 Builder.writeNullTerminatedString(Record.getUniqueName());
159 return writeRecord(Builder);
162 TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
163 TypeRecordBuilder Builder(TypeRecordKind::Enum);
165 Builder.writeUInt16(Record.getMemberCount());
166 Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
167 Builder.writeTypeIndex(Record.getUnderlyingType());
168 Builder.writeTypeIndex(Record.getFieldList());
169 Builder.writeNullTerminatedString(Record.getName());
170 if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
171 ClassOptions::None) {
172 Builder.writeNullTerminatedString(Record.getUniqueName());
175 return writeRecord(Builder);
178 TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
179 TypeRecordBuilder Builder(TypeRecordKind::BitField);
181 Builder.writeTypeIndex(Record.getType());
182 Builder.writeUInt8(Record.getBitSize());
183 Builder.writeUInt8(Record.getBitOffset());
185 return writeRecord(Builder);
188 TypeIndex TypeTableBuilder::writeVirtualTableShape(
189 const VirtualTableShapeRecord &Record) {
190 TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);
192 ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();
194 Builder.writeUInt16(Slots.size());
195 for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
196 uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
197 if ((SlotIndex + 1) < Slots.size()) {
198 Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
200 Builder.writeUInt8(Byte);
203 return writeRecord(Builder);
206 TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
207 return writeRecord(Builder.str());
210 TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
211 // TODO: Split the list into multiple records if it's longer than 64KB, using
212 // a subrecord of TypeRecordKind::Index to chain the records together.
213 return writeRecord(FieldList.str());
217 TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
218 // TODO: Split the list into multiple records if it's longer than 64KB, using
219 // a subrecord of TypeRecordKind::Index to chain the records together.
220 return writeRecord(MethodList.str());