Home | History | Annotate | Download | only in CodeView
      1 //===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
     11 #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
     12 
     13 #include "llvm/ADT/ArrayRef.h"
     14 #include "llvm/DebugInfo/CodeView/CodeView.h"
     15 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
     16 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
     17 #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
     18 #include "llvm/Support/Allocator.h"
     19 #include "llvm/Support/Error.h"
     20 #include <algorithm>
     21 #include <cassert>
     22 #include <cstdint>
     23 #include <type_traits>
     24 
     25 namespace llvm {
     26 namespace codeview {
     27 
     28 class TypeTableBuilder {
     29 private:
     30   TypeIndex handleError(Error EC) const {
     31     assert(false && "Couldn't write Type!");
     32     consumeError(std::move(EC));
     33     return TypeIndex();
     34   }
     35 
     36   BumpPtrAllocator &Allocator;
     37   TypeSerializer Serializer;
     38 
     39 public:
     40   explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
     41                             bool WriteUnique = true)
     42       : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
     43   TypeTableBuilder(const TypeTableBuilder &) = delete;
     44   TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
     45 
     46   bool empty() const { return Serializer.records().empty(); }
     47 
     48   BumpPtrAllocator &getAllocator() const { return Allocator; }
     49 
     50   template <typename T> TypeIndex writeKnownType(T &Record) {
     51     static_assert(!std::is_same<T, FieldListRecord>::value,
     52                   "Can't serialize FieldList!");
     53 
     54     CVType Type;
     55     Type.Type = static_cast<TypeLeafKind>(Record.getKind());
     56     if (auto EC = Serializer.visitTypeBegin(Type))
     57       return handleError(std::move(EC));
     58     if (auto EC = Serializer.visitKnownRecord(Type, Record))
     59       return handleError(std::move(EC));
     60 
     61     auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
     62     if (!ExpectedIndex)
     63       return handleError(ExpectedIndex.takeError());
     64 
     65     return *ExpectedIndex;
     66   }
     67 
     68   TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
     69     return Serializer.insertRecordBytes(Record);
     70   }
     71 
     72   TypeIndex writeSerializedRecord(const RemappedType &Record) {
     73     return Serializer.insertRecord(Record);
     74   }
     75 
     76   template <typename TFunc> void ForEachRecord(TFunc Func) {
     77     uint32_t Index = TypeIndex::FirstNonSimpleIndex;
     78 
     79     for (auto Record : Serializer.records()) {
     80       Func(TypeIndex(Index), Record);
     81       ++Index;
     82     }
     83   }
     84 
     85   ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
     86 };
     87 
     88 class FieldListRecordBuilder {
     89   TypeTableBuilder &TypeTable;
     90   BumpPtrAllocator Allocator;
     91   TypeSerializer TempSerializer;
     92   CVType Type;
     93 
     94 public:
     95   explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
     96       : TypeTable(TypeTable), TempSerializer(Allocator, false) {
     97     Type.Type = TypeLeafKind::LF_FIELDLIST;
     98   }
     99 
    100   void begin() {
    101     TempSerializer.reset();
    102 
    103     if (auto EC = TempSerializer.visitTypeBegin(Type))
    104       consumeError(std::move(EC));
    105   }
    106 
    107   template <typename T> void writeMemberType(T &Record) {
    108     CVMemberRecord CVMR;
    109     CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
    110     if (auto EC = TempSerializer.visitMemberBegin(CVMR))
    111       consumeError(std::move(EC));
    112     if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
    113       consumeError(std::move(EC));
    114     if (auto EC = TempSerializer.visitMemberEnd(CVMR))
    115       consumeError(std::move(EC));
    116   }
    117 
    118   TypeIndex end(bool Write) {
    119     TypeIndex Index;
    120     if (auto EC = TempSerializer.visitTypeEnd(Type)) {
    121       consumeError(std::move(EC));
    122       return TypeIndex();
    123     }
    124 
    125     if (Write) {
    126       for (auto Record : TempSerializer.records())
    127         Index = TypeTable.writeSerializedRecord(Record);
    128     }
    129 
    130     return Index;
    131   }
    132 };
    133 
    134 } // end namespace codeview
    135 } // end namespace llvm
    136 
    137 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
    138