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