Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp
Show All 20 Lines | |||||
static void addPadding(BinaryStreamWriter &Writer) { | static void addPadding(BinaryStreamWriter &Writer) { | ||||
uint32_t Align = Writer.getOffset() % 4; | uint32_t Align = Writer.getOffset() % 4; | ||||
if (Align == 0) | if (Align == 0) | ||||
return; | return; | ||||
int PaddingBytes = 4 - Align; | int PaddingBytes = 4 - Align; | ||||
while (PaddingBytes > 0) { | while (PaddingBytes > 0) { | ||||
uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); | uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); | ||||
cantFail(Writer.writeInteger(Pad)); | llvm_cantFail(Writer.writeInteger(Pad)); | ||||
--PaddingBytes; | --PaddingBytes; | ||||
} | } | ||||
} | } | ||||
static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST); | static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST); | ||||
static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST); | static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST); | ||||
static constexpr uint32_t ContinuationLength = sizeof(ContinuationRecord); | static constexpr uint32_t ContinuationLength = sizeof(ContinuationRecord); | ||||
Show All 26 Lines | const SegmentInjection *FLI = | ||||
: &InjectMethodOverloadList; | : &InjectMethodOverloadList; | ||||
const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI); | const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI); | ||||
InjectedSegmentBytes = | InjectedSegmentBytes = | ||||
ArrayRef<uint8_t>(FLIB, FLIB + sizeof(SegmentInjection)); | ArrayRef<uint8_t>(FLIB, FLIB + sizeof(SegmentInjection)); | ||||
// Seed the first record with an appropriate record prefix. | // Seed the first record with an appropriate record prefix. | ||||
RecordPrefix Prefix(getTypeLeafKind(RecordKind)); | RecordPrefix Prefix(getTypeLeafKind(RecordKind)); | ||||
CVType Type(&Prefix, sizeof(Prefix)); | CVType Type(&Prefix, sizeof(Prefix)); | ||||
cantFail(Mapping.visitTypeBegin(Type)); | llvm_cantFail(Mapping.visitTypeBegin(Type)); | ||||
cantFail(SegmentWriter.writeObject(Prefix)); | llvm_cantFail(SegmentWriter.writeObject(Prefix)); | ||||
} | } | ||||
template <typename RecordType> | template <typename RecordType> | ||||
void ContinuationRecordBuilder::writeMemberType(RecordType &Record) { | void ContinuationRecordBuilder::writeMemberType(RecordType &Record) { | ||||
assert(Kind.hasValue()); | assert(Kind.hasValue()); | ||||
uint32_t OriginalOffset = SegmentWriter.getOffset(); | uint32_t OriginalOffset = SegmentWriter.getOffset(); | ||||
CVMemberRecord CVMR; | CVMemberRecord CVMR; | ||||
CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); | CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind()); | ||||
// Member Records aren't length-prefixed, they only have a 2-byte TypeLeafKind | // Member Records aren't length-prefixed, they only have a 2-byte TypeLeafKind | ||||
// at the beginning. | // at the beginning. | ||||
cantFail(SegmentWriter.writeEnum(CVMR.Kind)); | llvm_cantFail(SegmentWriter.writeEnum(CVMR.Kind)); | ||||
// Let the Mapping handle the rest. | // Let the Mapping handle the rest. | ||||
cantFail(Mapping.visitMemberBegin(CVMR)); | llvm_cantFail(Mapping.visitMemberBegin(CVMR)); | ||||
cantFail(Mapping.visitKnownMember(CVMR, Record)); | llvm_cantFail(Mapping.visitKnownMember(CVMR, Record)); | ||||
cantFail(Mapping.visitMemberEnd(CVMR)); | llvm_cantFail(Mapping.visitMemberEnd(CVMR)); | ||||
// Make sure it's padded to 4 bytes. | // Make sure it's padded to 4 bytes. | ||||
addPadding(SegmentWriter); | addPadding(SegmentWriter); | ||||
assert(getCurrentSegmentLength() % 4 == 0); | assert(getCurrentSegmentLength() % 4 == 0); | ||||
// The maximum length of a single segment is 64KB minus the size to insert a | // 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 | // 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 | // previous member and the member that was just written, then end the previous | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | CVType ContinuationRecordBuilder::createSegmentRecord( | ||||
} | } | ||||
return CVType(Data); | return CVType(Data); | ||||
} | } | ||||
std::vector<CVType> ContinuationRecordBuilder::end(TypeIndex Index) { | std::vector<CVType> ContinuationRecordBuilder::end(TypeIndex Index) { | ||||
RecordPrefix Prefix(getTypeLeafKind(*Kind)); | RecordPrefix Prefix(getTypeLeafKind(*Kind)); | ||||
CVType Type(&Prefix, sizeof(Prefix)); | CVType Type(&Prefix, sizeof(Prefix)); | ||||
cantFail(Mapping.visitTypeEnd(Type)); | llvm_cantFail(Mapping.visitTypeEnd(Type)); | ||||
// We're now done, and we have a series of segments each beginning at an | // 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 | // offset specified in the SegmentOffsets array. We now need to iterate | ||||
// over each segment and post-process them in the following two ways: | // over each segment and post-process them in the following two ways: | ||||
// 1) Each top-level record has a RecordPrefix whose type is either | // 1) Each top-level record has a RecordPrefix whose type is either | ||||
// LF_FIELDLIST or LF_METHODLIST, but the Length field is still 0. | // LF_FIELDLIST or LF_METHODLIST, but the Length field is still 0. | ||||
// Those should all be set to the correct length now. | // Those should all be set to the correct length now. | ||||
// 2) Each continuation record has an IndexRef field which we set to the | // 2) Each continuation record has an IndexRef field which we set to the | ||||
▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines |