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 int PointerKindShift = 0;
24 const int PointerModeShift = 5;
25 const int PointerSizeShift = 13;
27 const int ClassHfaKindShift = 11;
28 const int ClassWindowsRTClassKindShift = 14;
30 void writePointerBase(TypeRecordBuilder &Builder,
31 const PointerRecordBase &Record) {
32 Builder.writeTypeIndex(Record.getReferentType());
34 static_cast<uint32_t>(Record.getOptions()) |
35 (Record.getSize() << PointerSizeShift) |
36 (static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
37 (static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
38 Builder.writeUInt32(flags);
42 TypeTableBuilder::TypeTableBuilder() {}
44 TypeTableBuilder::~TypeTableBuilder() {}
46 TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
47 TypeRecordBuilder Builder(TypeRecordKind::Modifier);
49 Builder.writeTypeIndex(Record.getModifiedType());
50 Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
52 return writeRecord(Builder);
55 TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
56 TypeRecordBuilder Builder(TypeRecordKind::Procedure);
58 Builder.writeTypeIndex(Record.getReturnType());
59 Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
60 Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
61 Builder.writeUInt16(Record.getParameterCount());
62 Builder.writeTypeIndex(Record.getArgumentList());
64 return writeRecord(Builder);
68 TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
69 TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);
71 Builder.writeTypeIndex(Record.getReturnType());
72 Builder.writeTypeIndex(Record.getClassType());
73 Builder.writeTypeIndex(Record.getThisType());
74 Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
75 Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
76 Builder.writeUInt16(Record.getParameterCount());
77 Builder.writeTypeIndex(Record.getArgumentList());
78 Builder.writeInt32(Record.getThisPointerAdjustment());
80 return writeRecord(Builder);
84 TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
85 TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
87 Builder.writeUInt32(Record.getArgumentTypes().size());
88 for (TypeIndex TI : Record.getArgumentTypes()) {
89 Builder.writeTypeIndex(TI);
92 return writeRecord(Builder);
95 TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
96 TypeRecordBuilder Builder(TypeRecordKind::Pointer);
98 writePointerBase(Builder, Record);
100 return writeRecord(Builder);
104 TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
105 TypeRecordBuilder Builder(TypeRecordKind::Pointer);
107 writePointerBase(Builder, Record);
109 Builder.writeTypeIndex(Record.getContainingType());
110 Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
112 return writeRecord(Builder);
115 TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
116 TypeRecordBuilder Builder(TypeRecordKind::Array);
118 Builder.writeTypeIndex(Record.getElementType());
119 Builder.writeTypeIndex(Record.getIndexType());
120 Builder.writeEncodedUnsignedInteger(Record.getSize());
121 Builder.writeNullTerminatedString(Record.getName());
123 return writeRecord(Builder);
126 TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
127 assert((Record.getKind() == TypeRecordKind::Structure) ||
128 (Record.getKind() == TypeRecordKind::Class) ||
129 (Record.getKind() == TypeRecordKind::Union));
131 TypeRecordBuilder Builder(Record.getKind());
133 Builder.writeUInt16(Record.getMemberCount());
135 static_cast<uint16_t>(Record.getOptions()) |
136 (static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
137 (static_cast<uint16_t>(Record.getWinRTKind())
138 << ClassWindowsRTClassKindShift);
139 Builder.writeUInt16(Flags);
140 Builder.writeTypeIndex(Record.getFieldList());
141 if (Record.getKind() != TypeRecordKind::Union) {
142 Builder.writeTypeIndex(Record.getDerivationList());
143 Builder.writeTypeIndex(Record.getVTableShape());
145 assert(Record.getDerivationList() == TypeIndex());
146 assert(Record.getVTableShape() == TypeIndex());
148 Builder.writeEncodedUnsignedInteger(Record.getSize());
149 Builder.writeNullTerminatedString(Record.getName());
150 if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
151 ClassOptions::None) {
152 Builder.writeNullTerminatedString(Record.getUniqueName());
155 return writeRecord(Builder);
158 TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
159 TypeRecordBuilder Builder(TypeRecordKind::Enum);
161 Builder.writeUInt16(Record.getMemberCount());
162 Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
163 Builder.writeTypeIndex(Record.getUnderlyingType());
164 Builder.writeTypeIndex(Record.getFieldList());
165 Builder.writeNullTerminatedString(Record.getName());
166 if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
167 ClassOptions::None) {
168 Builder.writeNullTerminatedString(Record.getUniqueName());
171 return writeRecord(Builder);
174 TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
175 TypeRecordBuilder Builder(TypeRecordKind::BitField);
177 Builder.writeTypeIndex(Record.getType());
178 Builder.writeUInt8(Record.getBitSize());
179 Builder.writeUInt8(Record.getBitOffset());
181 return writeRecord(Builder);
184 TypeIndex TypeTableBuilder::writeVirtualTableShape(
185 const VirtualTableShapeRecord &Record) {
186 TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);
188 ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();
190 Builder.writeUInt16(Slots.size());
191 for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
192 uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
193 if ((SlotIndex + 1) < Slots.size()) {
194 Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
196 Builder.writeUInt8(Byte);
199 return writeRecord(Builder);
202 TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
203 return writeRecord(Builder.str());
206 TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
207 // TODO: Split the list into multiple records if it's longer than 64KB, using
208 // a subrecord of TypeRecordKind::Index to chain the records together.
209 return writeRecord(FieldList.str());
213 TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
214 // TODO: Split the list into multiple records if it's longer than 64KB, using
215 // a subrecord of TypeRecordKind::Index to chain the records together.
216 return writeRecord(MethodList.str());