|
12 | 12 | #include "llvm/ADT/ArrayRef.h" |
13 | 13 | #include "llvm/ADT/SmallString.h" |
14 | 14 | #include "llvm/ADT/iterator.h" |
| 15 | +#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" |
15 | 16 | #include "llvm/DebugInfo/DWARF/DWARFExpression.h" |
16 | 17 | #include "llvm/Support/Error.h" |
17 | 18 | #include "llvm/TargetParser/Triple.h" |
@@ -309,7 +310,6 @@ class UnwindRow { |
309 | 310 |
|
310 | 311 | raw_ostream &operator<<(raw_ostream &OS, const UnwindRow &Row); |
311 | 312 |
|
312 | | -class CFIProgram; |
313 | 313 | class CIE; |
314 | 314 | class FDE; |
315 | 315 |
|
@@ -398,135 +398,6 @@ class UnwindTable { |
398 | 398 |
|
399 | 399 | raw_ostream &operator<<(raw_ostream &OS, const UnwindTable &Rows); |
400 | 400 |
|
401 | | -/// Represent a sequence of Call Frame Information instructions that, when read |
402 | | -/// in order, construct a table mapping PC to frame state. This can also be |
403 | | -/// referred to as "CFI rules" in DWARF literature to avoid confusion with |
404 | | -/// computer programs in the broader sense, and in this context each instruction |
405 | | -/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 |
406 | | -/// manual, "6.4.1 Structure of Call Frame Information". |
407 | | -class CFIProgram { |
408 | | -public: |
409 | | - static constexpr size_t MaxOperands = 3; |
410 | | - typedef SmallVector<uint64_t, MaxOperands> Operands; |
411 | | - |
412 | | - /// An instruction consists of a DWARF CFI opcode and an optional sequence of |
413 | | - /// operands. If it refers to an expression, then this expression has its own |
414 | | - /// sequence of operations and operands handled separately by DWARFExpression. |
415 | | - struct Instruction { |
416 | | - Instruction(uint8_t Opcode) : Opcode(Opcode) {} |
417 | | - |
418 | | - uint8_t Opcode; |
419 | | - Operands Ops; |
420 | | - // Associated DWARF expression in case this instruction refers to one |
421 | | - std::optional<DWARFExpression> Expression; |
422 | | - |
423 | | - Expected<uint64_t> getOperandAsUnsigned(const CFIProgram &CFIP, |
424 | | - uint32_t OperandIdx) const; |
425 | | - |
426 | | - Expected<int64_t> getOperandAsSigned(const CFIProgram &CFIP, |
427 | | - uint32_t OperandIdx) const; |
428 | | - }; |
429 | | - |
430 | | - using InstrList = std::vector<Instruction>; |
431 | | - using iterator = InstrList::iterator; |
432 | | - using const_iterator = InstrList::const_iterator; |
433 | | - |
434 | | - iterator begin() { return Instructions.begin(); } |
435 | | - const_iterator begin() const { return Instructions.begin(); } |
436 | | - iterator end() { return Instructions.end(); } |
437 | | - const_iterator end() const { return Instructions.end(); } |
438 | | - |
439 | | - unsigned size() const { return (unsigned)Instructions.size(); } |
440 | | - bool empty() const { return Instructions.empty(); } |
441 | | - uint64_t codeAlign() const { return CodeAlignmentFactor; } |
442 | | - int64_t dataAlign() const { return DataAlignmentFactor; } |
443 | | - Triple::ArchType triple() const { return Arch; } |
444 | | - |
445 | | - CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor, |
446 | | - Triple::ArchType Arch) |
447 | | - : CodeAlignmentFactor(CodeAlignmentFactor), |
448 | | - DataAlignmentFactor(DataAlignmentFactor), |
449 | | - Arch(Arch) {} |
450 | | - |
451 | | - /// Parse and store a sequence of CFI instructions from Data, |
452 | | - /// starting at *Offset and ending at EndOffset. *Offset is updated |
453 | | - /// to EndOffset upon successful parsing, or indicates the offset |
454 | | - /// where a problem occurred in case an error is returned. |
455 | | - Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset); |
456 | | - |
457 | | - void dump(raw_ostream &OS, DIDumpOptions DumpOpts, unsigned IndentLevel, |
458 | | - std::optional<uint64_t> InitialLocation) const; |
459 | | - |
460 | | - void addInstruction(const Instruction &I) { Instructions.push_back(I); } |
461 | | - |
462 | | - /// Get a DWARF CFI call frame string for the given DW_CFA opcode. |
463 | | - StringRef callFrameString(unsigned Opcode) const; |
464 | | - |
465 | | -private: |
466 | | - std::vector<Instruction> Instructions; |
467 | | - const uint64_t CodeAlignmentFactor; |
468 | | - const int64_t DataAlignmentFactor; |
469 | | - Triple::ArchType Arch; |
470 | | - |
471 | | - /// Convenience method to add a new instruction with the given opcode. |
472 | | - void addInstruction(uint8_t Opcode) { |
473 | | - Instructions.push_back(Instruction(Opcode)); |
474 | | - } |
475 | | - |
476 | | - /// Add a new single-operand instruction. |
477 | | - void addInstruction(uint8_t Opcode, uint64_t Operand1) { |
478 | | - Instructions.push_back(Instruction(Opcode)); |
479 | | - Instructions.back().Ops.push_back(Operand1); |
480 | | - } |
481 | | - |
482 | | - /// Add a new instruction that has two operands. |
483 | | - void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { |
484 | | - Instructions.push_back(Instruction(Opcode)); |
485 | | - Instructions.back().Ops.push_back(Operand1); |
486 | | - Instructions.back().Ops.push_back(Operand2); |
487 | | - } |
488 | | - |
489 | | - /// Add a new instruction that has three operands. |
490 | | - void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2, |
491 | | - uint64_t Operand3) { |
492 | | - Instructions.push_back(Instruction(Opcode)); |
493 | | - Instructions.back().Ops.push_back(Operand1); |
494 | | - Instructions.back().Ops.push_back(Operand2); |
495 | | - Instructions.back().Ops.push_back(Operand3); |
496 | | - } |
497 | | - |
498 | | - /// Types of operands to CFI instructions |
499 | | - /// In DWARF, this type is implicitly tied to a CFI instruction opcode and |
500 | | - /// thus this type doesn't need to be explicitly written to the file (this is |
501 | | - /// not a DWARF encoding). The relationship of instrs to operand types can |
502 | | - /// be obtained from getOperandTypes() and is only used to simplify |
503 | | - /// instruction printing. |
504 | | - enum OperandType { |
505 | | - OT_Unset, |
506 | | - OT_None, |
507 | | - OT_Address, |
508 | | - OT_Offset, |
509 | | - OT_FactoredCodeOffset, |
510 | | - OT_SignedFactDataOffset, |
511 | | - OT_UnsignedFactDataOffset, |
512 | | - OT_Register, |
513 | | - OT_AddressSpace, |
514 | | - OT_Expression |
515 | | - }; |
516 | | - |
517 | | - /// Get the OperandType as a "const char *". |
518 | | - static const char *operandTypeString(OperandType OT); |
519 | | - |
520 | | - /// Retrieve the array describing the types of operands according to the enum |
521 | | - /// above. This is indexed by opcode. |
522 | | - static ArrayRef<OperandType[MaxOperands]> getOperandTypes(); |
523 | | - |
524 | | - /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. |
525 | | - void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts, |
526 | | - const Instruction &Instr, unsigned OperandIdx, |
527 | | - uint64_t Operand, std::optional<uint64_t> &Address) const; |
528 | | -}; |
529 | | - |
530 | 401 | /// An entry in either debug_frame or eh_frame. This entry can be a CIE or an |
531 | 402 | /// FDE. |
532 | 403 | class FrameEntry { |
|
0 commit comments