1 //===- MCDwarf.h - Machine Code Dwarf support -------------------*- 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 // This file contains the declaration of the MCDwarfFile to support the dwarf 10 // .file directive and the .loc directive. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_MC_MCDWARF_H 15 #define LLVM_MC_MCDWARF_H 16 17 #include "llvm/ADT/MapVector.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringMap.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/MC/StringTableBuilder.h" 22 #include "llvm/Support/Error.h" 23 #include "llvm/Support/MD5.h" 24 #include "llvm/Support/SMLoc.h" 25 #include "llvm/Support/StringSaver.h" 26 #include <cassert> 27 #include <cstdint> 28 #include <optional> 29 #include <string> 30 #include <utility> 31 #include <vector> 32 33 namespace llvm { 34 35 template <typename T> class ArrayRef; 36 class MCAsmBackend; 37 class MCContext; 38 class MCObjectStreamer; 39 class MCSection; 40 class MCStreamer; 41 class MCSymbol; 42 class raw_ostream; 43 class SourceMgr; 44 45 namespace mcdwarf { 46 // Emit the common part of the DWARF 5 range/locations list tables header. 47 MCSymbol *emitListsTableHeaderStart(MCStreamer &S); 48 } // namespace mcdwarf 49 50 /// Manage the .debug_line_str section contents, if we use it. 51 class MCDwarfLineStr { 52 BumpPtrAllocator Alloc; 53 StringSaver Saver{Alloc}; 54 MCSymbol *LineStrLabel = nullptr; 55 StringTableBuilder LineStrings{StringTableBuilder::DWARF}; 56 bool UseRelocs = false; 57 58 public: 59 /// Construct an instance that can emit .debug_line_str (for use in a normal 60 /// v5 line table). 61 explicit MCDwarfLineStr(MCContext &Ctx); 62 63 StringSaver &getSaver() { return Saver; } 64 65 /// Emit a reference to the string. 66 void emitRef(MCStreamer *MCOS, StringRef Path); 67 68 /// Emit the .debug_line_str section if appropriate. 69 void emitSection(MCStreamer *MCOS); 70 71 /// Returns finalized section. 72 SmallString<0> getFinalizedData(); 73 74 /// Adds path \p Path to the line string. Returns offset in the 75 /// .debug_line_str section. 76 size_t addString(StringRef Path); 77 }; 78 79 /// Instances of this class represent the name of the dwarf .file directive and 80 /// its associated dwarf file number in the MC file. MCDwarfFile's are created 81 /// and uniqued by the MCContext class. In Dwarf 4 file numbers start from 1; 82 /// i.e. the entry with file number 1 is the first element in the vector of 83 /// DwarfFiles and there is no MCDwarfFile with file number 0. In Dwarf 5 file 84 /// numbers start from 0, with the MCDwarfFile with file number 0 being the 85 /// primary source file, and file numbers correspond to their index in the 86 /// vector. 87 struct MCDwarfFile { 88 // The base name of the file without its directory path. 89 std::string Name; 90 91 // The index into the list of directory names for this file name. 92 unsigned DirIndex = 0; 93 94 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated 95 /// in MCContext. 96 std::optional<MD5::MD5Result> Checksum; 97 98 /// The source code of the file. Non-owning reference to data allocated in 99 /// MCContext. 100 std::optional<StringRef> Source; 101 }; 102 103 /// Instances of this class represent the information from a 104 /// dwarf .loc directive. 105 class MCDwarfLoc { 106 uint32_t FileNum; 107 uint32_t Line; 108 uint16_t Column; 109 // Flags (see #define's below) 110 uint8_t Flags; 111 uint8_t Isa; 112 uint32_t Discriminator; 113 114 // Flag that indicates the initial value of the is_stmt_start flag. 115 #define DWARF2_LINE_DEFAULT_IS_STMT 1 116 117 #define DWARF2_FLAG_IS_STMT (1 << 0) 118 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) 119 #define DWARF2_FLAG_PROLOGUE_END (1 << 2) 120 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) 121 122 private: // MCContext manages these 123 friend class MCContext; 124 friend class MCDwarfLineEntry; 125 126 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, 127 unsigned isa, unsigned discriminator) 128 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), 129 Discriminator(discriminator) {} 130 131 // Allow the default copy constructor and assignment operator to be used 132 // for an MCDwarfLoc object. 133 134 public: 135 /// Get the FileNum of this MCDwarfLoc. 136 unsigned getFileNum() const { return FileNum; } 137 138 /// Get the Line of this MCDwarfLoc. 139 unsigned getLine() const { return Line; } 140 141 /// Get the Column of this MCDwarfLoc. 142 unsigned getColumn() const { return Column; } 143 144 /// Get the Flags of this MCDwarfLoc. 145 unsigned getFlags() const { return Flags; } 146 147 /// Get the Isa of this MCDwarfLoc. 148 unsigned getIsa() const { return Isa; } 149 150 /// Get the Discriminator of this MCDwarfLoc. 151 unsigned getDiscriminator() const { return Discriminator; } 152 153 /// Set the FileNum of this MCDwarfLoc. 154 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 155 156 /// Set the Line of this MCDwarfLoc. 157 void setLine(unsigned line) { Line = line; } 158 159 /// Set the Column of this MCDwarfLoc. 160 void setColumn(unsigned column) { 161 assert(column <= UINT16_MAX); 162 Column = column; 163 } 164 165 /// Set the Flags of this MCDwarfLoc. 166 void setFlags(unsigned flags) { 167 assert(flags <= UINT8_MAX); 168 Flags = flags; 169 } 170 171 /// Set the Isa of this MCDwarfLoc. 172 void setIsa(unsigned isa) { 173 assert(isa <= UINT8_MAX); 174 Isa = isa; 175 } 176 177 /// Set the Discriminator of this MCDwarfLoc. 178 void setDiscriminator(unsigned discriminator) { 179 Discriminator = discriminator; 180 } 181 }; 182 183 /// Instances of this class represent the line information for 184 /// the dwarf line table entries. Which is created after a machine 185 /// instruction is assembled and uses an address from a temporary label 186 /// created at the current address in the current section and the info from 187 /// the last .loc directive seen as stored in the context. 188 class MCDwarfLineEntry : public MCDwarfLoc { 189 MCSymbol *Label; 190 191 private: 192 // Allow the default copy constructor and assignment operator to be used 193 // for an MCDwarfLineEntry object. 194 195 public: 196 // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc. 197 MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc) 198 : MCDwarfLoc(loc), Label(label) {} 199 200 MCSymbol *getLabel() const { return Label; } 201 202 // This indicates the line entry is synthesized for an end entry. 203 bool IsEndEntry = false; 204 205 // Override the label with the given EndLabel. 206 void setEndLabel(MCSymbol *EndLabel) { 207 Label = EndLabel; 208 IsEndEntry = true; 209 } 210 211 // This is called when an instruction is assembled into the specified 212 // section and if there is information from the last .loc directive that 213 // has yet to have a line entry made for it is made. 214 static void make(MCStreamer *MCOS, MCSection *Section); 215 }; 216 217 /// Instances of this class represent the line information for a compile 218 /// unit where machine instructions have been assembled after seeing .loc 219 /// directives. This is the information used to build the dwarf line 220 /// table for a section. 221 class MCLineSection { 222 public: 223 // Add an entry to this MCLineSection's line entries. 224 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) { 225 MCLineDivisions[Sec].push_back(LineEntry); 226 } 227 228 // Add an end entry by cloning the last entry, if exists, for the section 229 // the given EndLabel belongs to. The label is replaced by the given EndLabel. 230 void addEndEntry(MCSymbol *EndLabel); 231 232 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>; 233 using iterator = MCDwarfLineEntryCollection::iterator; 234 using const_iterator = MCDwarfLineEntryCollection::const_iterator; 235 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>; 236 237 private: 238 // A collection of MCDwarfLineEntry for each section. 239 MCLineDivisionMap MCLineDivisions; 240 241 public: 242 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID. 243 const MCLineDivisionMap &getMCLineEntries() const { 244 return MCLineDivisions; 245 } 246 }; 247 248 struct MCDwarfLineTableParams { 249 /// First special line opcode - leave room for the standard opcodes. 250 /// Note: If you want to change this, you'll have to update the 251 /// "StandardOpcodeLengths" table that is emitted in 252 /// \c Emit(). 253 uint8_t DWARF2LineOpcodeBase = 13; 254 /// Minimum line offset in a special line info. opcode. The value 255 /// -5 was chosen to give a reasonable range of values. 256 int8_t DWARF2LineBase = -5; 257 /// Range of line offsets in a special line info. opcode. 258 uint8_t DWARF2LineRange = 14; 259 }; 260 261 struct MCDwarfLineTableHeader { 262 MCSymbol *Label = nullptr; 263 SmallVector<std::string, 3> MCDwarfDirs; 264 SmallVector<MCDwarfFile, 3> MCDwarfFiles; 265 StringMap<unsigned> SourceIdMap; 266 std::string CompilationDir; 267 MCDwarfFile RootFile; 268 bool HasSource = false; 269 private: 270 bool HasAllMD5 = true; 271 bool HasAnyMD5 = false; 272 273 public: 274 MCDwarfLineTableHeader() = default; 275 276 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, 277 std::optional<MD5::MD5Result> Checksum, 278 std::optional<StringRef> Source, 279 uint16_t DwarfVersion, unsigned FileNumber = 0); 280 std::pair<MCSymbol *, MCSymbol *> 281 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 282 std::optional<MCDwarfLineStr> &LineStr) const; 283 std::pair<MCSymbol *, MCSymbol *> 284 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 285 ArrayRef<char> SpecialOpcodeLengths, 286 std::optional<MCDwarfLineStr> &LineStr) const; 287 void resetMD5Usage() { 288 HasAllMD5 = true; 289 HasAnyMD5 = false; 290 } 291 void trackMD5Usage(bool MD5Used) { 292 HasAllMD5 &= MD5Used; 293 HasAnyMD5 |= MD5Used; 294 } 295 bool isMD5UsageConsistent() const { 296 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); 297 } 298 299 void setRootFile(StringRef Directory, StringRef FileName, 300 std::optional<MD5::MD5Result> Checksum, 301 std::optional<StringRef> Source) { 302 CompilationDir = std::string(Directory); 303 RootFile.Name = std::string(FileName); 304 RootFile.DirIndex = 0; 305 RootFile.Checksum = Checksum; 306 RootFile.Source = Source; 307 trackMD5Usage(Checksum.has_value()); 308 HasSource = Source.has_value(); 309 } 310 311 void resetFileTable() { 312 MCDwarfDirs.clear(); 313 MCDwarfFiles.clear(); 314 RootFile.Name.clear(); 315 resetMD5Usage(); 316 HasSource = false; 317 } 318 319 private: 320 void emitV2FileDirTables(MCStreamer *MCOS) const; 321 void emitV5FileDirTables(MCStreamer *MCOS, 322 std::optional<MCDwarfLineStr> &LineStr) const; 323 }; 324 325 class MCDwarfDwoLineTable { 326 MCDwarfLineTableHeader Header; 327 bool HasSplitLineTable = false; 328 329 public: 330 void maybeSetRootFile(StringRef Directory, StringRef FileName, 331 std::optional<MD5::MD5Result> Checksum, 332 std::optional<StringRef> Source) { 333 if (!Header.RootFile.Name.empty()) 334 return; 335 Header.setRootFile(Directory, FileName, Checksum, Source); 336 } 337 338 unsigned getFile(StringRef Directory, StringRef FileName, 339 std::optional<MD5::MD5Result> Checksum, 340 uint16_t DwarfVersion, std::optional<StringRef> Source) { 341 HasSplitLineTable = true; 342 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source, 343 DwarfVersion)); 344 } 345 346 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, 347 MCSection *Section) const; 348 }; 349 350 class MCDwarfLineTable { 351 MCDwarfLineTableHeader Header; 352 MCLineSection MCLineSections; 353 354 public: 355 // This emits the Dwarf file and the line tables for all Compile Units. 356 static void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params); 357 358 // This emits the Dwarf file and the line tables for a given Compile Unit. 359 void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, 360 std::optional<MCDwarfLineStr> &LineStr) const; 361 362 // This emits a single line table associated with a given Section. 363 static void 364 emitOne(MCStreamer *MCOS, MCSection *Section, 365 const MCLineSection::MCDwarfLineEntryCollection &LineEntries); 366 367 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName, 368 std::optional<MD5::MD5Result> Checksum, 369 std::optional<StringRef> Source, 370 uint16_t DwarfVersion, unsigned FileNumber = 0); 371 unsigned getFile(StringRef &Directory, StringRef &FileName, 372 std::optional<MD5::MD5Result> Checksum, 373 std::optional<StringRef> Source, uint16_t DwarfVersion, 374 unsigned FileNumber = 0) { 375 return cantFail(tryGetFile(Directory, FileName, Checksum, Source, 376 DwarfVersion, FileNumber)); 377 } 378 379 void setRootFile(StringRef Directory, StringRef FileName, 380 std::optional<MD5::MD5Result> Checksum, 381 std::optional<StringRef> Source) { 382 Header.CompilationDir = std::string(Directory); 383 Header.RootFile.Name = std::string(FileName); 384 Header.RootFile.DirIndex = 0; 385 Header.RootFile.Checksum = Checksum; 386 Header.RootFile.Source = Source; 387 Header.trackMD5Usage(Checksum.has_value()); 388 Header.HasSource = Source.has_value(); 389 } 390 391 void resetFileTable() { Header.resetFileTable(); } 392 393 bool hasRootFile() const { return !Header.RootFile.Name.empty(); } 394 395 MCDwarfFile &getRootFile() { return Header.RootFile; } 396 const MCDwarfFile &getRootFile() const { return Header.RootFile; } 397 398 // Report whether MD5 usage has been consistent (all-or-none). 399 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } 400 401 MCSymbol *getLabel() const { 402 return Header.Label; 403 } 404 405 void setLabel(MCSymbol *Label) { 406 Header.Label = Label; 407 } 408 409 const SmallVectorImpl<std::string> &getMCDwarfDirs() const { 410 return Header.MCDwarfDirs; 411 } 412 413 SmallVectorImpl<std::string> &getMCDwarfDirs() { 414 return Header.MCDwarfDirs; 415 } 416 417 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { 418 return Header.MCDwarfFiles; 419 } 420 421 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { 422 return Header.MCDwarfFiles; 423 } 424 425 const MCLineSection &getMCLineSections() const { 426 return MCLineSections; 427 } 428 MCLineSection &getMCLineSections() { 429 return MCLineSections; 430 } 431 }; 432 433 class MCDwarfLineAddr { 434 public: 435 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 436 static void encode(MCContext &Context, MCDwarfLineTableParams Params, 437 int64_t LineDelta, uint64_t AddrDelta, SmallVectorImpl<char> &OS); 438 439 /// Utility function to emit the encoding to a streamer. 440 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, 441 int64_t LineDelta, uint64_t AddrDelta); 442 }; 443 444 class MCGenDwarfInfo { 445 public: 446 // 447 // When generating dwarf for assembly source files this emits the Dwarf 448 // sections. 449 // 450 static void Emit(MCStreamer *MCOS); 451 }; 452 453 // When generating dwarf for assembly source files this is the info that is 454 // needed to be gathered for each symbol that will have a dwarf label. 455 class MCGenDwarfLabelEntry { 456 private: 457 // Name of the symbol without a leading underbar, if any. 458 StringRef Name; 459 // The dwarf file number this symbol is in. 460 unsigned FileNumber; 461 // The line number this symbol is at. 462 unsigned LineNumber; 463 // The low_pc for the dwarf label is taken from this symbol. 464 MCSymbol *Label; 465 466 public: 467 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, 468 MCSymbol *label) 469 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), 470 Label(label) {} 471 472 StringRef getName() const { return Name; } 473 unsigned getFileNumber() const { return FileNumber; } 474 unsigned getLineNumber() const { return LineNumber; } 475 MCSymbol *getLabel() const { return Label; } 476 477 // This is called when label is created when we are generating dwarf for 478 // assembly source files. 479 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, 480 SMLoc &Loc); 481 }; 482 483 class MCCFIInstruction { 484 public: 485 enum OpType { 486 OpSameValue, 487 OpRememberState, 488 OpRestoreState, 489 OpOffset, 490 OpLLVMDefAspaceCfa, 491 OpDefCfaRegister, 492 OpDefCfaOffset, 493 OpDefCfa, 494 OpRelOffset, 495 OpAdjustCfaOffset, 496 OpEscape, 497 OpRestore, 498 OpUndefined, 499 OpRegister, 500 OpWindowSave, 501 OpNegateRAState, 502 OpGnuArgsSize 503 }; 504 505 private: 506 OpType Operation; 507 MCSymbol *Label; 508 unsigned Register; 509 union { 510 int Offset; 511 unsigned Register2; 512 }; 513 unsigned AddressSpace = ~0u; 514 SMLoc Loc; 515 std::vector<char> Values; 516 std::string Comment; 517 518 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, SMLoc Loc, 519 StringRef V = "", StringRef Comment = "") 520 : Operation(Op), Label(L), Register(R), Offset(O), Loc(Loc), 521 Values(V.begin(), V.end()), Comment(Comment) { 522 assert(Op != OpRegister && Op != OpLLVMDefAspaceCfa); 523 } 524 525 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2, SMLoc Loc) 526 : Operation(Op), Label(L), Register(R1), Register2(R2), Loc(Loc) { 527 assert(Op == OpRegister); 528 } 529 530 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS, 531 SMLoc Loc) 532 : Operation(Op), Label(L), Register(R), Offset(O), AddressSpace(AS), 533 Loc(Loc) { 534 assert(Op == OpLLVMDefAspaceCfa); 535 } 536 537 public: 538 /// .cfi_def_cfa defines a rule for computing CFA as: take address from 539 /// Register and add Offset to it. 540 static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset, 541 SMLoc Loc = {}) { 542 return MCCFIInstruction(OpDefCfa, L, Register, Offset, Loc); 543 } 544 545 /// .cfi_def_cfa_register modifies a rule for computing CFA. From now 546 /// on Register will be used instead of the old one. Offset remains the same. 547 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, 548 SMLoc Loc = {}) { 549 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, Loc); 550 } 551 552 /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register 553 /// remains the same, but offset is new. Note that it is the absolute offset 554 /// that will be added to a defined register to the compute CFA address. 555 static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, 556 SMLoc Loc = {}) { 557 return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, Loc); 558 } 559 560 /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but 561 /// Offset is a relative value that is added/subtracted from the previous 562 /// offset. 563 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment, 564 SMLoc Loc = {}) { 565 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, Loc); 566 } 567 568 // FIXME: Update the remaining docs to use the new proposal wording. 569 /// .cfi_llvm_def_aspace_cfa defines the rule for computing the CFA to 570 /// be the result of evaluating the DWARF operation expression 571 /// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description. 572 static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register, 573 int Offset, 574 unsigned AddressSpace, 575 SMLoc Loc) { 576 return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset, 577 AddressSpace, Loc); 578 } 579 580 /// .cfi_offset Previous value of Register is saved at offset Offset 581 /// from CFA. 582 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, 583 int Offset, SMLoc Loc = {}) { 584 return MCCFIInstruction(OpOffset, L, Register, Offset, Loc); 585 } 586 587 /// .cfi_rel_offset Previous value of Register is saved at offset 588 /// Offset from the current CFA register. This is transformed to .cfi_offset 589 /// using the known displacement of the CFA register from the CFA. 590 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register, 591 int Offset, SMLoc Loc = {}) { 592 return MCCFIInstruction(OpRelOffset, L, Register, Offset, Loc); 593 } 594 595 /// .cfi_register Previous value of Register1 is saved in 596 /// register Register2. 597 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1, 598 unsigned Register2, SMLoc Loc = {}) { 599 return MCCFIInstruction(OpRegister, L, Register1, Register2, Loc); 600 } 601 602 /// .cfi_window_save SPARC register window is saved. 603 static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) { 604 return MCCFIInstruction(OpWindowSave, L, 0, 0, Loc); 605 } 606 607 /// .cfi_negate_ra_state AArch64 negate RA state. 608 static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc = {}) { 609 return MCCFIInstruction(OpNegateRAState, L, 0, 0, Loc); 610 } 611 612 /// .cfi_restore says that the rule for Register is now the same as it 613 /// was at the beginning of the function, after all initial instructions added 614 /// by .cfi_startproc were executed. 615 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, 616 SMLoc Loc = {}) { 617 return MCCFIInstruction(OpRestore, L, Register, 0, Loc); 618 } 619 620 /// .cfi_undefined From now on the previous value of Register can't be 621 /// restored anymore. 622 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register, 623 SMLoc Loc = {}) { 624 return MCCFIInstruction(OpUndefined, L, Register, 0, Loc); 625 } 626 627 /// .cfi_same_value Current value of Register is the same as in the 628 /// previous frame. I.e., no restoration is needed. 629 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register, 630 SMLoc Loc = {}) { 631 return MCCFIInstruction(OpSameValue, L, Register, 0, Loc); 632 } 633 634 /// .cfi_remember_state Save all current rules for all registers. 635 static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc = {}) { 636 return MCCFIInstruction(OpRememberState, L, 0, 0, Loc); 637 } 638 639 /// .cfi_restore_state Restore the previously saved state. 640 static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc = {}) { 641 return MCCFIInstruction(OpRestoreState, L, 0, 0, Loc); 642 } 643 644 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind 645 /// info. 646 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, 647 SMLoc Loc = {}, StringRef Comment = "") { 648 return MCCFIInstruction(OpEscape, L, 0, 0, Loc, Vals, Comment); 649 } 650 651 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE 652 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size, 653 SMLoc Loc = {}) { 654 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc); 655 } 656 657 OpType getOperation() const { return Operation; } 658 MCSymbol *getLabel() const { return Label; } 659 660 unsigned getRegister() const { 661 assert(Operation == OpDefCfa || Operation == OpOffset || 662 Operation == OpRestore || Operation == OpUndefined || 663 Operation == OpSameValue || Operation == OpDefCfaRegister || 664 Operation == OpRelOffset || Operation == OpRegister || 665 Operation == OpLLVMDefAspaceCfa); 666 return Register; 667 } 668 669 unsigned getRegister2() const { 670 assert(Operation == OpRegister); 671 return Register2; 672 } 673 674 unsigned getAddressSpace() const { 675 assert(Operation == OpLLVMDefAspaceCfa); 676 return AddressSpace; 677 } 678 679 int getOffset() const { 680 assert(Operation == OpDefCfa || Operation == OpOffset || 681 Operation == OpRelOffset || Operation == OpDefCfaOffset || 682 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize || 683 Operation == OpLLVMDefAspaceCfa); 684 return Offset; 685 } 686 687 StringRef getValues() const { 688 assert(Operation == OpEscape); 689 return StringRef(&Values[0], Values.size()); 690 } 691 692 StringRef getComment() const { return Comment; } 693 SMLoc getLoc() const { return Loc; } 694 }; 695 696 struct MCDwarfFrameInfo { 697 MCDwarfFrameInfo() = default; 698 699 MCSymbol *Begin = nullptr; 700 MCSymbol *End = nullptr; 701 const MCSymbol *Personality = nullptr; 702 const MCSymbol *Lsda = nullptr; 703 std::vector<MCCFIInstruction> Instructions; 704 unsigned CurrentCfaRegister = 0; 705 unsigned PersonalityEncoding = 0; 706 unsigned LsdaEncoding = 0; 707 uint32_t CompactUnwindEncoding = 0; 708 bool IsSignalFrame = false; 709 bool IsSimple = false; 710 unsigned RAReg = static_cast<unsigned>(INT_MAX); 711 bool IsBKeyFrame = false; 712 bool IsMTETaggedFrame = false; 713 }; 714 715 class MCDwarfFrameEmitter { 716 public: 717 // 718 // This emits the frame info section. 719 // 720 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH); 721 static void encodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, 722 SmallVectorImpl<char> &OS); 723 }; 724 725 } // end namespace llvm 726 727 #endif // LLVM_MC_MCDWARF_H 728