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/TypeSerializer.h"
     17 #include "llvm/DebugInfo/CodeView/TypeRecord.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       : Allocator(Allocator), Serializer(Allocator) {}
     42   TypeTableBuilder(const TypeTableBuilder &) = delete;
     43   TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
     44 
     45   bool empty() const { return Serializer.records().empty(); }
     46 
     47   BumpPtrAllocator &getAllocator() const { return Allocator; }
     48 
     49   template <typename T> TypeIndex writeKnownType(T &Record) {
     50     static_assert(!std::is_same<T, FieldListRecord>::value,
     51                   "Can't serialize FieldList!");
     52 
     53     CVType Type;
     54     Type.Type = static_cast<TypeLeafKind>(Record.getKind());
     55     if (auto EC = Serializer.visitTypeBegin(Type))
     56       return handleError(std::move(EC));
     57     if (auto EC = Serializer.visitKnownRecord(Type, Record))
     58       return handleError(std::move(EC));
     59 
     60     auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
     61     if (!ExpectedIndex)
     62       return handleError(ExpectedIndex.takeError());
     63 
     64     return *ExpectedIndex;
     65   }
     66 
     67   TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) {
     68     return Serializer.insertRecordBytes(Record);
     69   }
     70 
     71   template <typename TFunc> void ForEachRecord(TFunc Func) {
     72     uint32_t Index = TypeIndex::FirstNonSimpleIndex;
     73 
     74     for (auto Record : Serializer.records()) {
     75       Func(TypeIndex(Index), Record);
     76       ++Index;
     77     }
     78   }
     79 
     80   ArrayRef<MutableArrayRef<uint8_t>> records() const {
     81     return Serializer.records();
     82   }
     83 };
     84 
     85 class FieldListRecordBuilder {
     86   TypeTableBuilder &TypeTable;
     87   TypeSerializer TempSerializer;
     88   CVType Type;
     89 
     90 public:
     91   explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
     92       : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) {
     93     Type.Type = TypeLeafKind::LF_FIELDLIST;
     94   }
     95 
     96   void begin() {
     97     if (auto EC = TempSerializer.visitTypeBegin(Type))
     98       consumeError(std::move(EC));
     99   }
    100 
    101   template <typename T> void writeMemberType(T &Record) {
    102     CVMemberRecord CVMR;
    103     CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
    104     if (auto EC = TempSerializer.visitMemberBegin(CVMR))
    105       consumeError(std::move(EC));
    106     if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
    107       consumeError(std::move(EC));
    108     if (auto EC = TempSerializer.visitMemberEnd(CVMR))
    109       consumeError(std::move(EC));
    110   }
    111 
    112   TypeIndex end() {
    113     if (auto EC = TempSerializer.visitTypeEnd(Type)) {
    114       consumeError(std::move(EC));
    115       return TypeIndex();
    116     }
    117 
    118     TypeIndex Index;
    119     for (auto Record : TempSerializer.records()) {
    120       Index = TypeTable.writeSerializedRecord(Record);
    121     }
    122     return Index;
    123   }
    124 
    125   /// Stop building the record.
    126   void reset() {
    127     if (auto EC = TempSerializer.visitTypeEnd(Type))
    128       consumeError(std::move(EC));
    129   }
    130 };
    131 
    132 } // end namespace codeview
    133 } // end namespace llvm
    134 
    135 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
    136