10b57cec5SDimitry Andric //===- AppendingTypeTableBuilder.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
100b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
110b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h"
120b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
130b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeIndex.h"
140b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
1581ad6265SDimitry Andric #include "llvm/Support/ErrorHandling.h"
160b57cec5SDimitry Andric #include <cassert>
170b57cec5SDimitry Andric #include <cstdint>
180b57cec5SDimitry Andric #include <cstring>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric using namespace llvm::codeview;
220b57cec5SDimitry Andric 
nextTypeIndex() const230b57cec5SDimitry Andric TypeIndex AppendingTypeTableBuilder::nextTypeIndex() const {
240b57cec5SDimitry Andric   return TypeIndex::fromArrayIndex(SeenRecords.size());
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric 
AppendingTypeTableBuilder(BumpPtrAllocator & Storage)270b57cec5SDimitry Andric AppendingTypeTableBuilder::AppendingTypeTableBuilder(BumpPtrAllocator &Storage)
280b57cec5SDimitry Andric     : RecordStorage(Storage) {}
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric AppendingTypeTableBuilder::~AppendingTypeTableBuilder() = default;
310b57cec5SDimitry Andric 
getFirst()32bdd1243dSDimitry Andric std::optional<TypeIndex> AppendingTypeTableBuilder::getFirst() {
330b57cec5SDimitry Andric   if (empty())
34bdd1243dSDimitry Andric     return std::nullopt;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   return TypeIndex(TypeIndex::FirstNonSimpleIndex);
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
getNext(TypeIndex Prev)39bdd1243dSDimitry Andric std::optional<TypeIndex> AppendingTypeTableBuilder::getNext(TypeIndex Prev) {
400b57cec5SDimitry Andric   if (++Prev == nextTypeIndex())
41bdd1243dSDimitry Andric     return std::nullopt;
420b57cec5SDimitry Andric   return Prev;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
getType(TypeIndex Index)450b57cec5SDimitry Andric CVType AppendingTypeTableBuilder::getType(TypeIndex Index){
460b57cec5SDimitry Andric   return CVType(SeenRecords[Index.toArrayIndex()]);
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
getTypeName(TypeIndex Index)490b57cec5SDimitry Andric StringRef AppendingTypeTableBuilder::getTypeName(TypeIndex Index) {
500b57cec5SDimitry Andric   llvm_unreachable("Method not implemented");
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
contains(TypeIndex Index)530b57cec5SDimitry Andric bool AppendingTypeTableBuilder::contains(TypeIndex Index) {
540b57cec5SDimitry Andric   if (Index.isSimple() || Index.isNoneType())
550b57cec5SDimitry Andric     return false;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   return Index.toArrayIndex() < SeenRecords.size();
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
size()600b57cec5SDimitry Andric uint32_t AppendingTypeTableBuilder::size() { return SeenRecords.size(); }
610b57cec5SDimitry Andric 
capacity()620b57cec5SDimitry Andric uint32_t AppendingTypeTableBuilder::capacity() { return SeenRecords.size(); }
630b57cec5SDimitry Andric 
records() const640b57cec5SDimitry Andric ArrayRef<ArrayRef<uint8_t>> AppendingTypeTableBuilder::records() const {
650b57cec5SDimitry Andric   return SeenRecords;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
reset()680b57cec5SDimitry Andric void AppendingTypeTableBuilder::reset() { SeenRecords.clear(); }
690b57cec5SDimitry Andric 
stabilize(BumpPtrAllocator & RecordStorage,ArrayRef<uint8_t> Record)705ffd83dbSDimitry Andric static ArrayRef<uint8_t> stabilize(BumpPtrAllocator &RecordStorage,
715ffd83dbSDimitry Andric                                    ArrayRef<uint8_t> Record) {
725ffd83dbSDimitry Andric   uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size());
735ffd83dbSDimitry Andric   memcpy(Stable, Record.data(), Record.size());
745ffd83dbSDimitry Andric   return ArrayRef<uint8_t>(Stable, Record.size());
755ffd83dbSDimitry Andric }
765ffd83dbSDimitry Andric 
770b57cec5SDimitry Andric TypeIndex
insertRecordBytes(ArrayRef<uint8_t> & Record)780b57cec5SDimitry Andric AppendingTypeTableBuilder::insertRecordBytes(ArrayRef<uint8_t> &Record) {
790b57cec5SDimitry Andric   TypeIndex NewTI = nextTypeIndex();
805ffd83dbSDimitry Andric   Record = stabilize(RecordStorage, Record);
810b57cec5SDimitry Andric   SeenRecords.push_back(Record);
820b57cec5SDimitry Andric   return NewTI;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric TypeIndex
insertRecord(ContinuationRecordBuilder & Builder)860b57cec5SDimitry Andric AppendingTypeTableBuilder::insertRecord(ContinuationRecordBuilder &Builder) {
870b57cec5SDimitry Andric   TypeIndex TI;
880b57cec5SDimitry Andric   auto Fragments = Builder.end(nextTypeIndex());
890b57cec5SDimitry Andric   assert(!Fragments.empty());
900b57cec5SDimitry Andric   for (auto C : Fragments)
910b57cec5SDimitry Andric     TI = insertRecordBytes(C.RecordData);
920b57cec5SDimitry Andric   return TI;
930b57cec5SDimitry Andric }
945ffd83dbSDimitry Andric 
replaceType(TypeIndex & Index,CVType Data,bool Stabilize)955ffd83dbSDimitry Andric bool AppendingTypeTableBuilder::replaceType(TypeIndex &Index, CVType Data,
965ffd83dbSDimitry Andric                                             bool Stabilize) {
975ffd83dbSDimitry Andric   assert(Index.toArrayIndex() < SeenRecords.size() &&
985ffd83dbSDimitry Andric          "This function cannot be used to insert records!");
995ffd83dbSDimitry Andric 
1005ffd83dbSDimitry Andric   ArrayRef<uint8_t> Record = Data.data();
1015ffd83dbSDimitry Andric   if (Stabilize)
1025ffd83dbSDimitry Andric     Record = stabilize(RecordStorage, Record);
1035ffd83dbSDimitry Andric   SeenRecords[Index.toArrayIndex()] = Record;
1045ffd83dbSDimitry Andric   return true;
1055ffd83dbSDimitry Andric }
106