1311116Sdim//===- TypeDeserializer.h ---------------------------------------*- C++ -*-===// 2311116Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311116Sdim// 7311116Sdim//===----------------------------------------------------------------------===// 8311116Sdim 9311116Sdim#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H 10311116Sdim#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H 11311116Sdim 12311116Sdim#include "llvm/ADT/ArrayRef.h" 13311116Sdim#include "llvm/ADT/STLExtras.h" 14311116Sdim#include "llvm/DebugInfo/CodeView/CodeView.h" 15311116Sdim#include "llvm/DebugInfo/CodeView/TypeRecord.h" 16311116Sdim#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" 17311116Sdim#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" 18321369Sdim#include "llvm/Support/BinaryByteStream.h" 19321369Sdim#include "llvm/Support/BinaryStreamReader.h" 20311116Sdim#include "llvm/Support/Error.h" 21311116Sdim#include <cassert> 22311116Sdim#include <cstdint> 23311116Sdim#include <memory> 24311116Sdim 25311116Sdimnamespace llvm { 26311116Sdimnamespace codeview { 27311116Sdim 28311116Sdimclass TypeDeserializer : public TypeVisitorCallbacks { 29311116Sdim struct MappingInfo { 30311116Sdim explicit MappingInfo(ArrayRef<uint8_t> RecordData) 31321369Sdim : Stream(RecordData, llvm::support::little), Reader(Stream), 32321369Sdim Mapping(Reader) {} 33311116Sdim 34321369Sdim BinaryByteStream Stream; 35321369Sdim BinaryStreamReader Reader; 36311116Sdim TypeRecordMapping Mapping; 37311116Sdim }; 38311116Sdim 39311116Sdimpublic: 40311116Sdim TypeDeserializer() = default; 41311116Sdim 42321369Sdim template <typename T> static Error deserializeAs(CVType &CVT, T &Record) { 43321369Sdim Record.Kind = static_cast<TypeRecordKind>(CVT.kind()); 44321369Sdim MappingInfo I(CVT.content()); 45321369Sdim if (auto EC = I.Mapping.visitTypeBegin(CVT)) 46321369Sdim return EC; 47321369Sdim if (auto EC = I.Mapping.visitKnownRecord(CVT, Record)) 48321369Sdim return EC; 49321369Sdim if (auto EC = I.Mapping.visitTypeEnd(CVT)) 50321369Sdim return EC; 51321369Sdim return Error::success(); 52321369Sdim } 53321369Sdim 54327952Sdim template <typename T> 55327952Sdim static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) { 56327952Sdim const RecordPrefix *Prefix = 57327952Sdim reinterpret_cast<const RecordPrefix *>(Data.data()); 58327952Sdim TypeRecordKind K = 59327952Sdim static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind)); 60327952Sdim T Record(K); 61353358Sdim CVType CVT(Data); 62327952Sdim if (auto EC = deserializeAs<T>(CVT, Record)) 63327952Sdim return std::move(EC); 64327952Sdim return Record; 65327952Sdim } 66327952Sdim 67311116Sdim Error visitTypeBegin(CVType &Record) override { 68311116Sdim assert(!Mapping && "Already in a type mapping!"); 69360784Sdim Mapping = std::make_unique<MappingInfo>(Record.content()); 70311116Sdim return Mapping->Mapping.visitTypeBegin(Record); 71311116Sdim } 72311116Sdim 73321369Sdim Error visitTypeBegin(CVType &Record, TypeIndex Index) override { 74321369Sdim return visitTypeBegin(Record); 75321369Sdim } 76321369Sdim 77311116Sdim Error visitTypeEnd(CVType &Record) override { 78311116Sdim assert(Mapping && "Not in a type mapping!"); 79311116Sdim auto EC = Mapping->Mapping.visitTypeEnd(Record); 80311116Sdim Mapping.reset(); 81311116Sdim return EC; 82311116Sdim } 83311116Sdim 84311116Sdim#define TYPE_RECORD(EnumName, EnumVal, Name) \ 85311116Sdim Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \ 86311116Sdim return visitKnownRecordImpl<Name##Record>(CVR, Record); \ 87311116Sdim } 88311116Sdim#define MEMBER_RECORD(EnumName, EnumVal, Name) 89311116Sdim#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 90311116Sdim#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 91321369Sdim#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 92311116Sdim 93311116Sdimprivate: 94311116Sdim template <typename RecordType> 95311116Sdim Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) { 96311116Sdim return Mapping->Mapping.visitKnownRecord(CVR, Record); 97311116Sdim } 98311116Sdim 99311116Sdim std::unique_ptr<MappingInfo> Mapping; 100311116Sdim}; 101311116Sdim 102311116Sdimclass FieldListDeserializer : public TypeVisitorCallbacks { 103311116Sdim struct MappingInfo { 104321369Sdim explicit MappingInfo(BinaryStreamReader &R) 105311116Sdim : Reader(R), Mapping(Reader), StartOffset(0) {} 106311116Sdim 107321369Sdim BinaryStreamReader &Reader; 108311116Sdim TypeRecordMapping Mapping; 109311116Sdim uint32_t StartOffset; 110311116Sdim }; 111311116Sdim 112311116Sdimpublic: 113321369Sdim explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) { 114353358Sdim RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST)); 115353358Sdim CVType FieldList(&Pre, sizeof(Pre)); 116311116Sdim consumeError(Mapping.Mapping.visitTypeBegin(FieldList)); 117311116Sdim } 118311116Sdim 119311116Sdim ~FieldListDeserializer() override { 120353358Sdim RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST)); 121353358Sdim CVType FieldList(&Pre, sizeof(Pre)); 122311116Sdim consumeError(Mapping.Mapping.visitTypeEnd(FieldList)); 123311116Sdim } 124311116Sdim 125311116Sdim Error visitMemberBegin(CVMemberRecord &Record) override { 126311116Sdim Mapping.StartOffset = Mapping.Reader.getOffset(); 127311116Sdim return Mapping.Mapping.visitMemberBegin(Record); 128311116Sdim } 129311116Sdim 130311116Sdim Error visitMemberEnd(CVMemberRecord &Record) override { 131311116Sdim if (auto EC = Mapping.Mapping.visitMemberEnd(Record)) 132311116Sdim return EC; 133311116Sdim return Error::success(); 134311116Sdim } 135311116Sdim 136311116Sdim#define TYPE_RECORD(EnumName, EnumVal, Name) 137311116Sdim#define MEMBER_RECORD(EnumName, EnumVal, Name) \ 138311116Sdim Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \ 139311116Sdim return visitKnownMemberImpl<Name##Record>(CVR, Record); \ 140311116Sdim } 141311116Sdim#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 142311116Sdim#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 143321369Sdim#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" 144311116Sdim 145311116Sdimprivate: 146311116Sdim template <typename RecordType> 147311116Sdim Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) { 148311116Sdim if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record)) 149311116Sdim return EC; 150311116Sdim 151311116Sdim uint32_t EndOffset = Mapping.Reader.getOffset(); 152311116Sdim uint32_t RecordLength = EndOffset - Mapping.StartOffset; 153311116Sdim Mapping.Reader.setOffset(Mapping.StartOffset); 154311116Sdim if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength)) 155311116Sdim return EC; 156311116Sdim assert(Mapping.Reader.getOffset() == EndOffset); 157311116Sdim return Error::success(); 158311116Sdim } 159311116Sdim MappingInfo Mapping; 160311116Sdim}; 161311116Sdim 162311116Sdim} // end namespace codeview 163311116Sdim} // end namespace llvm 164311116Sdim 165311116Sdim#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H 166