1 //===- SymbolRecordMapping.cpp -----------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
10 
11 using namespace llvm;
12 using namespace llvm::codeview;
13 
14 #define error(X)                                                               \
15   if (auto EC = X)                                                             \
16     return EC;
17 
18 namespace {
19 struct MapGap {
operator ()__anona1e7665e0111::MapGap20   Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const {
21     error(IO.mapInteger(Gap.GapStartOffset));
22     error(IO.mapInteger(Gap.Range));
23     return Error::success();
24   }
25 };
26 }
27 
mapLocalVariableAddrRange(CodeViewRecordIO & IO,LocalVariableAddrRange & Range)28 static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO,
29                                        LocalVariableAddrRange &Range) {
30   error(IO.mapInteger(Range.OffsetStart));
31   error(IO.mapInteger(Range.ISectStart));
32   error(IO.mapInteger(Range.Range));
33   return Error::success();
34 }
35 
visitSymbolBegin(CVSymbol & Record)36 Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) {
37   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix)));
38   return Error::success();
39 }
40 
visitSymbolEnd(CVSymbol & Record)41 Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) {
42   error(IO.padToAlignment(alignOf(Container)));
43   error(IO.endRecord());
44   return Error::success();
45 }
46 
visitKnownRecord(CVSymbol & CVR,BlockSym & Block)47 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
48 
49   error(IO.mapInteger(Block.Parent));
50   error(IO.mapInteger(Block.End));
51   error(IO.mapInteger(Block.CodeSize));
52   error(IO.mapInteger(Block.CodeOffset));
53   error(IO.mapInteger(Block.Segment));
54   error(IO.mapStringZ(Block.Name));
55 
56   return Error::success();
57 }
58 
visitKnownRecord(CVSymbol & CVR,Thunk32Sym & Thunk)59 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
60 
61   error(IO.mapInteger(Thunk.Parent));
62   error(IO.mapInteger(Thunk.End));
63   error(IO.mapInteger(Thunk.Next));
64   error(IO.mapInteger(Thunk.Offset));
65   error(IO.mapInteger(Thunk.Segment));
66   error(IO.mapInteger(Thunk.Length));
67   error(IO.mapEnum(Thunk.Thunk));
68   error(IO.mapStringZ(Thunk.Name));
69   error(IO.mapByteVectorTail(Thunk.VariantData));
70 
71   return Error::success();
72 }
73 
visitKnownRecord(CVSymbol & CVR,TrampolineSym & Tramp)74 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
75                                             TrampolineSym &Tramp) {
76 
77   error(IO.mapEnum(Tramp.Type));
78   error(IO.mapInteger(Tramp.Size));
79   error(IO.mapInteger(Tramp.ThunkOffset));
80   error(IO.mapInteger(Tramp.TargetOffset));
81   error(IO.mapInteger(Tramp.ThunkSection));
82   error(IO.mapInteger(Tramp.TargetSection));
83 
84   return Error::success();
85 }
86 
visitKnownRecord(CVSymbol & CVR,SectionSym & Section)87 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
88                                             SectionSym &Section) {
89   uint8_t Padding = 0;
90 
91   error(IO.mapInteger(Section.SectionNumber));
92   error(IO.mapInteger(Section.Alignment));
93   error(IO.mapInteger(Padding));
94   error(IO.mapInteger(Section.Rva));
95   error(IO.mapInteger(Section.Length));
96   error(IO.mapInteger(Section.Characteristics));
97   error(IO.mapStringZ(Section.Name));
98 
99   return Error::success();
100 }
101 
visitKnownRecord(CVSymbol & CVR,CoffGroupSym & CoffGroup)102 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
103                                             CoffGroupSym &CoffGroup) {
104 
105   error(IO.mapInteger(CoffGroup.Size));
106   error(IO.mapInteger(CoffGroup.Characteristics));
107   error(IO.mapInteger(CoffGroup.Offset));
108   error(IO.mapInteger(CoffGroup.Segment));
109   error(IO.mapStringZ(CoffGroup.Name));
110 
111   return Error::success();
112 }
113 
visitKnownRecord(CVSymbol & CVR,BPRelativeSym & BPRel)114 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
115                                             BPRelativeSym &BPRel) {
116 
117   error(IO.mapInteger(BPRel.Offset));
118   error(IO.mapInteger(BPRel.Type));
119   error(IO.mapStringZ(BPRel.Name));
120 
121   return Error::success();
122 }
123 
visitKnownRecord(CVSymbol & CVR,BuildInfoSym & BuildInfo)124 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
125                                             BuildInfoSym &BuildInfo) {
126 
127   error(IO.mapInteger(BuildInfo.BuildId));
128 
129   return Error::success();
130 }
131 
visitKnownRecord(CVSymbol & CVR,CallSiteInfoSym & CallSiteInfo)132 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
133                                             CallSiteInfoSym &CallSiteInfo) {
134   uint16_t Padding = 0;
135 
136   error(IO.mapInteger(CallSiteInfo.CodeOffset));
137   error(IO.mapInteger(CallSiteInfo.Segment));
138   error(IO.mapInteger(Padding));
139   error(IO.mapInteger(CallSiteInfo.Type));
140 
141   return Error::success();
142 }
143 
visitKnownRecord(CVSymbol & CVR,EnvBlockSym & EnvBlock)144 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
145                                             EnvBlockSym &EnvBlock) {
146 
147   uint8_t Reserved = 0;
148   error(IO.mapInteger(Reserved));
149   error(IO.mapStringZVectorZ(EnvBlock.Fields));
150 
151   return Error::success();
152 }
153 
visitKnownRecord(CVSymbol & CVR,FileStaticSym & FileStatic)154 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
155                                             FileStaticSym &FileStatic) {
156 
157   error(IO.mapInteger(FileStatic.Index));
158   error(IO.mapInteger(FileStatic.ModFilenameOffset));
159   error(IO.mapEnum(FileStatic.Flags));
160   error(IO.mapStringZ(FileStatic.Name));
161 
162   return Error::success();
163 }
164 
visitKnownRecord(CVSymbol & CVR,ExportSym & Export)165 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
166 
167   error(IO.mapInteger(Export.Ordinal));
168   error(IO.mapEnum(Export.Flags));
169   error(IO.mapStringZ(Export.Name));
170 
171   return Error::success();
172 }
173 
visitKnownRecord(CVSymbol & CVR,Compile2Sym & Compile2)174 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
175                                             Compile2Sym &Compile2) {
176 
177   error(IO.mapEnum(Compile2.Flags));
178   error(IO.mapEnum(Compile2.Machine));
179   error(IO.mapInteger(Compile2.VersionFrontendMajor));
180   error(IO.mapInteger(Compile2.VersionFrontendMinor));
181   error(IO.mapInteger(Compile2.VersionFrontendBuild));
182   error(IO.mapInteger(Compile2.VersionBackendMajor));
183   error(IO.mapInteger(Compile2.VersionBackendMinor));
184   error(IO.mapInteger(Compile2.VersionBackendBuild));
185   error(IO.mapStringZ(Compile2.Version));
186   error(IO.mapStringZVectorZ(Compile2.ExtraStrings));
187 
188   return Error::success();
189 }
190 
visitKnownRecord(CVSymbol & CVR,Compile3Sym & Compile3)191 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
192                                             Compile3Sym &Compile3) {
193 
194   error(IO.mapEnum(Compile3.Flags));
195   error(IO.mapEnum(Compile3.Machine));
196   error(IO.mapInteger(Compile3.VersionFrontendMajor));
197   error(IO.mapInteger(Compile3.VersionFrontendMinor));
198   error(IO.mapInteger(Compile3.VersionFrontendBuild));
199   error(IO.mapInteger(Compile3.VersionFrontendQFE));
200   error(IO.mapInteger(Compile3.VersionBackendMajor));
201   error(IO.mapInteger(Compile3.VersionBackendMinor));
202   error(IO.mapInteger(Compile3.VersionBackendBuild));
203   error(IO.mapInteger(Compile3.VersionBackendQFE));
204   error(IO.mapStringZ(Compile3.Version));
205 
206   return Error::success();
207 }
208 
visitKnownRecord(CVSymbol & CVR,ConstantSym & Constant)209 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
210                                             ConstantSym &Constant) {
211 
212   error(IO.mapInteger(Constant.Type));
213   error(IO.mapEncodedInteger(Constant.Value));
214   error(IO.mapStringZ(Constant.Name));
215 
216   return Error::success();
217 }
218 
visitKnownRecord(CVSymbol & CVR,DataSym & Data)219 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
220 
221   error(IO.mapInteger(Data.Type));
222   error(IO.mapInteger(Data.DataOffset));
223   error(IO.mapInteger(Data.Segment));
224   error(IO.mapStringZ(Data.Name));
225 
226   return Error::success();
227 }
228 
visitKnownRecord(CVSymbol & CVR,DefRangeFramePointerRelSym & DefRangeFramePointerRel)229 Error SymbolRecordMapping::visitKnownRecord(
230     CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
231 
232   error(IO.mapObject(DefRangeFramePointerRel.Hdr.Offset));
233   error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range));
234   error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap()));
235 
236   return Error::success();
237 }
238 
visitKnownRecord(CVSymbol & CVR,DefRangeFramePointerRelFullScopeSym & DefRangeFramePointerRelFullScope)239 Error SymbolRecordMapping::visitKnownRecord(
240     CVSymbol &CVR,
241     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
242 
243   error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset));
244 
245   return Error::success();
246 }
247 
visitKnownRecord(CVSymbol & CVR,DefRangeRegisterRelSym & DefRangeRegisterRel)248 Error SymbolRecordMapping::visitKnownRecord(
249     CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
250 
251   error(IO.mapObject(DefRangeRegisterRel.Hdr.Register));
252   error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags));
253   error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset));
254   error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range));
255   error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap()));
256 
257   return Error::success();
258 }
259 
visitKnownRecord(CVSymbol & CVR,DefRangeRegisterSym & DefRangeRegister)260 Error SymbolRecordMapping::visitKnownRecord(
261     CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
262 
263   error(IO.mapObject(DefRangeRegister.Hdr.Register));
264   error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName));
265   error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range));
266   error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap()));
267 
268   return Error::success();
269 }
270 
visitKnownRecord(CVSymbol & CVR,DefRangeSubfieldRegisterSym & DefRangeSubfieldRegister)271 Error SymbolRecordMapping::visitKnownRecord(
272     CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
273 
274   error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register));
275   error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName));
276   error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent));
277   error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range));
278   error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap()));
279 
280   return Error::success();
281 }
282 
visitKnownRecord(CVSymbol & CVR,DefRangeSubfieldSym & DefRangeSubfield)283 Error SymbolRecordMapping::visitKnownRecord(
284     CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
285 
286   error(IO.mapInteger(DefRangeSubfield.Program));
287   error(IO.mapInteger(DefRangeSubfield.OffsetInParent));
288   error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range));
289   error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap()));
290 
291   return Error::success();
292 }
293 
visitKnownRecord(CVSymbol & CVR,DefRangeSym & DefRange)294 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
295                                             DefRangeSym &DefRange) {
296 
297   error(IO.mapInteger(DefRange.Program));
298   error(mapLocalVariableAddrRange(IO, DefRange.Range));
299   error(IO.mapVectorTail(DefRange.Gaps, MapGap()));
300 
301   return Error::success();
302 }
303 
visitKnownRecord(CVSymbol & CVR,FrameCookieSym & FrameCookie)304 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
305                                             FrameCookieSym &FrameCookie) {
306 
307   error(IO.mapInteger(FrameCookie.CodeOffset));
308   error(IO.mapInteger(FrameCookie.Register));
309   error(IO.mapEnum(FrameCookie.CookieKind));
310   error(IO.mapInteger(FrameCookie.Flags));
311 
312   return Error::success();
313 }
314 
visitKnownRecord(CVSymbol & CVR,FrameProcSym & FrameProc)315 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
316                                             FrameProcSym &FrameProc) {
317   error(IO.mapInteger(FrameProc.TotalFrameBytes));
318   error(IO.mapInteger(FrameProc.PaddingFrameBytes));
319   error(IO.mapInteger(FrameProc.OffsetToPadding));
320   error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters));
321   error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler));
322   error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler));
323   error(IO.mapEnum(FrameProc.Flags));
324 
325   return Error::success();
326 }
327 
visitKnownRecord(CVSymbol & CVR,HeapAllocationSiteSym & HeapAllocSite)328 Error SymbolRecordMapping::visitKnownRecord(
329     CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
330 
331   error(IO.mapInteger(HeapAllocSite.CodeOffset));
332   error(IO.mapInteger(HeapAllocSite.Segment));
333   error(IO.mapInteger(HeapAllocSite.CallInstructionSize));
334   error(IO.mapInteger(HeapAllocSite.Type));
335 
336   return Error::success();
337 }
338 
visitKnownRecord(CVSymbol & CVR,InlineSiteSym & InlineSite)339 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
340                                             InlineSiteSym &InlineSite) {
341 
342   error(IO.mapInteger(InlineSite.Parent));
343   error(IO.mapInteger(InlineSite.End));
344   error(IO.mapInteger(InlineSite.Inlinee));
345   error(IO.mapByteVectorTail(InlineSite.AnnotationData));
346 
347   return Error::success();
348 }
349 
visitKnownRecord(CVSymbol & CVR,RegisterSym & Register)350 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
351                                             RegisterSym &Register) {
352 
353   error(IO.mapInteger(Register.Index));
354   error(IO.mapEnum(Register.Register));
355   error(IO.mapStringZ(Register.Name));
356 
357   return Error::success();
358 }
359 
visitKnownRecord(CVSymbol & CVR,PublicSym32 & Public)360 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
361                                             PublicSym32 &Public) {
362 
363   error(IO.mapEnum(Public.Flags));
364   error(IO.mapInteger(Public.Offset));
365   error(IO.mapInteger(Public.Segment));
366   error(IO.mapStringZ(Public.Name));
367 
368   return Error::success();
369 }
370 
visitKnownRecord(CVSymbol & CVR,ProcRefSym & ProcRef)371 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
372                                             ProcRefSym &ProcRef) {
373 
374   error(IO.mapInteger(ProcRef.SumName));
375   error(IO.mapInteger(ProcRef.SymOffset));
376   error(IO.mapInteger(ProcRef.Module));
377   error(IO.mapStringZ(ProcRef.Name));
378 
379   return Error::success();
380 }
381 
visitKnownRecord(CVSymbol & CVR,LabelSym & Label)382 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
383 
384   error(IO.mapInteger(Label.CodeOffset));
385   error(IO.mapInteger(Label.Segment));
386   error(IO.mapEnum(Label.Flags));
387   error(IO.mapStringZ(Label.Name));
388 
389   return Error::success();
390 }
391 
visitKnownRecord(CVSymbol & CVR,LocalSym & Local)392 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
393   error(IO.mapInteger(Local.Type));
394   error(IO.mapEnum(Local.Flags));
395   error(IO.mapStringZ(Local.Name));
396 
397   return Error::success();
398 }
399 
visitKnownRecord(CVSymbol & CVR,ObjNameSym & ObjName)400 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
401                                             ObjNameSym &ObjName) {
402 
403   error(IO.mapInteger(ObjName.Signature));
404   error(IO.mapStringZ(ObjName.Name));
405 
406   return Error::success();
407 }
408 
visitKnownRecord(CVSymbol & CVR,ProcSym & Proc)409 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
410   error(IO.mapInteger(Proc.Parent));
411   error(IO.mapInteger(Proc.End));
412   error(IO.mapInteger(Proc.Next));
413   error(IO.mapInteger(Proc.CodeSize));
414   error(IO.mapInteger(Proc.DbgStart));
415   error(IO.mapInteger(Proc.DbgEnd));
416   error(IO.mapInteger(Proc.FunctionType));
417   error(IO.mapInteger(Proc.CodeOffset));
418   error(IO.mapInteger(Proc.Segment));
419   error(IO.mapEnum(Proc.Flags));
420   error(IO.mapStringZ(Proc.Name));
421   return Error::success();
422 }
423 
visitKnownRecord(CVSymbol & CVR,ScopeEndSym & ScopeEnd)424 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
425                                             ScopeEndSym &ScopeEnd) {
426   return Error::success();
427 }
428 
visitKnownRecord(CVSymbol & CVR,CallerSym & Caller)429 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
430   error(IO.mapVectorN<uint32_t>(
431       Caller.Indices,
432       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
433   return Error::success();
434 }
435 
visitKnownRecord(CVSymbol & CVR,RegRelativeSym & RegRel)436 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
437                                             RegRelativeSym &RegRel) {
438 
439   error(IO.mapInteger(RegRel.Offset));
440   error(IO.mapInteger(RegRel.Type));
441   error(IO.mapEnum(RegRel.Register));
442   error(IO.mapStringZ(RegRel.Name));
443 
444   return Error::success();
445 }
446 
visitKnownRecord(CVSymbol & CVR,ThreadLocalDataSym & Data)447 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
448                                             ThreadLocalDataSym &Data) {
449 
450   error(IO.mapInteger(Data.Type));
451   error(IO.mapInteger(Data.DataOffset));
452   error(IO.mapInteger(Data.Segment));
453   error(IO.mapStringZ(Data.Name));
454 
455   return Error::success();
456 }
457 
visitKnownRecord(CVSymbol & CVR,UDTSym & UDT)458 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
459 
460   error(IO.mapInteger(UDT.Type));
461   error(IO.mapStringZ(UDT.Name));
462 
463   return Error::success();
464 }
465 
visitKnownRecord(CVSymbol & CVR,UsingNamespaceSym & UN)466 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
467                                             UsingNamespaceSym &UN) {
468 
469   error(IO.mapStringZ(UN.Name));
470 
471   return Error::success();
472 }
473 
visitKnownRecord(CVSymbol & CVR,AnnotationSym & Annot)474 Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
475                                             AnnotationSym &Annot) {
476 
477   error(IO.mapInteger(Annot.CodeOffset));
478   error(IO.mapInteger(Annot.Segment));
479   error(IO.mapVectorN<uint16_t>(
480       Annot.Strings,
481       [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
482 
483   return Error::success();
484 }
485 
decodeFramePtrReg(EncodedFramePtrReg EncodedReg,CPUType CPU)486 RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg,
487                                        CPUType CPU) {
488   assert(unsigned(EncodedReg) < 4);
489   switch (CPU) {
490   // FIXME: Add ARM and AArch64 variants here.
491   default:
492     break;
493   case CPUType::Intel8080:
494   case CPUType::Intel8086:
495   case CPUType::Intel80286:
496   case CPUType::Intel80386:
497   case CPUType::Intel80486:
498   case CPUType::Pentium:
499   case CPUType::PentiumPro:
500   case CPUType::Pentium3:
501     switch (EncodedReg) {
502     case EncodedFramePtrReg::None:     return RegisterId::NONE;
503     case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME;
504     case EncodedFramePtrReg::FramePtr: return RegisterId::EBP;
505     case EncodedFramePtrReg::BasePtr:  return RegisterId::EBX;
506     }
507     llvm_unreachable("bad encoding");
508   case CPUType::X64:
509     switch (EncodedReg) {
510     case EncodedFramePtrReg::None:     return RegisterId::NONE;
511     case EncodedFramePtrReg::StackPtr: return RegisterId::RSP;
512     case EncodedFramePtrReg::FramePtr: return RegisterId::RBP;
513     case EncodedFramePtrReg::BasePtr:  return RegisterId::R13;
514     }
515     llvm_unreachable("bad encoding");
516   }
517   return RegisterId::NONE;
518 }
519 
encodeFramePtrReg(RegisterId Reg,CPUType CPU)520 EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) {
521   switch (CPU) {
522   // FIXME: Add ARM and AArch64 variants here.
523   default:
524     break;
525   case CPUType::Intel8080:
526   case CPUType::Intel8086:
527   case CPUType::Intel80286:
528   case CPUType::Intel80386:
529   case CPUType::Intel80486:
530   case CPUType::Pentium:
531   case CPUType::PentiumPro:
532   case CPUType::Pentium3:
533     switch (Reg) {
534     case RegisterId::VFRAME:
535       return EncodedFramePtrReg::StackPtr;
536     case RegisterId::EBP:
537       return EncodedFramePtrReg::FramePtr;
538     case RegisterId::EBX:
539       return EncodedFramePtrReg::BasePtr;
540     default:
541       break;
542     }
543     break;
544   case CPUType::X64:
545     switch (Reg) {
546     case RegisterId::RSP:
547       return EncodedFramePtrReg::StackPtr;
548     case RegisterId::RBP:
549       return EncodedFramePtrReg::FramePtr;
550     case RegisterId::R13:
551       return EncodedFramePtrReg::BasePtr;
552     default:
553       break;
554     }
555     break;
556   }
557   return EncodedFramePtrReg::None;
558 }
559