llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
Reid Kleckner 740c3d2411 [codeview] Use the correct max CV record length of 0xFF00
Previously we were splitting our records at 0xFFFF bytes, which the
Microsoft tools don't like.

Should fix failure on the new Windows self-host buildbot.

This length appears in microsoft-pdb/PDB/dbi/dbiimpl.h

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280522 91177308-0d34-0410-b5e6-96231b3b80d8
2016-09-02 18:43:27 +00:00

104 lines
3.8 KiB
C++

//===-- 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;
}