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