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