Previously we were assuming that any visitation of types would necessarily be against a type we had binary data for. Reasonable assumption when were just reading PDBs and dumping them, but once we start writing PDBs from Yaml this breaks down, because we have no binary data yet, only Yaml, and from that we need to read the record kind and perform the switch based on that. So this patch does that. Instead of having the visitor switch on the kind that is already in the CVType record, we change the visitTypeBegin() method to return the Kind, and switch on the returned value. This way, the default implementation can still return the value from the CVType, but the implementation which visits Yaml records and serializes binary PDB type records can use the field in the Yaml as the source of the switch. llvm-svn: 280307
521 lines
20 KiB
C++
521 lines
20 KiB
C++
//===- PdbYAML.cpp -------------------------------------------- *- C++ --*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CodeViewYaml.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
|
|
#include "llvm/DebugInfo/CodeView/EnumTables.h"
|
|
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
|
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
|
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::codeview;
|
|
using namespace llvm::codeview::yaml;
|
|
|
|
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
|
|
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint64_t)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
|
|
LLVM_YAML_IS_SEQUENCE_VECTOR(CVType)
|
|
|
|
namespace llvm {
|
|
namespace yaml {
|
|
template <> struct ScalarEnumerationTraits<PointerToMemberRepresentation> {
|
|
static void enumeration(IO &IO, PointerToMemberRepresentation &Value) {
|
|
IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown);
|
|
IO.enumCase(Value, "SingleInheritanceData",
|
|
PointerToMemberRepresentation::SingleInheritanceData);
|
|
IO.enumCase(Value, "MultipleInheritanceData",
|
|
PointerToMemberRepresentation::MultipleInheritanceData);
|
|
IO.enumCase(Value, "VirtualInheritanceData",
|
|
PointerToMemberRepresentation::VirtualInheritanceData);
|
|
IO.enumCase(Value, "GeneralData",
|
|
PointerToMemberRepresentation::GeneralData);
|
|
IO.enumCase(Value, "SingleInheritanceFunction",
|
|
PointerToMemberRepresentation::SingleInheritanceFunction);
|
|
IO.enumCase(Value, "MultipleInheritanceFunction",
|
|
PointerToMemberRepresentation::MultipleInheritanceFunction);
|
|
IO.enumCase(Value, "VirtualInheritanceFunction",
|
|
PointerToMemberRepresentation::VirtualInheritanceFunction);
|
|
IO.enumCase(Value, "GeneralFunction",
|
|
PointerToMemberRepresentation::GeneralFunction);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<VFTableSlotKind> {
|
|
static void enumeration(IO &IO, VFTableSlotKind &Kind) {
|
|
IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16);
|
|
IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16);
|
|
IO.enumCase(Kind, "This", VFTableSlotKind::This);
|
|
IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer);
|
|
IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta);
|
|
IO.enumCase(Kind, "Near", VFTableSlotKind::Near);
|
|
IO.enumCase(Kind, "Far", VFTableSlotKind::Far);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<CallingConvention> {
|
|
static void enumeration(IO &IO, CallingConvention &Value) {
|
|
IO.enumCase(Value, "NearC", CallingConvention::NearC);
|
|
IO.enumCase(Value, "FarC", CallingConvention::FarC);
|
|
IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal);
|
|
IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal);
|
|
IO.enumCase(Value, "NearFast", CallingConvention::NearFast);
|
|
IO.enumCase(Value, "FarFast", CallingConvention::FarFast);
|
|
IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall);
|
|
IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall);
|
|
IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall);
|
|
IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall);
|
|
IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall);
|
|
IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall);
|
|
IO.enumCase(Value, "Generic", CallingConvention::Generic);
|
|
IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall);
|
|
IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall);
|
|
IO.enumCase(Value, "SHCall", CallingConvention::SHCall);
|
|
IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall);
|
|
IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call);
|
|
IO.enumCase(Value, "TriCall", CallingConvention::TriCall);
|
|
IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call);
|
|
IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall);
|
|
IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall);
|
|
IO.enumCase(Value, "Inline", CallingConvention::Inline);
|
|
IO.enumCase(Value, "NearVector", CallingConvention::NearVector);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<PointerKind> {
|
|
static void enumeration(IO &IO, PointerKind &Kind) {
|
|
IO.enumCase(Kind, "Near16", PointerKind::Near16);
|
|
IO.enumCase(Kind, "Far16", PointerKind::Far16);
|
|
IO.enumCase(Kind, "Huge16", PointerKind::Huge16);
|
|
IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment);
|
|
IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue);
|
|
IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue);
|
|
IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress);
|
|
IO.enumCase(Kind, "BasedOnSegmentAddress",
|
|
PointerKind::BasedOnSegmentAddress);
|
|
IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType);
|
|
IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf);
|
|
IO.enumCase(Kind, "Near32", PointerKind::Near32);
|
|
IO.enumCase(Kind, "Far32", PointerKind::Far32);
|
|
IO.enumCase(Kind, "Near64", PointerKind::Near64);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<PointerMode> {
|
|
static void enumeration(IO &IO, PointerMode &Mode) {
|
|
IO.enumCase(Mode, "Pointer", PointerMode::Pointer);
|
|
IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference);
|
|
IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember);
|
|
IO.enumCase(Mode, "PointerToMemberFunction",
|
|
PointerMode::PointerToMemberFunction);
|
|
IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<HfaKind> {
|
|
static void enumeration(IO &IO, HfaKind &Value) {
|
|
IO.enumCase(Value, "None", HfaKind::None);
|
|
IO.enumCase(Value, "Float", HfaKind::Float);
|
|
IO.enumCase(Value, "Double", HfaKind::Double);
|
|
IO.enumCase(Value, "Other", HfaKind::Other);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<MemberAccess> {
|
|
static void enumeration(IO &IO, MemberAccess &Access) {
|
|
IO.enumCase(Access, "None", MemberAccess::None);
|
|
IO.enumCase(Access, "Private", MemberAccess::Private);
|
|
IO.enumCase(Access, "Protected", MemberAccess::Protected);
|
|
IO.enumCase(Access, "Public", MemberAccess::Public);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<MethodKind> {
|
|
static void enumeration(IO &IO, MethodKind &Kind) {
|
|
IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla);
|
|
IO.enumCase(Kind, "Virtual", MethodKind::Virtual);
|
|
IO.enumCase(Kind, "Static", MethodKind::Static);
|
|
IO.enumCase(Kind, "Friend", MethodKind::Friend);
|
|
IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual);
|
|
IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual);
|
|
IO.enumCase(Kind, "PureIntroducingVirtual",
|
|
MethodKind::PureIntroducingVirtual);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarEnumerationTraits<WindowsRTClassKind> {
|
|
static void enumeration(IO &IO, WindowsRTClassKind &Value) {
|
|
IO.enumCase(Value, "None", WindowsRTClassKind::None);
|
|
IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass);
|
|
IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass);
|
|
IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<PointerOptions> {
|
|
static void bitset(IO &IO, PointerOptions &Options) {
|
|
IO.bitSetCase(Options, "None", PointerOptions::None);
|
|
IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32);
|
|
IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile);
|
|
IO.bitSetCase(Options, "Const", PointerOptions::Const);
|
|
IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned);
|
|
IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict);
|
|
IO.bitSetCase(Options, "WinRTSmartPointer",
|
|
PointerOptions::WinRTSmartPointer);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<ModifierOptions> {
|
|
static void bitset(IO &IO, ModifierOptions &Options) {
|
|
IO.bitSetCase(Options, "None", ModifierOptions::None);
|
|
IO.bitSetCase(Options, "Const", ModifierOptions::Const);
|
|
IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile);
|
|
IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<FunctionOptions> {
|
|
static void bitset(IO &IO, FunctionOptions &Options) {
|
|
IO.bitSetCase(Options, "None", FunctionOptions::None);
|
|
IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt);
|
|
IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor);
|
|
IO.bitSetCase(Options, "ConstructorWithVirtualBases",
|
|
FunctionOptions::ConstructorWithVirtualBases);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<ClassOptions> {
|
|
static void bitset(IO &IO, ClassOptions &Options) {
|
|
IO.bitSetCase(Options, "None", ClassOptions::None);
|
|
IO.bitSetCase(Options, "HasConstructorOrDestructor",
|
|
ClassOptions::HasConstructorOrDestructor);
|
|
IO.bitSetCase(Options, "HasOverloadedOperator",
|
|
ClassOptions::HasOverloadedOperator);
|
|
IO.bitSetCase(Options, "Nested", ClassOptions::Nested);
|
|
IO.bitSetCase(Options, "ContainsNestedClass",
|
|
ClassOptions::ContainsNestedClass);
|
|
IO.bitSetCase(Options, "HasOverloadedAssignmentOperator",
|
|
ClassOptions::HasOverloadedAssignmentOperator);
|
|
IO.bitSetCase(Options, "HasConversionOperator",
|
|
ClassOptions::HasConversionOperator);
|
|
IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference);
|
|
IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped);
|
|
IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName);
|
|
IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed);
|
|
IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarBitSetTraits<MethodOptions> {
|
|
static void bitset(IO &IO, MethodOptions &Options) {
|
|
IO.bitSetCase(Options, "None", MethodOptions::None);
|
|
IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo);
|
|
IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit);
|
|
IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct);
|
|
IO.bitSetCase(Options, "CompilerGenerated",
|
|
MethodOptions::CompilerGenerated);
|
|
IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed);
|
|
}
|
|
};
|
|
|
|
template <> struct ScalarTraits<APSInt> {
|
|
static void output(const APSInt &S, void *, llvm::raw_ostream &OS) {
|
|
S.print(OS, true);
|
|
}
|
|
static StringRef input(StringRef Scalar, void *Ctx, APSInt &S) {
|
|
S = APSInt(Scalar);
|
|
return "";
|
|
}
|
|
|
|
static bool mustQuote(StringRef Scalar) { return false; }
|
|
};
|
|
|
|
void MappingTraits<CVType>::mapping(IO &IO, CVType &Record) {
|
|
if (IO.outputting()) {
|
|
codeview::TypeDeserializer Deserializer;
|
|
codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
|
|
|
|
codeview::TypeVisitorCallbackPipeline Pipeline;
|
|
Pipeline.addCallbackToPipeline(Deserializer);
|
|
Pipeline.addCallbackToPipeline(Callbacks);
|
|
|
|
codeview::CVTypeVisitor Visitor(Pipeline);
|
|
consumeError(Visitor.visitTypeRecord(Record));
|
|
}
|
|
}
|
|
|
|
void MappingTraits<FieldListRecord>::mapping(IO &IO,
|
|
FieldListRecord &FieldList) {
|
|
if (IO.outputting()) {
|
|
codeview::yaml::YamlTypeDumperCallbacks Callbacks(IO);
|
|
codeview::TypeDeserializer Deserializer;
|
|
|
|
codeview::TypeVisitorCallbackPipeline Pipeline;
|
|
Pipeline.addCallbackToPipeline(Deserializer);
|
|
Pipeline.addCallbackToPipeline(Callbacks);
|
|
|
|
codeview::CVTypeVisitor Visitor(Pipeline);
|
|
consumeError(Visitor.visitFieldListMemberStream(FieldList.Data));
|
|
}
|
|
}
|
|
|
|
void MappingTraits<StringIdRecord>::mapping(IO &IO, StringIdRecord &String) {
|
|
IO.mapRequired("Id", String.Id);
|
|
IO.mapRequired("String", String.String);
|
|
}
|
|
|
|
void MappingTraits<ArgListRecord>::mapping(IO &IO, ArgListRecord &Args) {
|
|
IO.mapRequired("ArgIndices", Args.StringIndices);
|
|
}
|
|
|
|
void MappingTraits<ClassRecord>::mapping(IO &IO, ClassRecord &Class) {
|
|
IO.mapRequired("MemberCount", Class.MemberCount);
|
|
IO.mapRequired("Options", Class.Options);
|
|
IO.mapRequired("FieldList", Class.FieldList);
|
|
IO.mapRequired("Name", Class.Name);
|
|
IO.mapRequired("UniqueName", Class.UniqueName);
|
|
IO.mapRequired("Hfa", Class.Hfa);
|
|
IO.mapRequired("WinRTKind", Class.WinRTKind);
|
|
IO.mapRequired("DerivationList", Class.DerivationList);
|
|
IO.mapRequired("VTableShape", Class.VTableShape);
|
|
IO.mapRequired("Size", Class.Size);
|
|
}
|
|
|
|
void MappingTraits<UnionRecord>::mapping(IO &IO, UnionRecord &Union) {
|
|
IO.mapRequired("MemberCount", Union.MemberCount);
|
|
IO.mapRequired("Options", Union.Options);
|
|
IO.mapRequired("FieldList", Union.FieldList);
|
|
IO.mapRequired("Name", Union.Name);
|
|
IO.mapRequired("UniqueName", Union.UniqueName);
|
|
IO.mapRequired("Hfa", Union.Hfa);
|
|
IO.mapRequired("Size", Union.Size);
|
|
}
|
|
|
|
void MappingTraits<EnumRecord>::mapping(IO &IO, EnumRecord &Enum) {
|
|
IO.mapRequired("NumEnumerators", Enum.MemberCount);
|
|
IO.mapRequired("Options", Enum.Options);
|
|
IO.mapRequired("FieldList", Enum.FieldList);
|
|
IO.mapRequired("Name", Enum.Name);
|
|
IO.mapRequired("UniqueName", Enum.UniqueName);
|
|
IO.mapRequired("UnderlyingType", Enum.UnderlyingType);
|
|
}
|
|
|
|
void MappingTraits<ArrayRecord>::mapping(IO &IO, ArrayRecord &AT) {
|
|
IO.mapRequired("ElementType", AT.ElementType);
|
|
IO.mapRequired("IndexType", AT.IndexType);
|
|
IO.mapRequired("Size", AT.Size);
|
|
IO.mapRequired("Name", AT.Name);
|
|
}
|
|
|
|
void MappingTraits<VFTableRecord>::mapping(IO &IO, VFTableRecord &VFT) {
|
|
IO.mapRequired("CompleteClass", VFT.CompleteClass);
|
|
IO.mapRequired("OverriddenVFTable", VFT.OverriddenVFTable);
|
|
IO.mapRequired("VFPtrOffset", VFT.VFPtrOffset);
|
|
IO.mapRequired("Name", VFT.Name);
|
|
IO.mapRequired("MethodNames", VFT.MethodNames);
|
|
}
|
|
|
|
void MappingTraits<MemberFuncIdRecord>::mapping(IO &IO,
|
|
MemberFuncIdRecord &Id) {
|
|
IO.mapRequired("ClassType", Id.ClassType);
|
|
IO.mapRequired("FunctionType", Id.FunctionType);
|
|
IO.mapRequired("Name", Id.Name);
|
|
}
|
|
|
|
void MappingTraits<ProcedureRecord>::mapping(IO &IO, ProcedureRecord &Proc) {
|
|
IO.mapRequired("ReturnType", Proc.ReturnType);
|
|
IO.mapRequired("CallConv", Proc.CallConv);
|
|
IO.mapRequired("Options", Proc.Options);
|
|
IO.mapRequired("ParameterCount", Proc.ParameterCount);
|
|
IO.mapRequired("ArgumentList", Proc.ArgumentList);
|
|
}
|
|
|
|
void MappingTraits<MemberFunctionRecord>::mapping(IO &IO,
|
|
MemberFunctionRecord &MF) {
|
|
IO.mapRequired("ReturnType", MF.ReturnType);
|
|
IO.mapRequired("ClassType", MF.ClassType);
|
|
IO.mapRequired("ThisType", MF.ThisType);
|
|
IO.mapRequired("CallConv", MF.CallConv);
|
|
IO.mapRequired("Options", MF.Options);
|
|
IO.mapRequired("ParameterCount", MF.ParameterCount);
|
|
IO.mapRequired("ArgumentList", MF.ArgumentList);
|
|
IO.mapRequired("ThisPointerAdjustment", MF.ThisPointerAdjustment);
|
|
}
|
|
|
|
void MappingTraits<MethodOverloadListRecord>::mapping(
|
|
IO &IO, MethodOverloadListRecord &MethodList) {
|
|
IO.mapRequired("Methods", MethodList.Methods);
|
|
}
|
|
|
|
void MappingTraits<FuncIdRecord>::mapping(IO &IO, FuncIdRecord &Func) {
|
|
IO.mapRequired("ParentScope", Func.ParentScope);
|
|
IO.mapRequired("FunctionType", Func.FunctionType);
|
|
IO.mapRequired("Name", Func.Name);
|
|
}
|
|
|
|
void MappingTraits<TypeServer2Record>::mapping(IO &IO, TypeServer2Record &TS) {
|
|
IO.mapRequired("Guid", TS.Guid);
|
|
IO.mapRequired("Age", TS.Age);
|
|
IO.mapRequired("Name", TS.Name);
|
|
}
|
|
|
|
void MappingTraits<PointerRecord>::mapping(IO &IO, PointerRecord &Ptr) {
|
|
IO.mapRequired("ReferentType", Ptr.ReferentType);
|
|
IO.mapRequired("PtrKind", Ptr.PtrKind);
|
|
IO.mapRequired("Mode", Ptr.Mode);
|
|
IO.mapRequired("Options", Ptr.Options);
|
|
IO.mapRequired("Size", Ptr.Size);
|
|
IO.mapOptional("MemberInfo", Ptr.MemberInfo);
|
|
}
|
|
|
|
void MappingTraits<MemberPointerInfo>::mapping(IO &IO, MemberPointerInfo &MPI) {
|
|
IO.mapRequired("ContainingType", MPI.ContainingType);
|
|
IO.mapRequired("Representation", MPI.Representation);
|
|
}
|
|
|
|
void MappingTraits<ModifierRecord>::mapping(IO &IO, ModifierRecord &Mod) {
|
|
IO.mapRequired("ModifiedType", Mod.ModifiedType);
|
|
IO.mapRequired("Modifiers", Mod.Modifiers);
|
|
}
|
|
|
|
void MappingTraits<BitFieldRecord>::mapping(IO &IO, BitFieldRecord &BitField) {
|
|
IO.mapRequired("Type", BitField.Type);
|
|
IO.mapRequired("BitSize", BitField.BitSize);
|
|
IO.mapRequired("BitOffset", BitField.BitOffset);
|
|
}
|
|
|
|
void MappingTraits<VFTableShapeRecord>::mapping(IO &IO,
|
|
VFTableShapeRecord &Shape) {
|
|
IO.mapRequired("Slots", Shape.Slots);
|
|
}
|
|
|
|
void MappingTraits<UdtSourceLineRecord>::mapping(IO &IO,
|
|
UdtSourceLineRecord &Line) {
|
|
IO.mapRequired("UDT", Line.UDT);
|
|
IO.mapRequired("SourceFile", Line.SourceFile);
|
|
IO.mapRequired("LineNumber", Line.LineNumber);
|
|
}
|
|
|
|
void MappingTraits<UdtModSourceLineRecord>::mapping(
|
|
IO &IO, UdtModSourceLineRecord &Line) {
|
|
IO.mapRequired("UDT", Line.UDT);
|
|
IO.mapRequired("SourceFile", Line.SourceFile);
|
|
IO.mapRequired("LineNumber", Line.LineNumber);
|
|
IO.mapRequired("Module", Line.Module);
|
|
}
|
|
|
|
void MappingTraits<BuildInfoRecord>::mapping(IO &IO, BuildInfoRecord &Args) {
|
|
IO.mapRequired("ArgIndices", Args.ArgIndices);
|
|
}
|
|
|
|
void MappingTraits<NestedTypeRecord>::mapping(IO &IO,
|
|
NestedTypeRecord &Nested) {
|
|
IO.mapRequired("Type", Nested.Type);
|
|
IO.mapRequired("Name", Nested.Name);
|
|
}
|
|
|
|
void MappingTraits<OneMethodRecord>::mapping(IO &IO, OneMethodRecord &Method) {
|
|
IO.mapRequired("Type", Method.Type);
|
|
IO.mapRequired("Kind", Method.Kind);
|
|
IO.mapRequired("Options", Method.Options);
|
|
IO.mapRequired("Access", Method.Access);
|
|
IO.mapRequired("VFTableOffset", Method.VFTableOffset);
|
|
IO.mapRequired("Name", Method.Name);
|
|
}
|
|
|
|
void MappingTraits<OverloadedMethodRecord>::mapping(
|
|
IO &IO, OverloadedMethodRecord &Method) {
|
|
IO.mapRequired("NumOverloads", Method.NumOverloads);
|
|
IO.mapRequired("MethodList", Method.MethodList);
|
|
IO.mapRequired("Name", Method.Name);
|
|
}
|
|
|
|
void MappingTraits<DataMemberRecord>::mapping(IO &IO, DataMemberRecord &Field) {
|
|
IO.mapRequired("Access", Field.Access);
|
|
IO.mapRequired("Type", Field.Type);
|
|
IO.mapRequired("FieldOffset", Field.FieldOffset);
|
|
IO.mapRequired("Name", Field.Name);
|
|
}
|
|
|
|
void MappingTraits<StaticDataMemberRecord>::mapping(
|
|
IO &IO, StaticDataMemberRecord &Field) {
|
|
IO.mapRequired("Access", Field.Access);
|
|
IO.mapRequired("Type", Field.Type);
|
|
IO.mapRequired("Name", Field.Name);
|
|
}
|
|
|
|
void MappingTraits<VFPtrRecord>::mapping(IO &IO, VFPtrRecord &VFTable) {
|
|
IO.mapRequired("Type", VFTable.Type);
|
|
}
|
|
|
|
void MappingTraits<EnumeratorRecord>::mapping(IO &IO, EnumeratorRecord &Enum) {
|
|
IO.mapRequired("Access", Enum.Access);
|
|
IO.mapRequired("Value", Enum.Value);
|
|
IO.mapRequired("Name", Enum.Name);
|
|
}
|
|
|
|
void MappingTraits<BaseClassRecord>::mapping(IO &IO, BaseClassRecord &Base) {
|
|
IO.mapRequired("Access", Base.Access);
|
|
IO.mapRequired("Type", Base.Type);
|
|
IO.mapRequired("Offset", Base.Offset);
|
|
}
|
|
|
|
void MappingTraits<VirtualBaseClassRecord>::mapping(
|
|
IO &IO, VirtualBaseClassRecord &Base) {
|
|
IO.mapRequired("Access", Base.Access);
|
|
IO.mapRequired("BaseType", Base.BaseType);
|
|
IO.mapRequired("VBPtrType", Base.VBPtrType);
|
|
IO.mapRequired("VBPtrOffset", Base.VBPtrOffset);
|
|
IO.mapRequired("VTableIndex", Base.VTableIndex);
|
|
}
|
|
|
|
void MappingTraits<ListContinuationRecord>::mapping(
|
|
IO &IO, ListContinuationRecord &Cont) {
|
|
IO.mapRequired("ContinuationIndex", Cont.ContinuationIndex);
|
|
}
|
|
|
|
template <> struct ScalarTraits<codeview::TypeIndex> {
|
|
static void output(const codeview::TypeIndex &S, void *,
|
|
llvm::raw_ostream &OS) {
|
|
OS << S.getIndex();
|
|
}
|
|
static StringRef input(StringRef Scalar, void *Ctx, codeview::TypeIndex &S) {
|
|
uint32_t I;
|
|
StringRef Result = ScalarTraits<uint32_t>::input(Scalar, Ctx, I);
|
|
if (!Result.empty())
|
|
return Result;
|
|
S = TypeIndex(I);
|
|
return "";
|
|
}
|
|
static bool mustQuote(StringRef Scalar) { return false; }
|
|
};
|
|
|
|
void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
|
|
TypeLeafKind &Value) {
|
|
auto TypeLeafNames = getTypeLeafNames();
|
|
for (const auto &E : TypeLeafNames)
|
|
io.enumCase(Value, E.Name.str().c_str(), E.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
Expected<TypeLeafKind>
|
|
llvm::codeview::yaml::YamlTypeDumperCallbacks::visitTypeBegin(
|
|
const CVRecord<TypeLeafKind> &CVR) {
|
|
// When we're outputting, `CVR.Type` already has the right value in it. But
|
|
// when we're inputting, we need to read the value. Since `CVR.Type` is const
|
|
// we do it into a temp variable.
|
|
TypeLeafKind K = CVR.Type;
|
|
YamlIO.mapRequired("Kind", K);
|
|
return K;
|
|
}
|