1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===-- ListRecordBuilder.cpp ---------------------------------------------===// 2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The LLVM Compiler Infrastructure 4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details. 7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/ADT/SmallString.h" 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h" 12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" 13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm; 15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace codeview; 16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : Kind(Kind), Builder(Kind) {} 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) { 21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TypeRecordBuilder &Builder = getBuilder(); 22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit"); 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation); 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeUInt16(0); 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeTypeIndex(R.getContinuationIndex()); 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // End the current segment manually so that nothing comes after the 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // continuation. 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ContinuationOffsets.push_back(Builder.size()); 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SubrecordStart = Builder.size(); 33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarvoid ListRecordBuilder::finishSubRecord() { 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // The type table inserts a 16 bit size field before each list, so factor that 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // into our alignment padding. 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t Remainder = 39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (Builder.size() + 2 * (ContinuationOffsets.size() + 1)) % 4; 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Remainder != 0) { 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0; 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar --PaddingBytesLeft) { 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeUInt8(LF_PAD0 + PaddingBytesLeft); 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check if this subrecord makes the current segment not fit in 64K minus the 48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // space for a continuation record (8 bytes). If the segment does not fit, 49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // back up and insert a continuation record, sliding the current subrecord 50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // down. 51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (getLastContinuationSize() > 65535 - 8) { 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(SubrecordStart != 0 && "can't slide from the start!"); 53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SmallString<128> SubrecordCopy( 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.str().slice(SubrecordStart, Builder.size())); 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(SubrecordCopy.size() < 65530 && "subrecord is too large to slide!"); 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.truncate(SubrecordStart); 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Write a placeholder continuation record. 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeTypeRecordKind(TypeRecordKind::ListContinuation); 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeUInt16(0); 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeUInt32(0); 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ContinuationOffsets.push_back(Builder.size()); 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(Builder.size() == SubrecordStart + 8 && "wrong continuation size"); 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(getLastContinuationSize() < 65535 && "segment too big"); 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Start a new list record of the appropriate kind, and copy the previous 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // subrecord into place. 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeTypeRecordKind(Kind); 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Builder.writeBytes(SubrecordCopy); 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SubrecordStart = Builder.size(); 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarTypeIndex ListRecordBuilder::writeListRecord(TypeTableBuilder &Table) { 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Get the continuation segments as a reversed vector of StringRefs for 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // convenience. 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SmallVector<StringRef, 1> Segments; 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef Data = str(); 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar size_t LastEnd = 0; 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (size_t SegEnd : ContinuationOffsets) { 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Segments.push_back(Data.slice(LastEnd, SegEnd)); 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LastEnd = SegEnd; 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar Segments.push_back(Data.slice(LastEnd, Builder.size())); 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Pop the last record off and emit it directly. 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar StringRef LastRec = Segments.pop_back_val(); 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar TypeIndex ContinuationIndex = Table.writeRecord(LastRec); 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Emit each record with a continuation in reverse order, so that each one 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // references the previous record. 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (StringRef Rec : reverse(Segments)) { 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(*reinterpret_cast<const ulittle16_t *>(Rec.data()) == 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unsigned(Kind)); 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t *ContinuationPtr = 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar reinterpret_cast<ulittle32_t *>(const_cast<char *>(Rec.end())) - 1; 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar *ContinuationPtr = ContinuationIndex.getIndex(); 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ContinuationIndex = Table.writeRecord(Rec); 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return ContinuationIndex; 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 103