MCDwarf.h 22 KB

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