Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:40

0001 //===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
0010 #define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
0011 
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/STLExtras.h"
0014 #include "llvm/DebugInfo/CodeView/CodeView.h"
0015 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
0016 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
0017 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
0018 #include "llvm/Support/BinaryByteStream.h"
0019 #include "llvm/Support/BinaryStreamReader.h"
0020 #include "llvm/Support/Error.h"
0021 #include <cassert>
0022 #include <cstdint>
0023 #include <memory>
0024 
0025 namespace llvm {
0026 namespace codeview {
0027 
0028 class TypeDeserializer : public TypeVisitorCallbacks {
0029   struct MappingInfo {
0030     explicit MappingInfo(ArrayRef<uint8_t> RecordData)
0031         : Stream(RecordData, llvm::endianness::little), Reader(Stream),
0032           Mapping(Reader) {}
0033 
0034     BinaryByteStream Stream;
0035     BinaryStreamReader Reader;
0036     TypeRecordMapping Mapping;
0037   };
0038 
0039 public:
0040   TypeDeserializer() = default;
0041 
0042   template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
0043     Record.Kind = static_cast<TypeRecordKind>(CVT.kind());
0044     MappingInfo I(CVT.content());
0045     if (auto EC = I.Mapping.visitTypeBegin(CVT))
0046       return EC;
0047     if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
0048       return EC;
0049     if (auto EC = I.Mapping.visitTypeEnd(CVT))
0050       return EC;
0051     return Error::success();
0052   }
0053 
0054   template <typename T>
0055   static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
0056     const RecordPrefix *Prefix =
0057         reinterpret_cast<const RecordPrefix *>(Data.data());
0058     TypeRecordKind K =
0059         static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
0060     T Record(K);
0061     CVType CVT(Data);
0062     if (auto EC = deserializeAs<T>(CVT, Record))
0063       return std::move(EC);
0064     return Record;
0065   }
0066 
0067   Error visitTypeBegin(CVType &Record) override {
0068     assert(!Mapping && "Already in a type mapping!");
0069     Mapping = std::make_unique<MappingInfo>(Record.content());
0070     return Mapping->Mapping.visitTypeBegin(Record);
0071   }
0072 
0073   Error visitTypeBegin(CVType &Record, TypeIndex Index) override {
0074     return visitTypeBegin(Record);
0075   }
0076 
0077   Error visitTypeEnd(CVType &Record) override {
0078     assert(Mapping && "Not in a type mapping!");
0079     auto EC = Mapping->Mapping.visitTypeEnd(Record);
0080     Mapping.reset();
0081     return EC;
0082   }
0083 
0084 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
0085   Error visitKnownRecord(CVType &CVR, Name##Record &Record) override {         \
0086     return visitKnownRecordImpl<Name##Record>(CVR, Record);                    \
0087   }
0088 #define MEMBER_RECORD(EnumName, EnumVal, Name)
0089 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0090 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0091 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
0092 
0093 private:
0094   template <typename RecordType>
0095   Error visitKnownRecordImpl(CVType &CVR, RecordType &Record) {
0096     return Mapping->Mapping.visitKnownRecord(CVR, Record);
0097   }
0098 
0099   std::unique_ptr<MappingInfo> Mapping;
0100 };
0101 
0102 class FieldListDeserializer : public TypeVisitorCallbacks {
0103   struct MappingInfo {
0104     explicit MappingInfo(BinaryStreamReader &R)
0105         : Reader(R), Mapping(Reader), StartOffset(0) {}
0106 
0107     BinaryStreamReader &Reader;
0108     TypeRecordMapping Mapping;
0109     uint32_t StartOffset;
0110   };
0111 
0112 public:
0113   explicit FieldListDeserializer(BinaryStreamReader &Reader) : Mapping(Reader) {
0114     RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
0115     CVType FieldList(&Pre, sizeof(Pre));
0116     consumeError(Mapping.Mapping.visitTypeBegin(FieldList));
0117   }
0118 
0119   ~FieldListDeserializer() override {
0120     RecordPrefix Pre(static_cast<uint16_t>(TypeLeafKind::LF_FIELDLIST));
0121     CVType FieldList(&Pre, sizeof(Pre));
0122     consumeError(Mapping.Mapping.visitTypeEnd(FieldList));
0123   }
0124 
0125   Error visitMemberBegin(CVMemberRecord &Record) override {
0126     Mapping.StartOffset = Mapping.Reader.getOffset();
0127     return Mapping.Mapping.visitMemberBegin(Record);
0128   }
0129 
0130   Error visitMemberEnd(CVMemberRecord &Record) override {
0131     if (auto EC = Mapping.Mapping.visitMemberEnd(Record))
0132       return EC;
0133     return Error::success();
0134   }
0135 
0136 #define TYPE_RECORD(EnumName, EnumVal, Name)
0137 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
0138   Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
0139     return visitKnownMemberImpl<Name##Record>(CVR, Record);                    \
0140   }
0141 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0142 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
0143 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
0144 
0145 private:
0146   template <typename RecordType>
0147   Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
0148     if (auto EC = Mapping.Mapping.visitKnownMember(CVR, Record))
0149       return EC;
0150 
0151     uint32_t EndOffset = Mapping.Reader.getOffset();
0152     uint32_t RecordLength = EndOffset - Mapping.StartOffset;
0153     Mapping.Reader.setOffset(Mapping.StartOffset);
0154     if (auto EC = Mapping.Reader.readBytes(CVR.Data, RecordLength))
0155       return EC;
0156     assert(Mapping.Reader.getOffset() == EndOffset);
0157     return Error::success();
0158   }
0159   MappingInfo Mapping;
0160 };
0161 
0162 } // end namespace codeview
0163 } // end namespace llvm
0164 
0165 #endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H