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