diff options
Diffstat (limited to 'gnu/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp')
| -rw-r--r-- | gnu/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/gnu/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp b/gnu/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp deleted file mode 100644 index f180fc6990f..00000000000 --- a/gnu/llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp +++ /dev/null @@ -1,259 +0,0 @@ -#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h" - -using namespace llvm; -using namespace llvm::codeview; - -namespace { -struct ContinuationRecord { - ulittle16_t Kind{uint16_t(TypeLeafKind::LF_INDEX)}; - ulittle16_t Size{0}; - ulittle32_t IndexRef{0xB0C0B0C0}; -}; - -struct SegmentInjection { - SegmentInjection(TypeLeafKind Kind) { Prefix.RecordKind = Kind; } - - ContinuationRecord Cont; - RecordPrefix Prefix; -}; -} // namespace - -static void addPadding(BinaryStreamWriter &Writer) { - uint32_t Align = Writer.getOffset() % 4; - if (Align == 0) - return; - - int PaddingBytes = 4 - Align; - while (PaddingBytes > 0) { - uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); - cantFail(Writer.writeInteger(Pad)); - --PaddingBytes; - } -} - -static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST); -static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST); - -static constexpr uint32_t ContinuationLength = sizeof(ContinuationRecord); -static constexpr uint32_t MaxSegmentLength = - MaxRecordLength - ContinuationLength; - -static inline TypeLeafKind getTypeLeafKind(ContinuationRecordKind CK) { - return (CK == ContinuationRecordKind::FieldList) ? LF_FIELDLIST - : LF_METHODLIST; -} - -ContinuationRecordBuilder::ContinuationRecordBuilder() - : SegmentWriter(Buffer), Mapping(SegmentWriter) {} - -ContinuationRecordBuilder::~ContinuationRecordBuilder() {} - -void ContinuationRecordBuilder::begin(ContinuationRecordKind RecordKind) { - assert(!Kind.hasValue()); - Kind = RecordKind; - Buffer.clear(); - SegmentWriter.setOffset(0); - SegmentOffsets.clear(); - SegmentOffsets.push_back(0); - assert(SegmentWriter.getOffset() == 0); - assert(SegmentWriter.getLength() == 0); - - const SegmentInjection *FLI = - (RecordKind == ContinuationRecordKind::FieldList) - ? &InjectFieldList - : &InjectMethodOverloadList; - const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI); - InjectedSegmentBytes = - ArrayRef<uint8_t>(FLIB, FLIB + sizeof(SegmentInjection)); - - CVType Type; - Type.Type = getTypeLeafKind(RecordKind); - cantFail(Mapping.visitTypeBegin(Type)); - - // Seed the first trecord with an appropriate record prefix. - RecordPrefix Prefix; - Prefix.RecordLen = 0; - Prefix.RecordKind = Type.Type; - cantFail(SegmentWriter.writeObject(Prefix)); -} - -template <typename RecordType> -void ContinuationRecordBuilder::writeMemberType(RecordType &Record) { - assert(Kind.hasValue()); - - uint32_t OriginalOffset = SegmentWriter.getOffset(); - CVMemberRecord CVMR; - CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); - - // Member Records aren't length-prefixed, they only have a 2-byte TypeLeafKind - // at the beginning. - cantFail(SegmentWriter.writeEnum(CVMR.Kind)); - - // Let the Mapping handle the rest. - cantFail(Mapping.visitMemberBegin(CVMR)); - cantFail(Mapping.visitKnownMember(CVMR, Record)); - cantFail(Mapping.visitMemberEnd(CVMR)); - - // Make sure it's padded to 4 bytes. - addPadding(SegmentWriter); - assert(getCurrentSegmentLength() % 4 == 0); - - // The maximum length of a single segment is 64KB minus the size to insert a - // continuation. So if we are over that, inject a continuation between the - // previous member and the member that was just written, then end the previous - // segment after the continuation and begin a new one with the just-written - // member. - if (getCurrentSegmentLength() > MaxSegmentLength) { - // We need to inject some bytes before the member we just wrote but after - // the previous member. Save off the length of the member we just wrote so - // that we can do some sanity checking on it. - uint32_t MemberLength = SegmentWriter.getOffset() - OriginalOffset; - (void) MemberLength; - insertSegmentEnd(OriginalOffset); - // Since this member now becomes a new top-level record, it should have - // gotten a RecordPrefix injected, and that RecordPrefix + the member we - // just wrote should now constitute the entirety of the current "new" - // segment. - assert(getCurrentSegmentLength() == MemberLength + sizeof(RecordPrefix)); - } - - assert(getCurrentSegmentLength() % 4 == 0); - assert(getCurrentSegmentLength() <= MaxSegmentLength); -} - -uint32_t ContinuationRecordBuilder::getCurrentSegmentLength() const { - return SegmentWriter.getOffset() - SegmentOffsets.back(); -} - -void ContinuationRecordBuilder::insertSegmentEnd(uint32_t Offset) { - uint32_t SegmentBegin = SegmentOffsets.back(); - (void)SegmentBegin; - assert(Offset > SegmentBegin); - assert(Offset - SegmentBegin <= MaxSegmentLength); - - // We need to make space for the continuation record. For now we can't fill - // out the length or the TypeIndex of the back-reference, but we need the - // space to at least be there. - Buffer.insert(Offset, InjectedSegmentBytes); - - uint32_t NewSegmentBegin = Offset + ContinuationLength; - uint32_t SegmentLength = NewSegmentBegin - SegmentOffsets.back(); - (void) SegmentLength; - - assert(SegmentLength % 4 == 0); - assert(SegmentLength <= MaxRecordLength); - SegmentOffsets.push_back(NewSegmentBegin); - - // Seek to the end so that we can keep writing against the new segment. - SegmentWriter.setOffset(SegmentWriter.getLength()); - assert(SegmentWriter.bytesRemaining() == 0); -} - -CVType ContinuationRecordBuilder::createSegmentRecord( - uint32_t OffBegin, uint32_t OffEnd, Optional<TypeIndex> RefersTo) { - assert(OffEnd - OffBegin <= USHRT_MAX); - - MutableArrayRef<uint8_t> Data = Buffer.data(); - Data = Data.slice(OffBegin, OffEnd - OffBegin); - - CVType Type; - Type.Type = getTypeLeafKind(*Kind); - Type.RecordData = Data; - - // Write the length to the RecordPrefix, making sure it does not include - // sizeof(RecordPrefix.Length) - RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(Data.data()); - assert(Prefix->RecordKind == Type.Type); - Prefix->RecordLen = Data.size() - sizeof(RecordPrefix::RecordLen); - - if (RefersTo.hasValue()) { - auto Continuation = Data.take_back(ContinuationLength); - ContinuationRecord *CR = - reinterpret_cast<ContinuationRecord *>(Continuation.data()); - assert(CR->Kind == TypeLeafKind::LF_INDEX); - assert(CR->IndexRef == 0xB0C0B0C0); - CR->IndexRef = RefersTo->getIndex(); - } - - return Type; -} - -std::vector<CVType> ContinuationRecordBuilder::end(TypeIndex Index) { - CVType Type; - Type.Type = getTypeLeafKind(*Kind); - cantFail(Mapping.visitTypeEnd(Type)); - - // We're now done, and we have a series of segments each beginning at an - // offset specified in the SegmentOffsets array. We now need to iterate - // over each segment and post-process them in the following two ways: - // 1) Each top-level record has a RecordPrefix whose type is either - // LF_FIELDLIST or LF_METHODLIST, but the Length field is still 0. - // Those should all be set to the correct length now. - // 2) Each continuation record has an IndexRef field which we set to the - // magic value 0xB0C0B0C0. Now that the caller has told us the TypeIndex - // they want this sequence to start from, we can go through and update - // each one. - // - // Logically, the sequence of records we've built up looks like this: - // - // SegmentOffsets[0]: <Length> (Initially: uninitialized) - // SegmentOffsets[0]+2: LF_FIELDLIST - // SegmentOffsets[0]+4: Member[0] - // SegmentOffsets[0]+?: ... - // SegmentOffsets[0]+?: Member[4] - // SegmentOffsets[1]-8: LF_INDEX - // SegmentOffsets[1]-6: 0 - // SegmentOffsets[1]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0) - // - // SegmentOffsets[1]: <Length> (Initially: uninitialized) - // SegmentOffsets[1]+2: LF_FIELDLIST - // SegmentOffsets[1]+4: Member[0] - // SegmentOffsets[1]+?: ... - // SegmentOffsets[1]+?: Member[s] - // SegmentOffsets[2]-8: LF_INDEX - // SegmentOffsets[2]-6: 0 - // SegmentOffsets[2]-4: <Type Index of Next Record> (Initially: 0xB0C0B0C0) - // - // ... - // - // SegmentOffsets[N]: <Length> (Initially: uninitialized) - // SegmentOffsets[N]+2: LF_FIELDLIST - // SegmentOffsets[N]+4: Member[0] - // SegmentOffsets[N]+?: ... - // SegmentOffsets[N]+?: Member[t] - // - // And this is the way we have laid them out in the serialization buffer. But - // we cannot actually commit them to the underlying stream this way, due to - // the topological sorting requirement of a type stream (specifically, - // TypeIndex references can only point backwards, not forwards). So the - // sequence that we return to the caller contains the records in reverse - // order, which is the proper order for committing the serialized records. - - std::vector<CVType> Types; - Types.reserve(SegmentOffsets.size()); - - auto SO = makeArrayRef(SegmentOffsets); - - uint32_t End = SegmentWriter.getOffset(); - - Optional<TypeIndex> RefersTo; - for (uint32_t Offset : reverse(SO)) { - Types.push_back(createSegmentRecord(Offset, End, RefersTo)); - - End = Offset; - RefersTo = Index++; - } - - Kind.reset(); - return Types; -} - -// Explicitly instantiate the member function for each known type so that we can -// implement this in the cpp file. -#define TYPE_RECORD(EnumName, EnumVal, Name) -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD(EnumName, EnumVal, Name) \ - template void llvm::codeview::ContinuationRecordBuilder::writeMemberType( \ - Name##Record &Record); -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" |
