MCDwarf.h 22 KB

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