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