MCDwarf.h 24 KB

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