|  | //===- SymbolRecordMapping.cpp -----------------------------------*- C++-*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::codeview; | 
|  |  | 
|  | #define error(X)                                                               \ | 
|  | if (auto EC = X)                                                             \ | 
|  | return EC; | 
|  |  | 
|  | namespace { | 
|  | struct MapGap { | 
|  | Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const { | 
|  | error(IO.mapInteger(Gap.GapStartOffset)); | 
|  | error(IO.mapInteger(Gap.Range)); | 
|  | return Error::success(); | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO, | 
|  | LocalVariableAddrRange &Range) { | 
|  | error(IO.mapInteger(Range.OffsetStart)); | 
|  | error(IO.mapInteger(Range.ISectStart)); | 
|  | error(IO.mapInteger(Range.Range)); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) { | 
|  | error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix))); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) { | 
|  | error(IO.padToAlignment(alignOf(Container))); | 
|  | error(IO.endRecord()); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) { | 
|  |  | 
|  | error(IO.mapInteger(Block.Parent)); | 
|  | error(IO.mapInteger(Block.End)); | 
|  | error(IO.mapInteger(Block.CodeSize)); | 
|  | error(IO.mapInteger(Block.CodeOffset)); | 
|  | error(IO.mapInteger(Block.Segment)); | 
|  | error(IO.mapStringZ(Block.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) { | 
|  |  | 
|  | error(IO.mapInteger(Thunk.Parent)); | 
|  | error(IO.mapInteger(Thunk.End)); | 
|  | error(IO.mapInteger(Thunk.Next)); | 
|  | error(IO.mapInteger(Thunk.Offset)); | 
|  | error(IO.mapInteger(Thunk.Segment)); | 
|  | error(IO.mapInteger(Thunk.Length)); | 
|  | error(IO.mapEnum(Thunk.Thunk)); | 
|  | error(IO.mapStringZ(Thunk.Name)); | 
|  | error(IO.mapByteVectorTail(Thunk.VariantData)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | TrampolineSym &Tramp) { | 
|  |  | 
|  | error(IO.mapEnum(Tramp.Type)); | 
|  | error(IO.mapInteger(Tramp.Size)); | 
|  | error(IO.mapInteger(Tramp.ThunkOffset)); | 
|  | error(IO.mapInteger(Tramp.TargetOffset)); | 
|  | error(IO.mapInteger(Tramp.ThunkSection)); | 
|  | error(IO.mapInteger(Tramp.TargetSection)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | SectionSym &Section) { | 
|  | uint8_t Padding = 0; | 
|  |  | 
|  | error(IO.mapInteger(Section.SectionNumber)); | 
|  | error(IO.mapInteger(Section.Alignment)); | 
|  | error(IO.mapInteger(Padding)); | 
|  | error(IO.mapInteger(Section.Rva)); | 
|  | error(IO.mapInteger(Section.Length)); | 
|  | error(IO.mapInteger(Section.Characteristics)); | 
|  | error(IO.mapStringZ(Section.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | CoffGroupSym &CoffGroup) { | 
|  |  | 
|  | error(IO.mapInteger(CoffGroup.Size)); | 
|  | error(IO.mapInteger(CoffGroup.Characteristics)); | 
|  | error(IO.mapInteger(CoffGroup.Offset)); | 
|  | error(IO.mapInteger(CoffGroup.Segment)); | 
|  | error(IO.mapStringZ(CoffGroup.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | BPRelativeSym &BPRel) { | 
|  |  | 
|  | error(IO.mapInteger(BPRel.Offset)); | 
|  | error(IO.mapInteger(BPRel.Type)); | 
|  | error(IO.mapStringZ(BPRel.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | BuildInfoSym &BuildInfo) { | 
|  |  | 
|  | error(IO.mapInteger(BuildInfo.BuildId)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | CallSiteInfoSym &CallSiteInfo) { | 
|  | uint16_t Padding = 0; | 
|  |  | 
|  | error(IO.mapInteger(CallSiteInfo.CodeOffset)); | 
|  | error(IO.mapInteger(CallSiteInfo.Segment)); | 
|  | error(IO.mapInteger(Padding)); | 
|  | error(IO.mapInteger(CallSiteInfo.Type)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | EnvBlockSym &EnvBlock) { | 
|  |  | 
|  | uint8_t Reserved = 0; | 
|  | error(IO.mapInteger(Reserved)); | 
|  | error(IO.mapStringZVectorZ(EnvBlock.Fields)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | FileStaticSym &FileStatic) { | 
|  |  | 
|  | error(IO.mapInteger(FileStatic.Index)); | 
|  | error(IO.mapInteger(FileStatic.ModFilenameOffset)); | 
|  | error(IO.mapEnum(FileStatic.Flags)); | 
|  | error(IO.mapStringZ(FileStatic.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) { | 
|  |  | 
|  | error(IO.mapInteger(Export.Ordinal)); | 
|  | error(IO.mapEnum(Export.Flags)); | 
|  | error(IO.mapStringZ(Export.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | Compile2Sym &Compile2) { | 
|  |  | 
|  | error(IO.mapEnum(Compile2.Flags)); | 
|  | error(IO.mapEnum(Compile2.Machine)); | 
|  | error(IO.mapInteger(Compile2.VersionFrontendMajor)); | 
|  | error(IO.mapInteger(Compile2.VersionFrontendMinor)); | 
|  | error(IO.mapInteger(Compile2.VersionFrontendBuild)); | 
|  | error(IO.mapInteger(Compile2.VersionBackendMajor)); | 
|  | error(IO.mapInteger(Compile2.VersionBackendMinor)); | 
|  | error(IO.mapInteger(Compile2.VersionBackendBuild)); | 
|  | error(IO.mapStringZ(Compile2.Version)); | 
|  | error(IO.mapStringZVectorZ(Compile2.ExtraStrings)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | Compile3Sym &Compile3) { | 
|  |  | 
|  | error(IO.mapEnum(Compile3.Flags)); | 
|  | error(IO.mapEnum(Compile3.Machine)); | 
|  | error(IO.mapInteger(Compile3.VersionFrontendMajor)); | 
|  | error(IO.mapInteger(Compile3.VersionFrontendMinor)); | 
|  | error(IO.mapInteger(Compile3.VersionFrontendBuild)); | 
|  | error(IO.mapInteger(Compile3.VersionFrontendQFE)); | 
|  | error(IO.mapInteger(Compile3.VersionBackendMajor)); | 
|  | error(IO.mapInteger(Compile3.VersionBackendMinor)); | 
|  | error(IO.mapInteger(Compile3.VersionBackendBuild)); | 
|  | error(IO.mapInteger(Compile3.VersionBackendQFE)); | 
|  | error(IO.mapStringZ(Compile3.Version)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | ConstantSym &Constant) { | 
|  |  | 
|  | error(IO.mapInteger(Constant.Type)); | 
|  | error(IO.mapEncodedInteger(Constant.Value)); | 
|  | error(IO.mapStringZ(Constant.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) { | 
|  |  | 
|  | error(IO.mapInteger(Data.Type)); | 
|  | error(IO.mapInteger(Data.DataOffset)); | 
|  | error(IO.mapInteger(Data.Segment)); | 
|  | error(IO.mapStringZ(Data.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) { | 
|  |  | 
|  | error(IO.mapInteger(DefRangeFramePointerRel.Offset)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range)); | 
|  | error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, | 
|  | DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) { | 
|  |  | 
|  | error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) { | 
|  |  | 
|  | error(IO.mapObject(DefRangeRegisterRel.Hdr.Register)); | 
|  | error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags)); | 
|  | error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range)); | 
|  | error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) { | 
|  |  | 
|  | error(IO.mapObject(DefRangeRegister.Hdr.Register)); | 
|  | error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range)); | 
|  | error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) { | 
|  |  | 
|  | error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register)); | 
|  | error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName)); | 
|  | error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range)); | 
|  | error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) { | 
|  |  | 
|  | error(IO.mapInteger(DefRangeSubfield.Program)); | 
|  | error(IO.mapInteger(DefRangeSubfield.OffsetInParent)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range)); | 
|  | error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | DefRangeSym &DefRange) { | 
|  |  | 
|  | error(IO.mapInteger(DefRange.Program)); | 
|  | error(mapLocalVariableAddrRange(IO, DefRange.Range)); | 
|  | error(IO.mapVectorTail(DefRange.Gaps, MapGap())); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | FrameCookieSym &FrameCookie) { | 
|  |  | 
|  | error(IO.mapInteger(FrameCookie.CodeOffset)); | 
|  | error(IO.mapInteger(FrameCookie.Register)); | 
|  | error(IO.mapEnum(FrameCookie.CookieKind)); | 
|  | error(IO.mapInteger(FrameCookie.Flags)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | FrameProcSym &FrameProc) { | 
|  | error(IO.mapInteger(FrameProc.TotalFrameBytes)); | 
|  | error(IO.mapInteger(FrameProc.PaddingFrameBytes)); | 
|  | error(IO.mapInteger(FrameProc.OffsetToPadding)); | 
|  | error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters)); | 
|  | error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler)); | 
|  | error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler)); | 
|  | error(IO.mapEnum(FrameProc.Flags)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord( | 
|  | CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) { | 
|  |  | 
|  | error(IO.mapInteger(HeapAllocSite.CodeOffset)); | 
|  | error(IO.mapInteger(HeapAllocSite.Segment)); | 
|  | error(IO.mapInteger(HeapAllocSite.CallInstructionSize)); | 
|  | error(IO.mapInteger(HeapAllocSite.Type)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | InlineSiteSym &InlineSite) { | 
|  |  | 
|  | error(IO.mapInteger(InlineSite.Parent)); | 
|  | error(IO.mapInteger(InlineSite.End)); | 
|  | error(IO.mapInteger(InlineSite.Inlinee)); | 
|  | error(IO.mapByteVectorTail(InlineSite.AnnotationData)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | RegisterSym &Register) { | 
|  |  | 
|  | error(IO.mapInteger(Register.Index)); | 
|  | error(IO.mapEnum(Register.Register)); | 
|  | error(IO.mapStringZ(Register.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | PublicSym32 &Public) { | 
|  |  | 
|  | error(IO.mapEnum(Public.Flags)); | 
|  | error(IO.mapInteger(Public.Offset)); | 
|  | error(IO.mapInteger(Public.Segment)); | 
|  | error(IO.mapStringZ(Public.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | ProcRefSym &ProcRef) { | 
|  |  | 
|  | error(IO.mapInteger(ProcRef.SumName)); | 
|  | error(IO.mapInteger(ProcRef.SymOffset)); | 
|  | error(IO.mapInteger(ProcRef.Module)); | 
|  | error(IO.mapStringZ(ProcRef.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) { | 
|  |  | 
|  | error(IO.mapInteger(Label.CodeOffset)); | 
|  | error(IO.mapInteger(Label.Segment)); | 
|  | error(IO.mapEnum(Label.Flags)); | 
|  | error(IO.mapStringZ(Label.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) { | 
|  | error(IO.mapInteger(Local.Type)); | 
|  | error(IO.mapEnum(Local.Flags)); | 
|  | error(IO.mapStringZ(Local.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | ObjNameSym &ObjName) { | 
|  |  | 
|  | error(IO.mapInteger(ObjName.Signature)); | 
|  | error(IO.mapStringZ(ObjName.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) { | 
|  | error(IO.mapInteger(Proc.Parent)); | 
|  | error(IO.mapInteger(Proc.End)); | 
|  | error(IO.mapInteger(Proc.Next)); | 
|  | error(IO.mapInteger(Proc.CodeSize)); | 
|  | error(IO.mapInteger(Proc.DbgStart)); | 
|  | error(IO.mapInteger(Proc.DbgEnd)); | 
|  | error(IO.mapInteger(Proc.FunctionType)); | 
|  | error(IO.mapInteger(Proc.CodeOffset)); | 
|  | error(IO.mapInteger(Proc.Segment)); | 
|  | error(IO.mapEnum(Proc.Flags)); | 
|  | error(IO.mapStringZ(Proc.Name)); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | ScopeEndSym &ScopeEnd) { | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) { | 
|  | error(IO.mapVectorN<uint32_t>( | 
|  | Caller.Indices, | 
|  | [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); })); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | RegRelativeSym &RegRel) { | 
|  |  | 
|  | error(IO.mapInteger(RegRel.Offset)); | 
|  | error(IO.mapInteger(RegRel.Type)); | 
|  | error(IO.mapEnum(RegRel.Register)); | 
|  | error(IO.mapStringZ(RegRel.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | ThreadLocalDataSym &Data) { | 
|  |  | 
|  | error(IO.mapInteger(Data.Type)); | 
|  | error(IO.mapInteger(Data.DataOffset)); | 
|  | error(IO.mapInteger(Data.Segment)); | 
|  | error(IO.mapStringZ(Data.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) { | 
|  |  | 
|  | error(IO.mapInteger(UDT.Type)); | 
|  | error(IO.mapStringZ(UDT.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, | 
|  | UsingNamespaceSym &UN) { | 
|  |  | 
|  | error(IO.mapStringZ(UN.Name)); | 
|  |  | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg, | 
|  | CPUType CPU) { | 
|  | assert(unsigned(EncodedReg) < 4); | 
|  | switch (CPU) { | 
|  | // FIXME: Add ARM and AArch64 variants here. | 
|  | default: | 
|  | break; | 
|  | case CPUType::Intel8080: | 
|  | case CPUType::Intel8086: | 
|  | case CPUType::Intel80286: | 
|  | case CPUType::Intel80386: | 
|  | case CPUType::Intel80486: | 
|  | case CPUType::Pentium: | 
|  | case CPUType::PentiumPro: | 
|  | case CPUType::Pentium3: | 
|  | switch (EncodedReg) { | 
|  | case EncodedFramePtrReg::None:     return RegisterId::NONE; | 
|  | case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME; | 
|  | case EncodedFramePtrReg::FramePtr: return RegisterId::EBP; | 
|  | case EncodedFramePtrReg::BasePtr:  return RegisterId::EBX; | 
|  | } | 
|  | llvm_unreachable("bad encoding"); | 
|  | case CPUType::X64: | 
|  | switch (EncodedReg) { | 
|  | case EncodedFramePtrReg::None:     return RegisterId::NONE; | 
|  | case EncodedFramePtrReg::StackPtr: return RegisterId::RSP; | 
|  | case EncodedFramePtrReg::FramePtr: return RegisterId::RBP; | 
|  | case EncodedFramePtrReg::BasePtr:  return RegisterId::R13; | 
|  | } | 
|  | llvm_unreachable("bad encoding"); | 
|  | } | 
|  | return RegisterId::NONE; | 
|  | } | 
|  |  | 
|  | EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) { | 
|  | switch (CPU) { | 
|  | // FIXME: Add ARM and AArch64 variants here. | 
|  | default: | 
|  | break; | 
|  | case CPUType::Intel8080: | 
|  | case CPUType::Intel8086: | 
|  | case CPUType::Intel80286: | 
|  | case CPUType::Intel80386: | 
|  | case CPUType::Intel80486: | 
|  | case CPUType::Pentium: | 
|  | case CPUType::PentiumPro: | 
|  | case CPUType::Pentium3: | 
|  | switch (Reg) { | 
|  | case RegisterId::VFRAME: | 
|  | return EncodedFramePtrReg::StackPtr; | 
|  | case RegisterId::EBP: | 
|  | return EncodedFramePtrReg::FramePtr; | 
|  | case RegisterId::EBX: | 
|  | return EncodedFramePtrReg::BasePtr; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case CPUType::X64: | 
|  | switch (Reg) { | 
|  | case RegisterId::RSP: | 
|  | return EncodedFramePtrReg::StackPtr; | 
|  | case RegisterId::RBP: | 
|  | return EncodedFramePtrReg::FramePtr; | 
|  | case RegisterId::R13: | 
|  | return EncodedFramePtrReg::BasePtr; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | break; | 
|  | } | 
|  | return EncodedFramePtrReg::None; | 
|  | } |