1//===-- TypeTableBuilder.cpp ----------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 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" 17 18using namespace llvm; 19using namespace codeview; 20 21namespace { 22 23const int PointerKindShift = 0; 24const int PointerModeShift = 5; 25const int PointerSizeShift = 13; 26 27const int ClassHfaKindShift = 11; 28const int ClassWindowsRTClassKindShift = 14; 29 30void writePointerBase(TypeRecordBuilder &Builder, 31 const PointerRecordBase &Record) { 32 Builder.writeTypeIndex(Record.getReferentType()); 33 uint32_t flags = 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); 39} 40} 41 42TypeTableBuilder::TypeTableBuilder() {} 43 44TypeTableBuilder::~TypeTableBuilder() {} 45 46TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) { 47 TypeRecordBuilder Builder(TypeRecordKind::Modifier); 48 49 Builder.writeTypeIndex(Record.getModifiedType()); 50 Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions())); 51 52 return writeRecord(Builder); 53} 54 55TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) { 56 TypeRecordBuilder Builder(TypeRecordKind::Procedure); 57 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()); 63 64 return writeRecord(Builder); 65} 66 67TypeIndex 68TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) { 69 TypeRecordBuilder Builder(TypeRecordKind::MemberFunction); 70 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()); 79 80 return writeRecord(Builder); 81} 82 83TypeIndex 84TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) { 85 TypeRecordBuilder Builder(TypeRecordKind::ArgumentList); 86 87 Builder.writeUInt32(Record.getArgumentTypes().size()); 88 for (TypeIndex TI : Record.getArgumentTypes()) { 89 Builder.writeTypeIndex(TI); 90 } 91 92 return writeRecord(Builder); 93} 94 95TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) { 96 TypeRecordBuilder Builder(TypeRecordKind::Pointer); 97 98 writePointerBase(Builder, Record); 99 100 return writeRecord(Builder); 101} 102 103TypeIndex 104TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) { 105 TypeRecordBuilder Builder(TypeRecordKind::Pointer); 106 107 writePointerBase(Builder, Record); 108 109 Builder.writeTypeIndex(Record.getContainingType()); 110 Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation())); 111 112 return writeRecord(Builder); 113} 114 115TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) { 116 TypeRecordBuilder Builder(TypeRecordKind::Array); 117 118 Builder.writeTypeIndex(Record.getElementType()); 119 Builder.writeTypeIndex(Record.getIndexType()); 120 Builder.writeEncodedUnsignedInteger(Record.getSize()); 121 Builder.writeNullTerminatedString(Record.getName()); 122 123 return writeRecord(Builder); 124} 125 126TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) { 127 assert((Record.getKind() == TypeRecordKind::Structure) || 128 (Record.getKind() == TypeRecordKind::Class) || 129 (Record.getKind() == TypeRecordKind::Union)); 130 131 TypeRecordBuilder Builder(Record.getKind()); 132 133 Builder.writeUInt16(Record.getMemberCount()); 134 uint16_t Flags = 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()); 144 } else { 145 assert(Record.getDerivationList() == TypeIndex()); 146 assert(Record.getVTableShape() == TypeIndex()); 147 } 148 Builder.writeEncodedUnsignedInteger(Record.getSize()); 149 Builder.writeNullTerminatedString(Record.getName()); 150 if ((Record.getOptions() & ClassOptions::HasUniqueName) != 151 ClassOptions::None) { 152 Builder.writeNullTerminatedString(Record.getUniqueName()); 153 } 154 155 return writeRecord(Builder); 156} 157 158TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) { 159 TypeRecordBuilder Builder(TypeRecordKind::Enum); 160 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()); 169 } 170 171 return writeRecord(Builder); 172} 173 174TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) { 175 TypeRecordBuilder Builder(TypeRecordKind::BitField); 176 177 Builder.writeTypeIndex(Record.getType()); 178 Builder.writeUInt8(Record.getBitSize()); 179 Builder.writeUInt8(Record.getBitOffset()); 180 181 return writeRecord(Builder); 182} 183 184TypeIndex TypeTableBuilder::writeVirtualTableShape( 185 const VirtualTableShapeRecord &Record) { 186 TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape); 187 188 ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots(); 189 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]); 195 } 196 Builder.writeUInt8(Byte); 197 } 198 199 return writeRecord(Builder); 200} 201 202TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) { 203 return writeRecord(Builder.str()); 204} 205 206TypeIndex 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()); 210} 211 212TypeIndex 213TypeTableBuilder::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()); 217} 218