diff options
Diffstat (limited to 'llvm/lib/DebugInfo')
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp | 65 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp | 41 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp | 132 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp | 103 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp | 46 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp | 49 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp | 119 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp | 100 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp | 243 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp | 300 |
13 files changed, 374 insertions, 850 deletions
diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 4bbc48d111f..12675c3c631 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -4,21 +4,16 @@ add_llvm_library(LLVMDebugInfoCodeView CVSymbolVisitor.cpp CVTypeVisitor.cpp EnumTables.cpp - FieldListRecordBuilder.cpp Line.cpp - ListRecordBuilder.cpp - MemoryTypeTableBuilder.cpp - MethodListRecordBuilder.cpp ModuleSubstream.cpp ModuleSubstreamVisitor.cpp RecordSerialization.cpp SymbolDumper.cpp TypeDumper.cpp TypeRecord.cpp - TypeRecordBuilder.cpp TypeRecordMapping.cpp + TypeSerializer.cpp TypeStreamMerger.cpp - TypeTableBuilder.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index 5f5d5fe35ef..5171e24f3aa 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -17,24 +17,6 @@ using namespace llvm; using namespace llvm::codeview; -template <typename T> -static Expected<CVMemberRecord> -deserializeMemberRecord(FieldListDeserializer &Deserializer, - msf::StreamReader &Reader, TypeLeafKind Kind) { - T MR(static_cast<TypeRecordKind>(Kind)); - CVMemberRecord CVR; - CVR.Kind = Kind; - - if (auto EC = Deserializer.visitMemberBegin(CVR)) - return std::move(EC); - if (auto EC = Deserializer.visitKnownMember(CVR, MR)) - return std::move(EC); - if (auto EC = Deserializer.visitMemberEnd(CVR)) - return std::move(EC); - - return CVR; -} - CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) : Callbacks(Callbacks) {} @@ -85,7 +67,8 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) { return Error::success(); } -Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) { +static Error visitMemberRecord(CVMemberRecord &Record, + TypeVisitorCallbacks &Callbacks) { if (auto EC = Callbacks.visitMemberBegin(Record)) return EC; @@ -113,6 +96,10 @@ Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) { return Error::success(); } +Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) { + return ::visitMemberRecord(Record, Callbacks); +} + /// Visits the type records in Data. Sets the error flag on parse failures. Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) { for (auto I : Types) { @@ -122,23 +109,6 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) { return Error::success(); } -template <typename MR> -static Error visitKnownMember(FieldListDeserializer &Deserializer, - msf::StreamReader &Reader, TypeLeafKind Leaf, - TypeVisitorCallbacks &Callbacks) { - MR Record(static_cast<TypeRecordKind>(Leaf)); - CVMemberRecord CVR; - CVR.Kind = Leaf; - - if (auto EC = Callbacks.visitMemberBegin(CVR)) - return EC; - if (auto EC = Callbacks.visitKnownMember(CVR, Record)) - return EC; - if (auto EC = Callbacks.visitMemberEnd(CVR)) - return EC; - return Error::success(); -} - Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) { FieldListDeserializer Deserializer(Reader); TypeVisitorCallbackPipeline Pipeline; @@ -150,25 +120,12 @@ Error CVTypeVisitor::visitFieldListMemberStream(msf::StreamReader Reader) { if (auto EC = Reader.readEnum(Leaf)) return EC; - CVType Record; - switch (Leaf) { - default: - // Field list records do not describe their own length, so we cannot - // continue parsing past a type that we don't know how to deserialize. - return llvm::make_error<CodeViewError>( - cv_error_code::unknown_member_record); -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - case EnumName: { \ - if (auto EC = visitKnownMember<Name##Record>(Deserializer, Reader, Leaf, \ - Pipeline)) \ - return EC; \ - break; \ - } -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ - MEMBER_RECORD(EnumVal, EnumVal, AliasName) -#include "llvm/DebugInfo/CodeView/TypeRecords.def" - } + CVMemberRecord Record; + Record.Kind = Leaf; + if (auto EC = ::visitMemberRecord(Record, Pipeline)) + return EC; } + return Error::success(); } diff --git a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp index 7841e4f2f6a..19facaec9f0 100644 --- a/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ b/llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -16,20 +16,39 @@ using namespace llvm; using namespace llvm::codeview; -Error CodeViewRecordIO::beginRecord(uint16_t Kind) { - assert(!CurrentRecord.hasValue() && "There is already a record active!"); - CurrentRecord.emplace(); - - CurrentRecord->Kind = Kind; +Error CodeViewRecordIO::beginRecord(Optional<uint32_t> MaxLength) { + RecordLimit Limit; + Limit.MaxLength = MaxLength; + Limit.BeginOffset = getCurrentOffset(); + Limits.push_back(Limit); return Error::success(); } Error CodeViewRecordIO::endRecord() { - assert(CurrentRecord.hasValue() && "Not in a record!"); - CurrentRecord.reset(); + assert(!Limits.empty() && "Not in a record!"); + Limits.pop_back(); return Error::success(); } +uint32_t CodeViewRecordIO::maxFieldLength() const { + assert(!Limits.empty() && "Not in a record!"); + + // The max length of the next field is the minimum of all lengths that would + // be allowed by any of the sub-records we're in. In practice, we can only + // ever be at most 1 sub-record deep (in a FieldList), but this works for + // the general case. + uint32_t Offset = getCurrentOffset(); + Optional<uint32_t> Min = Limits.front().bytesRemaining(Offset); + for (auto X : makeArrayRef(Limits).drop_front()) { + Optional<uint32_t> ThisMin = X.bytesRemaining(Offset); + if (ThisMin.hasValue()) + Min = (Min.hasValue()) ? std::min(*Min, *ThisMin) : *ThisMin; + } + assert(Min.hasValue() && "Every field must have a maximum length!"); + + return *Min; +} + Error CodeViewRecordIO::skipPadding() { assert(!isWriting() && "Cannot skip padding while writing!"); @@ -114,7 +133,9 @@ Error CodeViewRecordIO::mapEncodedInteger(APSInt &Value) { Error CodeViewRecordIO::mapStringZ(StringRef &Value) { if (isWriting()) { - if (auto EC = Writer->writeZeroString(Value)) + // Truncate if we attempt to write too much. + StringRef S = Value.take_front(maxFieldLength() - 1); + if (auto EC = Writer->writeZeroString(S)) return EC; } else { if (auto EC = Reader->readZeroString(Value)) @@ -124,6 +145,10 @@ Error CodeViewRecordIO::mapStringZ(StringRef &Value) { } Error CodeViewRecordIO::mapGuid(StringRef &Guid) { + constexpr uint32_t GuidSize = 16; + if (maxFieldLength() < GuidSize) + return make_error<CodeViewError>(cv_error_code::insufficient_buffer); + if (isWriting()) { assert(Guid.size() == 16 && "Invalid Guid Size!"); if (auto EC = Writer->writeFixedString(Guid)) diff --git a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp deleted file mode 100644 index ac2ef3972b6..00000000000 --- a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//===-- 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::writeMemberType(const BaseClassRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(TypeRecordKind::BaseClass); - Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess())); - Builder.writeTypeIndex(Record.getBaseType()); - Builder.writeEncodedUnsignedInteger(Record.getBaseOffset()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType(const EnumeratorRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(TypeRecordKind::Enumerator); - Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess())); - // FIXME: Handle full APInt such as __int128. - Builder.writeEncodedUnsignedInteger(Record.getValue().getZExtValue()); - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType(const DataMemberRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(Record.getKind()); - Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess())); - Builder.writeTypeIndex(Record.getType()); - Builder.writeEncodedUnsignedInteger(Record.getFieldOffset()); - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType( - const OverloadedMethodRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod); - Builder.writeUInt16(Record.getNumOverloads()); - Builder.writeTypeIndex(Record.getMethodList()); - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType(const OneMethodRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - uint16_t Flags = static_cast<uint16_t>(Record.getAccess()); - Flags |= static_cast<uint16_t>(Record.getKind()) << MethodKindShift; - Flags |= static_cast<uint16_t>(Record.getOptions()); - - Builder.writeTypeRecordKind(TypeRecordKind::OneMethod); - Builder.writeUInt16(Flags); - Builder.writeTypeIndex(Record.getType()); - if (Record.isIntroducingVirtual()) { - assert(Record.getVFTableOffset() >= 0); - Builder.writeInt32(Record.getVFTableOffset()); - } else { - assert(Record.getVFTableOffset() == -1); - } - - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType(const NestedTypeRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(Record.getKind()); - Builder.writeUInt16(0); - Builder.writeTypeIndex(Record.getNestedType()); - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType( - const StaticDataMemberRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(Record.getKind()); - Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess())); - Builder.writeTypeIndex(Record.getType()); - Builder.writeNullTerminatedString(Record.getName()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType( - const VirtualBaseClassRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(Record.getKind()); - Builder.writeUInt16(static_cast<uint16_t>(Record.getAccess())); - Builder.writeTypeIndex(Record.getBaseType()); - Builder.writeTypeIndex(Record.getVBPtrType()); - Builder.writeEncodedInteger(Record.getVBPtrOffset()); - Builder.writeEncodedUnsignedInteger(Record.getVTableIndex()); - - finishSubRecord(); -} - -void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) { - TypeRecordBuilder &Builder = getBuilder(); - - Builder.writeTypeRecordKind(TypeRecordKind::VFPtr); - Builder.writeUInt16(0); - Builder.writeTypeIndex(Record.getType()); - - finishSubRecord(); -} diff --git a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp deleted file mode 100644 index efac32a0f86..00000000000 --- a/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//===-- 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/ADT/SmallString.h" -#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h" -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" - -using namespace llvm; -using namespace codeview; - -ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) - : Kind(Kind), Builder(Kind) {} - -void ListRecordBuilder::writeMemberType(const ListContinuationRecord &R) { - TypeRecordBuilder &Builder = getBuilder(); - - assert(getLastContinuationSize() < MaxRecordLength - 8 && "continuation won't fit"); - - Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation); - Builder.writeUInt16(0); - Builder.writeTypeIndex(R.getContinuationIndex()); - - // End the current segment manually so that nothing comes after the - // continuation. - ContinuationOffsets.push_back(Builder.size()); - SubrecordStart = Builder.size(); -} - -void ListRecordBuilder::finishSubRecord() { - // The type table inserts a 16 bit size field before each list, so factor that - // into our alignment padding. - uint32_t Remainder = - (Builder.size() + 2 * (ContinuationOffsets.size() + 1)) % 4; - if (Remainder != 0) { - for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0; - --PaddingBytesLeft) { - Builder.writeUInt8(LF_PAD0 + PaddingBytesLeft); - } - } - - // Check if this subrecord makes the current segment not fit in 64K minus the - // space for a continuation record (8 bytes). If the segment does not fit, - // back up and insert a continuation record, sliding the current subrecord - // down. - if (getLastContinuationSize() > MaxRecordLength - 8) { - assert(SubrecordStart != 0 && "can't slide from the start!"); - SmallString<128> SubrecordCopy( - Builder.str().slice(SubrecordStart, Builder.size())); - assert(SubrecordCopy.size() < MaxRecordLength - 8 && - "subrecord is too large to slide!"); - Builder.truncate(SubrecordStart); - - // Write a placeholder continuation record. - Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation); - Builder.writeUInt16(0); - Builder.writeUInt32(0); - ContinuationOffsets.push_back(Builder.size()); - assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size"); - assert(getLastContinuationSize() < MaxRecordLength && "segment too big"); - - // Start a new list record of the appropriate kind, and copy the previous - // subrecord into place. - Builder.writeTypeRecordKind(Kind); - Builder.writeBytes(SubrecordCopy); - } - - SubrecordStart = Builder.size(); -} - -TypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) { - // Get the continuation segments as a reversed vector of StringRefs for - // convenience. - SmallVector<StringRef, 1> Segments; - StringRef Data = str(); - size_t LastEnd = 0; - for (size_t SegEnd : ContinuationOffsets) { - Segments.push_back(Data.slice(LastEnd, SegEnd)); - LastEnd = SegEnd; - } - Segments.push_back(Data.slice(LastEnd, Builder.size())); - - // Pop the last record off and emit it directly. - StringRef LastRec = Segments.pop_back_val(); - TypeIndex ContinuationIndex = Table.writeRecord(LastRec); - - // Emit each record with a continuation in reverse order, so that each one - // references the previous record. - for (StringRef Rec : reverse(Segments)) { - assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) == - unsigned(Kind)); - ulittle32_t *ContinuationPtr = - reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1; - *ContinuationPtr = ContinuationIndex.getIndex(); - ContinuationIndex = Table.writeRecord(Rec); - } - return ContinuationIndex; -} diff --git a/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp deleted file mode 100644 index 8b9e73b94ff..00000000000 --- a/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===-- 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; - -TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) { - assert(Data.size() <= UINT16_MAX); - auto I = HashedRecords.find(Data); - if (I != HashedRecords.end()) { - return I->second; - } - - // The record provided by the user lacks the 2 byte size field prefix and is - // not padded to 4 bytes. Ultimately, that is what gets emitted in the object - // file, so pad it out now. - const int SizeOfRecLen = 2; - const int Align = 4; - int TotalSize = alignTo(Data.size() + SizeOfRecLen, Align); - assert(TotalSize - SizeOfRecLen <= UINT16_MAX); - char *Mem = - reinterpret_cast<char *>(RecordStorage.Allocate(TotalSize, Align)); - *reinterpret_cast<ulittle16_t *>(Mem) = uint16_t(TotalSize - SizeOfRecLen); - memcpy(Mem + SizeOfRecLen, Data.data(), Data.size()); - for (int I = Data.size() + SizeOfRecLen; I < TotalSize; ++I) - Mem[I] = LF_PAD0 + (TotalSize - I); - - TypeIndex TI(static_cast<uint32_t>(Records.size()) + - TypeIndex::FirstNonSimpleIndex); - - // Use only the data supplied by the user as a key to the hash table, so that - // future lookups will succeed. - HashedRecords.insert(std::make_pair(StringRef(Mem + SizeOfRecLen, Data.size()), TI)); - Records.push_back(StringRef(Mem, TotalSize)); - - return TI; -} diff --git a/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp deleted file mode 100644 index ae089a35208..00000000000 --- a/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===-- 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::MethodOverloadList) {} - -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/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 84abad91c53..4274d834076 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -428,7 +428,7 @@ Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR, MethodOverloadListRecord &MethodList) { for (auto &M : MethodList.getMethods()) { ListScope S(*W, "Method"); - printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions()); + printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions()); printTypeIndex("Type", M.getType()); if (M.isIntroducingVirtual()) W->printHex("VFTableOffset", M.getVFTableOffset()); @@ -607,7 +607,7 @@ Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR, OneMethodRecord &Method) { - MethodKind K = Method.getKind(); + MethodKind K = Method.getMethodKind(); printMemberAttributes(Method.getAccess(), K, Method.getOptions()); printTypeIndex("Type", Method.getType()); // If virtual, then read the vftable offset. diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp deleted file mode 100644 index f775bdd8202..00000000000 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===-- 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) - : Kind(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(LF_CHAR); - writeInt16(static_cast<int8_t>(Value)); - } else if (Value >= std::numeric_limits<int16_t>::min() && - Value <= std::numeric_limits<int16_t>::max()) { - writeUInt16(LF_SHORT); - writeInt16(static_cast<int16_t>(Value)); - } else if (Value >= std::numeric_limits<int32_t>::min() && - Value <= std::numeric_limits<int32_t>::max()) { - writeUInt16(LF_LONG); - writeInt32(static_cast<int32_t>(Value)); - } else { - writeUInt16(LF_QUADWORD); - writeInt64(Value); - } -} - -void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) { - if (Value < LF_CHAR) { - writeUInt16(static_cast<uint16_t>(Value)); - } else if (Value <= std::numeric_limits<uint16_t>::max()) { - writeUInt16(LF_USHORT); - writeUInt16(static_cast<uint16_t>(Value)); - } else if (Value <= std::numeric_limits<uint32_t>::max()) { - writeUInt16(LF_ULONG); - writeUInt32(static_cast<uint32_t>(Value)); - } else { - writeUInt16(LF_UQUADWORD); - writeUInt64(Value); - } -} - -void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) { - // Usually the null terminated string comes last, so truncate it to avoid a - // record larger than MaxNameLength. Don't do this if this is a list record. - // Those have special handling to split the record. - unsigned MaxNameLength = MaxRecordLength; - if (Kind != TypeRecordKind::FieldList && - Kind != TypeRecordKind::MethodOverloadList) - MaxNameLength = maxBytesRemaining(); - assert(MaxNameLength > 0 && "need room for null terminator"); - Value = Value.take_front(MaxNameLength - 1); - Stream.write(Value.data(), Value.size()); - writeUInt8(0); -} - -void TypeRecordBuilder::writeGuid(StringRef Guid) { - assert(Guid.size() == 16); - Stream.write(Guid.data(), 16); -} - -void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) { - writeUInt32(TypeInd.getIndex()); -} - -void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) { - writeUInt16(static_cast<uint16_t>(Kind)); -} diff --git a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp index d85a643c6d2..f260ddad3fd 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -17,24 +17,6 @@ using namespace llvm::codeview; return EC; namespace { -struct MapStringZ { - Error operator()(CodeViewRecordIO &IO, StringRef &S) const { - return IO.mapStringZ(S); - } -}; - -struct MapInteger { - template <typename T> Error operator()(CodeViewRecordIO &IO, T &N) const { - return IO.mapInteger(N); - } -}; - -struct MapEnum { - template <typename T> Error operator()(CodeViewRecordIO &IO, T &N) const { - return IO.mapEnum(N); - } -}; - struct MapOneMethodRecord { explicit MapOneMethodRecord(bool IsFromOverloadList) : IsFromOverloadList(IsFromOverloadList) {} @@ -64,35 +46,97 @@ private: static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName) { - error(IO.mapStringZ(Name)); - if (HasUniqueName) - error(IO.mapStringZ(UniqueName)); + if (IO.isWriting()) { + // Try to be smart about what we write here. We can't write anything too + // large, so if we're going to go over the limit, truncate both the name + // and unique name by the same amount. + uint32_t BytesLeft = IO.maxFieldLength(); + if (HasUniqueName) { + uint32_t BytesNeeded = Name.size() + UniqueName.size() + 2; + StringRef N = Name; + StringRef U = UniqueName; + if (BytesNeeded > BytesLeft) { + uint32_t BytesToDrop = (BytesNeeded - BytesLeft); + uint32_t DropN = std::min(N.size(), BytesToDrop / 2); + uint32_t DropU = std::min(U.size(), BytesToDrop - DropN); + + N = N.drop_back(DropN); + U = U.drop_back(DropU); + } + + error(IO.mapStringZ(N)); + error(IO.mapStringZ(U)); + } else { + uint32_t BytesNeeded = Name.size() + 1; + StringRef N = Name; + if (BytesNeeded > BytesLeft) { + uint32_t BytesToDrop = std::min(N.size(), BytesToDrop); + N = N.drop_back(BytesToDrop); + } + error(IO.mapStringZ(N)); + } + } else { + error(IO.mapStringZ(Name)); + if (HasUniqueName) + error(IO.mapStringZ(UniqueName)); + } return Error::success(); } Error TypeRecordMapping::visitTypeBegin(CVType &CVR) { - error(IO.beginRecord(CVR.Type)); + assert(!TypeKind.hasValue() && "Already in a type mapping!"); + assert(!MemberKind.hasValue() && "Already in a member mapping!"); + + // FieldList and MethodList records can be any length because they can be + // split with continuation records. All other record types cannot be + // longer than the maximum record length. + Optional<uint32_t> MaxLen; + if (CVR.Type != TypeLeafKind::LF_FIELDLIST && + CVR.Type != TypeLeafKind::LF_METHODLIST) + MaxLen = MaxRecordLength - sizeof(RecordPrefix); + error(IO.beginRecord(MaxLen)); TypeKind = CVR.Type; return Error::success(); } Error TypeRecordMapping::visitTypeEnd(CVType &Record) { + assert(TypeKind.hasValue() && "Not in a type mapping!"); + assert(!MemberKind.hasValue() && "Still in a member mapping!"); + error(IO.endRecord()); + TypeKind.reset(); return Error::success(); } Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) { + assert(TypeKind.hasValue() && "Not in a type mapping!"); + assert(!MemberKind.hasValue() && "Already in a member mapping!"); + + // The largest possible subrecord is one in which there is a record prefix, + // followed by the subrecord, followed by a continuation, and that entire + // sequence spaws `MaxRecordLength` bytes. So the record's length is + // calculated as follows. + constexpr uint32_t ContinuationLength = 8; + error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) - + ContinuationLength)); + + MemberKind = Record.Kind; return Error::success(); } Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) { + assert(TypeKind.hasValue() && "Not in a type mapping!"); + assert(MemberKind.hasValue() && "Not in a member mapping!"); + if (!IO.isWriting()) { if (auto EC = IO.skipPadding()) return EC; } + MemberKind.reset(); + error(IO.endRecord()); return Error::success(); } @@ -129,7 +173,9 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) { - error(IO.mapVectorN<uint32_t>(Record.StringIndices, MapInteger())); + error(IO.mapVectorN<uint32_t>( + Record.StringIndices, + [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); })); return Error::success(); } @@ -245,7 +291,9 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) { NamesLen += Name.size() + 1; } error(IO.mapInteger(NamesLen)); - error(IO.mapVectorTail(Record.MethodNames, MapStringZ())); + error(IO.mapVectorTail( + Record.MethodNames, + [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); })); return Error::success(); } @@ -295,7 +343,9 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BuildInfoRecord &Record) { - error(IO.mapVectorN<uint16_t>(Record.ArgIndices, MapInteger())); + error(IO.mapVectorN<uint16_t>( + Record.ArgIndices, + [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); })); return Error::success(); } diff --git a/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp new file mode 100644 index 00000000000..f24fcff8627 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp @@ -0,0 +1,243 @@ +//===- TypeSerialzier.cpp ---------------------------------------*- C++ -*-===// +// +// 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/TypeSerializer.h" + +#include "llvm/DebugInfo/MSF/StreamWriter.h" + +#include <string.h> + +using namespace llvm; +using namespace llvm::codeview; + +bool TypeSerializer::isInFieldList() const { + return TypeKind.hasValue() && *TypeKind == TypeLeafKind::LF_FIELDLIST; +} + +TypeIndex TypeSerializer::calcNextTypeIndex() const { + if (LastTypeIndex.isNoneType()) + return TypeIndex(TypeIndex::FirstNonSimpleIndex); + else + return TypeIndex(LastTypeIndex.getIndex() + 1); +} + +TypeIndex TypeSerializer::incrementTypeIndex() { + TypeIndex Previous = LastTypeIndex; + LastTypeIndex = calcNextTypeIndex(); + return Previous; +} + +MutableArrayRef<uint8_t> TypeSerializer::getCurrentSubRecordData() { + assert(isInFieldList()); + return getCurrentRecordData().drop_front(CurrentSegment.length()); +} + +MutableArrayRef<uint8_t> TypeSerializer::getCurrentRecordData() { + return MutableArrayRef<uint8_t>(RecordBuffer).take_front(Writer.getOffset()); +} + +Error TypeSerializer::writeRecordPrefix(TypeLeafKind Kind) { + RecordPrefix Prefix; + Prefix.RecordKind = Kind; + Prefix.RecordLen = 0; + if (auto EC = Writer.writeObject(Prefix)) + return EC; + return Error::success(); +} + +TypeIndex +TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) { + assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!"); + + StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size()); + + TypeIndex NextTypeIndex = calcNextTypeIndex(); + auto Result = HashedRecords.try_emplace(S, NextTypeIndex); + if (Result.second) { + LastTypeIndex = NextTypeIndex; + SeenRecords.push_back(Record); + } + return Result.first->getValue(); +} + +Expected<MutableArrayRef<uint8_t>> +TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) { + uint32_t Align = Record.size() % 4; + if (Align == 0) + return Record; + + int PaddingBytes = 4 - Align; + int N = PaddingBytes; + while (PaddingBytes > 0) { + uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); + if (auto EC = Writer.writeInteger(Pad)) + return std::move(EC); + --PaddingBytes; + } + return MutableArrayRef<uint8_t>(Record.data(), Record.size() + N); +} + +TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage) + : RecordStorage(Storage), LastTypeIndex(), + RecordBuffer(MaxRecordLength * 2), Stream(RecordBuffer), Writer(Stream), + Mapping(Writer) { + // RecordBuffer needs to be able to hold enough data so that if we are 1 + // byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes, + // we won't overflow. +} + +ArrayRef<MutableArrayRef<uint8_t>> TypeSerializer::records() const { + return SeenRecords; +} + +TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; } + +TypeIndex TypeSerializer::insertRecordBytes(MutableArrayRef<uint8_t> Record) { + assert(!TypeKind.hasValue() && "Already in a type mapping!"); + assert(Writer.getOffset() == 0 && "Stream has data already!"); + + return insertRecordBytesPrivate(Record); +} + +Error TypeSerializer::visitTypeBegin(CVType &Record) { + assert(!TypeKind.hasValue() && "Already in a type mapping!"); + assert(Writer.getOffset() == 0 && "Stream has data already!"); + + if (auto EC = writeRecordPrefix(Record.kind())) + return EC; + + TypeKind = Record.kind(); + if (auto EC = Mapping.visitTypeBegin(Record)) + return EC; + + return Error::success(); +} + +Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) { + assert(TypeKind.hasValue() && "Not in a type mapping!"); + if (auto EC = Mapping.visitTypeEnd(Record)) + return std::move(EC); + + // Update the record's length and fill out the CVType members to point to + // the stable memory holding the record's data. + auto ThisRecordData = getCurrentRecordData(); + auto ExpectedData = addPadding(ThisRecordData); + if (!ExpectedData) + return ExpectedData.takeError(); + ThisRecordData = *ExpectedData; + + RecordPrefix *Prefix = + reinterpret_cast<RecordPrefix *>(ThisRecordData.data()); + Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t); + + uint8_t *Copy = RecordStorage.Allocate<uint8_t>(ThisRecordData.size()); + ::memcpy(Copy, ThisRecordData.data(), ThisRecordData.size()); + ThisRecordData = MutableArrayRef<uint8_t>(Copy, ThisRecordData.size()); + Record = CVType(*TypeKind, ThisRecordData); + TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(ThisRecordData); + + // Write out each additional segment in reverse order, and update each + // record's continuation index to point to the previous one. + for (auto X : reverse(FieldListSegments)) { + auto CIBytes = X.take_back(sizeof(uint32_t)); + support::ulittle32_t *CI = + reinterpret_cast<support::ulittle32_t *>(CIBytes.data()); + assert(*CI == 0xB0C0B0C0 && "Invalid TypeIndex placeholder"); + *CI = InsertedTypeIndex.getIndex(); + InsertedTypeIndex = insertRecordBytesPrivate(X); + } + + TypeKind.reset(); + Writer.setOffset(0); + FieldListSegments.clear(); + CurrentSegment.SubRecords.clear(); + + return InsertedTypeIndex; +} + +Error TypeSerializer::visitTypeEnd(CVType &Record) { + auto ExpectedIndex = visitTypeEndGetIndex(Record); + if (!ExpectedIndex) + return ExpectedIndex.takeError(); + return Error::success(); +} + +Error TypeSerializer::visitMemberBegin(CVMemberRecord &Record) { + assert(isInFieldList() && "Not in a field list!"); + assert(!MemberKind.hasValue() && "Already in a member record!"); + MemberKind = Record.Kind; + + if (auto EC = Mapping.visitMemberBegin(Record)) + return EC; + + return Error::success(); +} + +Error TypeSerializer::visitMemberEnd(CVMemberRecord &Record) { + if (auto EC = Mapping.visitMemberEnd(Record)) + return EC; + + // Check if this subrecord makes the current segment not fit in 64K minus + // the space for a continuation record (8 bytes). If the segment does not + // fit, insert a continuation record. + if (Writer.getOffset() > MaxRecordLength - ContinuationLength) { + MutableArrayRef<uint8_t> Data = getCurrentRecordData(); + SubRecord LastSubRecord = CurrentSegment.SubRecords.back(); + uint32_t CopySize = CurrentSegment.length() - LastSubRecord.Size; + auto CopyData = Data.take_front(CopySize); + auto LeftOverData = Data.drop_front(CopySize); + assert(LastSubRecord.Size == LeftOverData.size()); + + // Allocate stable storage for the record and copy the old record plus + // continuation over. + uint16_t LengthWithSize = CopySize + ContinuationLength; + assert(LengthWithSize <= MaxRecordLength); + RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(CopyData.data()); + Prefix->RecordLen = LengthWithSize - sizeof(uint16_t); + + uint8_t *SegmentBytes = RecordStorage.Allocate<uint8_t>(LengthWithSize); + auto SavedSegment = MutableArrayRef<uint8_t>(SegmentBytes, LengthWithSize); + msf::MutableByteStream CS(SavedSegment); + msf::StreamWriter CW(CS); + if (auto EC = CW.writeBytes(CopyData)) + return EC; + if (auto EC = CW.writeEnum(TypeLeafKind::LF_INDEX)) + return EC; + if (auto EC = CW.writeInteger(uint16_t(0))) + return EC; + if (auto EC = CW.writeInteger(uint32_t(0xB0C0B0C0))) + return EC; + FieldListSegments.push_back(SavedSegment); + + // Write a new placeholder record prefix to mark the start of this new + // top-level record. + Writer.setOffset(0); + if (auto EC = writeRecordPrefix(TypeLeafKind::LF_FIELDLIST)) + return EC; + + // Then move over the subrecord that overflowed the old segment to the + // beginning of this segment. Note that we have to use memmove here + // instead of Writer.writeBytes(), because the new and old locations + // could overlap. + ::memmove(Stream.data().data() + sizeof(RecordPrefix), LeftOverData.data(), + LeftOverData.size()); + // And point the segment writer at the end of that subrecord. + Writer.setOffset(LeftOverData.size() + sizeof(RecordPrefix)); + + CurrentSegment.SubRecords.clear(); + CurrentSegment.SubRecords.push_back(LastSubRecord); + } + + // Update the CVMemberRecord since we may have shifted around or gotten + // padded. + Record.Data = getCurrentSubRecordData(); + + MemberKind.reset(); + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 551a98a67c8..ed6cf5743a1 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -11,10 +11,10 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/Error.h" @@ -54,7 +54,8 @@ namespace { /// existing destination type index. class TypeStreamMerger : public TypeVisitorCallbacks { public: - TypeStreamMerger(TypeTableBuilder &DestStream) : DestStream(DestStream) { + TypeStreamMerger(TypeTableBuilder &DestStream) + : DestStream(DestStream), FieldListBuilder(DestStream) { assert(!hadError()); } @@ -94,7 +95,7 @@ private: template <typename RecordType> Error visitKnownMemberRecordImpl(RecordType &Record) { FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap); - FieldBuilder.writeMemberType(Record); + FieldListBuilder.writeMemberType(Record); return Error::success(); } @@ -102,9 +103,10 @@ private: bool FoundBadTypeIndex = false; - FieldListRecordBuilder FieldBuilder; + BumpPtrAllocator Allocator; TypeTableBuilder &DestStream; + FieldListRecordBuilder FieldListBuilder; bool IsInFieldList{false}; size_t BeginIndexMapSize = 0; @@ -120,6 +122,7 @@ Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) { if (Rec.Type == TypeLeafKind::LF_FIELDLIST) { assert(!IsInFieldList); IsInFieldList = true; + FieldListBuilder.begin(); } else BeginIndexMapSize = IndexMap.size(); return Error::success(); @@ -127,8 +130,8 @@ Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) { Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) { if (Rec.Type == TypeLeafKind::LF_FIELDLIST) { - IndexMap.push_back(DestStream.writeFieldList(FieldBuilder)); - FieldBuilder.reset(); + TypeIndex Index = FieldListBuilder.end(); + IndexMap.push_back(Index); IsInFieldList = false; } return Error::success(); diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp deleted file mode 100644 index 1bd0b3f4382..00000000000 --- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp +++ /dev/null @@ -1,300 +0,0 @@ -//===-- 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/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; - -TypeTableBuilder::TypeTableBuilder() {} - -TypeTableBuilder::~TypeTableBuilder() {} - -TypeIndex TypeTableBuilder::writeKnownType(const ModifierRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeTypeIndex(Record.getModifiedType()); - Builder.writeUInt16(static_cast<uint16_t>(Record.getModifiers())); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const ProcedureRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - 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::writeKnownType(const MemberFunctionRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - 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::writeKnownType(const ArgListRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeUInt32(Record.getIndices().size()); - for (TypeIndex TI : Record.getIndices()) { - Builder.writeTypeIndex(TI); - } - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeTypeIndex(Record.getReferentType()); - Builder.writeUInt32(Record.Attrs); - - if (Record.isPointerToMember()) { - const MemberPointerInfo &M = Record.getMemberInfo(); - Builder.writeTypeIndex(M.getContainingType()); - Builder.writeUInt16(static_cast<uint16_t>(M.getRepresentation())); - } - - return writeRecord(Builder); -} - -static void writeNameAndUniqueName(TypeRecordBuilder &Builder, ClassOptions CO, - StringRef Name, StringRef UniqueName) { - // Truncate the names to half the remaining record length. - unsigned MaxNameLength = Builder.maxBytesRemaining() / 2; - Name = Name.take_front(MaxNameLength - 1); - UniqueName = UniqueName.take_front(MaxNameLength - 1); - - Builder.writeNullTerminatedString(Name); - if ((CO & ClassOptions::HasUniqueName) != ClassOptions::None) { - Builder.writeNullTerminatedString(UniqueName); - } -} - -TypeIndex TypeTableBuilder::writeKnownType(const ArrayRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeTypeIndex(Record.getElementType()); - Builder.writeTypeIndex(Record.getIndexType()); - Builder.writeEncodedUnsignedInteger(Record.getSize()); - Builder.writeNullTerminatedString(Record.getName()); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const ClassRecord &Record) { - assert((Record.getKind() == TypeRecordKind::Struct) || - (Record.getKind() == TypeRecordKind::Class) || - (Record.getKind() == TypeRecordKind::Interface)); - - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeUInt16(Record.getMemberCount()); - uint16_t Flags = - static_cast<uint16_t>(Record.getOptions()) | - (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift) | - (static_cast<uint16_t>(Record.getWinRTKind()) - << ClassRecord::WinRTKindShift); - Builder.writeUInt16(Flags); - Builder.writeTypeIndex(Record.getFieldList()); - Builder.writeTypeIndex(Record.getDerivationList()); - Builder.writeTypeIndex(Record.getVTableShape()); - Builder.writeEncodedUnsignedInteger(Record.getSize()); - writeNameAndUniqueName(Builder, Record.getOptions(), Record.getName(), - Record.getUniqueName()); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const UnionRecord &Record) { - TypeRecordBuilder Builder(TypeRecordKind::Union); - Builder.writeUInt16(Record.getMemberCount()); - uint16_t Flags = - static_cast<uint16_t>(Record.getOptions()) | - (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift); - Builder.writeUInt16(Flags); - Builder.writeTypeIndex(Record.getFieldList()); - Builder.writeEncodedUnsignedInteger(Record.getSize()); - writeNameAndUniqueName(Builder, Record.getOptions(), Record.getName(), - Record.getUniqueName()); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const EnumRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeUInt16(Record.getMemberCount()); - Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions())); - Builder.writeTypeIndex(Record.getUnderlyingType()); - Builder.writeTypeIndex(Record.getFieldList()); - writeNameAndUniqueName(Builder, Record.getOptions(), Record.getName(), - Record.getUniqueName()); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const BitFieldRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - Builder.writeTypeIndex(Record.getType()); - Builder.writeUInt8(Record.getBitSize()); - Builder.writeUInt8(Record.getBitOffset()); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const VFTableShapeRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - - ArrayRef<VFTableSlotKind> 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::writeKnownType(const VFTableRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeTypeIndex(Record.getCompleteClass()); - Builder.writeTypeIndex(Record.getOverriddenVTable()); - Builder.writeUInt32(Record.getVFPtrOffset()); - - // Sum up the lengths of the null-terminated names. - size_t NamesLen = Record.getName().size() + 1; - for (StringRef MethodName : Record.getMethodNames()) - NamesLen += MethodName.size() + 1; - - // FIXME: Avoid creating a record longer than MaxRecordLength. - Builder.writeUInt32(NamesLen); - Builder.writeNullTerminatedString(Record.getName()); - for (StringRef MethodName : Record.getMethodNames()) - Builder.writeNullTerminatedString(MethodName); - - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const StringIdRecord &Record) { - TypeRecordBuilder Builder(TypeRecordKind::StringId); - Builder.writeTypeIndex(Record.getId()); - Builder.writeNullTerminatedString(Record.getString()); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const UdtSourceLineRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeTypeIndex(Record.getUDT()); - Builder.writeTypeIndex(Record.getSourceFile()); - Builder.writeUInt32(Record.getLineNumber()); - return writeRecord(Builder); -} - -TypeIndex -TypeTableBuilder::writeKnownType(const UdtModSourceLineRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeTypeIndex(Record.getUDT()); - Builder.writeTypeIndex(Record.getSourceFile()); - Builder.writeUInt32(Record.getLineNumber()); - Builder.writeUInt16(Record.getModule()); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const FuncIdRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeTypeIndex(Record.getParentScope()); - Builder.writeTypeIndex(Record.getFunctionType()); - Builder.writeNullTerminatedString(Record.getName()); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const MemberFuncIdRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeTypeIndex(Record.getClassType()); - Builder.writeTypeIndex(Record.getFunctionType()); - Builder.writeNullTerminatedString(Record.getName()); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const BuildInfoRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - assert(Record.getArgs().size() <= UINT16_MAX); - Builder.writeUInt16(Record.getArgs().size()); - for (TypeIndex Arg : Record.getArgs()) - Builder.writeTypeIndex(Arg); - return writeRecord(Builder); -} - -TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) { - TypeIndex I = writeRecord(Builder.str()); - RecordKinds.push_back(Builder.kind()); - return I; -} - -TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) { - TypeIndex I = FieldList.writeListRecord(*this); - RecordKinds.push_back(TypeRecordKind::FieldList); - return I; -} - -TypeIndex -TypeTableBuilder::writeKnownType(const MethodOverloadListRecord &Record) { - TypeRecordBuilder Builder(Record.getKind()); - for (const OneMethodRecord &Method : Record.getMethods()) { - uint16_t Flags = static_cast<uint16_t>(Method.getAccess()); - Flags |= static_cast<uint16_t>(Method.getKind()) - << MemberAttributes::MethodKindShift; - Flags |= static_cast<uint16_t>(Method.getOptions()); - Builder.writeUInt16(Flags); - Builder.writeUInt16(0); // padding - Builder.writeTypeIndex(Method.getType()); - if (Method.isIntroducingVirtual()) { - assert(Method.getVFTableOffset() >= 0); - Builder.writeInt32(Method.getVFTableOffset()); - } else { - assert(Method.getVFTableOffset() == -1); - } - } - - // 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(Builder); -} - -TypeIndex TypeTableBuilder::writeKnownType(const TypeServer2Record &Record) { - TypeRecordBuilder Builder(Record.getKind()); - Builder.writeGuid(Record.getGuid()); - Builder.writeUInt32(Record.getAge()); - Builder.writeNullTerminatedString(Record.getName()); - return writeRecord(Builder); -} |

