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