blob: 2bfaf19cf2c64ace28f67de449673d51b2ea05ff [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the declaration of the MCDwarfFile to support the dwarf
11// .file directive and the .loc directive.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_MC_MCDWARF_H
16#define LLVM_MC_MCDWARF_H
17
18#include "llvm/ADT/MapVector.h"
19#include "llvm/ADT/Optional.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/MC/MCSection.h"
24#include "llvm/Support/Error.h"
25#include "llvm/Support/MD5.h"
26#include <cassert>
27#include <cstdint>
28#include <string>
29#include <utility>
30#include <vector>
31
32namespace llvm {
33
34template <typename T> class ArrayRef;
35class MCAsmBackend;
36class MCContext;
37class MCDwarfLineStr;
38class MCObjectStreamer;
39class MCStreamer;
40class MCSymbol;
41class raw_ostream;
42class SMLoc;
43class SourceMgr;
44
Andrew Scullcdfcccc2018-10-05 20:58:37 +010045/// Instances of this class represent the name of the dwarf
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046/// .file directive and its associated dwarf file number in the MC file,
47/// and MCDwarfFile's are created and uniqued by the MCContext class where
48/// the file number for each is its index into the vector of DwarfFiles (note
49/// index 0 is not used and not a valid dwarf file number).
50struct MCDwarfFile {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010051 // The base name of the file without its directory path.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010052 std::string Name;
53
Andrew Scullcdfcccc2018-10-05 20:58:37 +010054 // The index into the list of directory names for this file name.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010055 unsigned DirIndex;
56
57 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
58 /// in MCContext.
59 MD5::MD5Result *Checksum = nullptr;
60
61 /// The source code of the file. Non-owning reference to data allocated in
62 /// MCContext.
63 Optional<StringRef> Source;
64};
65
Andrew Scullcdfcccc2018-10-05 20:58:37 +010066/// Instances of this class represent the information from a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010067/// dwarf .loc directive.
68class MCDwarfLoc {
69 uint32_t FileNum;
70 uint32_t Line;
71 uint16_t Column;
72 // Flags (see #define's below)
73 uint8_t Flags;
74 uint8_t Isa;
75 uint32_t Discriminator;
76
77// Flag that indicates the initial value of the is_stmt_start flag.
78#define DWARF2_LINE_DEFAULT_IS_STMT 1
79
80#define DWARF2_FLAG_IS_STMT (1 << 0)
81#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
82#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
83#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
84
85private: // MCContext manages these
86 friend class MCContext;
87 friend class MCDwarfLineEntry;
88
89 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
90 unsigned isa, unsigned discriminator)
91 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
92 Discriminator(discriminator) {}
93
94 // Allow the default copy constructor and assignment operator to be used
95 // for an MCDwarfLoc object.
96
97public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010098 /// Get the FileNum of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010099 unsigned getFileNum() const { return FileNum; }
100
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100101 /// Get the Line of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100102 unsigned getLine() const { return Line; }
103
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100104 /// Get the Column of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100105 unsigned getColumn() const { return Column; }
106
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100107 /// Get the Flags of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100108 unsigned getFlags() const { return Flags; }
109
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100110 /// Get the Isa of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100111 unsigned getIsa() const { return Isa; }
112
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100113 /// Get the Discriminator of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100114 unsigned getDiscriminator() const { return Discriminator; }
115
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100116 /// Set the FileNum of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100117 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
118
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100119 /// Set the Line of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100120 void setLine(unsigned line) { Line = line; }
121
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100122 /// Set the Column of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100123 void setColumn(unsigned column) {
124 assert(column <= UINT16_MAX);
125 Column = column;
126 }
127
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100128 /// Set the Flags of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100129 void setFlags(unsigned flags) {
130 assert(flags <= UINT8_MAX);
131 Flags = flags;
132 }
133
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100134 /// Set the Isa of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100135 void setIsa(unsigned isa) {
136 assert(isa <= UINT8_MAX);
137 Isa = isa;
138 }
139
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100140 /// Set the Discriminator of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100141 void setDiscriminator(unsigned discriminator) {
142 Discriminator = discriminator;
143 }
144};
145
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100146/// Instances of this class represent the line information for
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100147/// the dwarf line table entries. Which is created after a machine
148/// instruction is assembled and uses an address from a temporary label
149/// created at the current address in the current section and the info from
150/// the last .loc directive seen as stored in the context.
151class MCDwarfLineEntry : public MCDwarfLoc {
152 MCSymbol *Label;
153
154private:
155 // Allow the default copy constructor and assignment operator to be used
156 // for an MCDwarfLineEntry object.
157
158public:
159 // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
160 MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
161 : MCDwarfLoc(loc), Label(label) {}
162
163 MCSymbol *getLabel() const { return Label; }
164
165 // This is called when an instruction is assembled into the specified
166 // section and if there is information from the last .loc directive that
167 // has yet to have a line entry made for it is made.
168 static void Make(MCObjectStreamer *MCOS, MCSection *Section);
169};
170
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100171/// Instances of this class represent the line information for a compile
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100172/// unit where machine instructions have been assembled after seeing .loc
173/// directives. This is the information used to build the dwarf line
174/// table for a section.
175class MCLineSection {
176public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100177 // Add an entry to this MCLineSection's line entries.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100178 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
179 MCLineDivisions[Sec].push_back(LineEntry);
180 }
181
182 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
183 using iterator = MCDwarfLineEntryCollection::iterator;
184 using const_iterator = MCDwarfLineEntryCollection::const_iterator;
185 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
186
187private:
188 // A collection of MCDwarfLineEntry for each section.
189 MCLineDivisionMap MCLineDivisions;
190
191public:
192 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
193 const MCLineDivisionMap &getMCLineEntries() const {
194 return MCLineDivisions;
195 }
196};
197
198struct MCDwarfLineTableParams {
199 /// First special line opcode - leave room for the standard opcodes.
200 /// Note: If you want to change this, you'll have to update the
201 /// "StandardOpcodeLengths" table that is emitted in
202 /// \c Emit().
203 uint8_t DWARF2LineOpcodeBase = 13;
204 /// Minimum line offset in a special line info. opcode. The value
205 /// -5 was chosen to give a reasonable range of values.
206 int8_t DWARF2LineBase = -5;
207 /// Range of line offsets in a special line info. opcode.
208 uint8_t DWARF2LineRange = 14;
209};
210
211struct MCDwarfLineTableHeader {
212 MCSymbol *Label = nullptr;
213 SmallVector<std::string, 3> MCDwarfDirs;
214 SmallVector<MCDwarfFile, 3> MCDwarfFiles;
215 StringMap<unsigned> SourceIdMap;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100216 std::string CompilationDir;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100217 MCDwarfFile RootFile;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100218 bool HasSource = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100219private:
220 bool HasAllMD5 = true;
221 bool HasAnyMD5 = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100222
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100223public:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100224 MCDwarfLineTableHeader() = default;
225
226 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
227 MD5::MD5Result *Checksum,
228 Optional<StringRef> &Source,
229 unsigned FileNumber = 0);
230 std::pair<MCSymbol *, MCSymbol *>
231 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
232 Optional<MCDwarfLineStr> &LineStr) const;
233 std::pair<MCSymbol *, MCSymbol *>
234 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
235 ArrayRef<char> SpecialOpcodeLengths,
236 Optional<MCDwarfLineStr> &LineStr) const;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100237 void resetMD5Usage() {
238 HasAllMD5 = true;
239 HasAnyMD5 = false;
240 }
241 void trackMD5Usage(bool MD5Used) {
242 HasAllMD5 &= MD5Used;
243 HasAnyMD5 |= MD5Used;
244 }
245 bool isMD5UsageConsistent() const {
246 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
247 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100248
249private:
250 void emitV2FileDirTables(MCStreamer *MCOS) const;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100251 void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr,
252 StringRef CtxCompilationDir) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100253};
254
255class MCDwarfDwoLineTable {
256 MCDwarfLineTableHeader Header;
257
258public:
259 void maybeSetRootFile(StringRef Directory, StringRef FileName,
260 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
261 if (!Header.RootFile.Name.empty())
262 return;
263 Header.CompilationDir = Directory;
264 Header.RootFile.Name = FileName;
265 Header.RootFile.DirIndex = 0;
266 Header.RootFile.Checksum = Checksum;
267 Header.RootFile.Source = Source;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100268 Header.trackMD5Usage(Checksum);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100269 Header.HasSource = Source.hasValue();
270 }
271
272 unsigned getFile(StringRef Directory, StringRef FileName,
273 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
274 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
275 }
276
277 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
278 MCSection *Section) const;
279};
280
281class MCDwarfLineTable {
282 MCDwarfLineTableHeader Header;
283 MCLineSection MCLineSections;
284
285public:
286 // This emits the Dwarf file and the line tables for all Compile Units.
287 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
288
289 // This emits the Dwarf file and the line tables for a given Compile Unit.
290 void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
291 Optional<MCDwarfLineStr> &LineStr) const;
292
293 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
294 MD5::MD5Result *Checksum,
295 Optional<StringRef> Source,
296 unsigned FileNumber = 0);
297 unsigned getFile(StringRef &Directory, StringRef &FileName,
298 MD5::MD5Result *Checksum, Optional<StringRef> &Source,
299 unsigned FileNumber = 0) {
300 return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
301 FileNumber));
302 }
303
304 void setRootFile(StringRef Directory, StringRef FileName,
305 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
306 Header.CompilationDir = Directory;
307 Header.RootFile.Name = FileName;
308 Header.RootFile.DirIndex = 0;
309 Header.RootFile.Checksum = Checksum;
310 Header.RootFile.Source = Source;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100311 Header.trackMD5Usage(Checksum);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100312 Header.HasSource = Source.hasValue();
313 }
314
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100315 void resetRootFile() {
316 assert(Header.MCDwarfFiles.empty());
317 Header.RootFile.Name.clear();
318 Header.resetMD5Usage();
319 Header.HasSource = false;
320 }
321
322 bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
323
324 // Report whether MD5 usage has been consistent (all-or-none).
325 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
326
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100327 MCSymbol *getLabel() const {
328 return Header.Label;
329 }
330
331 void setLabel(MCSymbol *Label) {
332 Header.Label = Label;
333 }
334
335 const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
336 return Header.MCDwarfDirs;
337 }
338
339 SmallVectorImpl<std::string> &getMCDwarfDirs() {
340 return Header.MCDwarfDirs;
341 }
342
343 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
344 return Header.MCDwarfFiles;
345 }
346
347 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
348 return Header.MCDwarfFiles;
349 }
350
351 const MCLineSection &getMCLineSections() const {
352 return MCLineSections;
353 }
354 MCLineSection &getMCLineSections() {
355 return MCLineSections;
356 }
357};
358
359class MCDwarfLineAddr {
360public:
361 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
362 static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
363 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
364
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100365 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
366 /// fixed length operands.
367 static bool FixedEncode(MCContext &Context,
368 MCDwarfLineTableParams Params,
369 int64_t LineDelta, uint64_t AddrDelta,
370 raw_ostream &OS, uint32_t *Offset, uint32_t *Size);
371
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100372 /// Utility function to emit the encoding to a streamer.
373 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
374 int64_t LineDelta, uint64_t AddrDelta);
375};
376
377class MCGenDwarfInfo {
378public:
379 //
380 // When generating dwarf for assembly source files this emits the Dwarf
381 // sections.
382 //
383 static void Emit(MCStreamer *MCOS);
384};
385
386// When generating dwarf for assembly source files this is the info that is
387// needed to be gathered for each symbol that will have a dwarf label.
388class MCGenDwarfLabelEntry {
389private:
390 // Name of the symbol without a leading underbar, if any.
391 StringRef Name;
392 // The dwarf file number this symbol is in.
393 unsigned FileNumber;
394 // The line number this symbol is at.
395 unsigned LineNumber;
396 // The low_pc for the dwarf label is taken from this symbol.
397 MCSymbol *Label;
398
399public:
400 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
401 MCSymbol *label)
402 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
403 Label(label) {}
404
405 StringRef getName() const { return Name; }
406 unsigned getFileNumber() const { return FileNumber; }
407 unsigned getLineNumber() const { return LineNumber; }
408 MCSymbol *getLabel() const { return Label; }
409
410 // This is called when label is created when we are generating dwarf for
411 // assembly source files.
412 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
413 SMLoc &Loc);
414};
415
416class MCCFIInstruction {
417public:
418 enum OpType {
419 OpSameValue,
420 OpRememberState,
421 OpRestoreState,
422 OpOffset,
423 OpDefCfaRegister,
424 OpDefCfaOffset,
425 OpDefCfa,
426 OpRelOffset,
427 OpAdjustCfaOffset,
428 OpEscape,
429 OpRestore,
430 OpUndefined,
431 OpRegister,
432 OpWindowSave,
433 OpGnuArgsSize
434 };
435
436private:
437 OpType Operation;
438 MCSymbol *Label;
439 unsigned Register;
440 union {
441 int Offset;
442 unsigned Register2;
443 };
444 std::vector<char> Values;
445
446 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
447 : Operation(Op), Label(L), Register(R), Offset(O),
448 Values(V.begin(), V.end()) {
449 assert(Op != OpRegister);
450 }
451
452 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
453 : Operation(Op), Label(L), Register(R1), Register2(R2) {
454 assert(Op == OpRegister);
455 }
456
457public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100458 /// .cfi_def_cfa defines a rule for computing CFA as: take address from
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100459 /// Register and add Offset to it.
460 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
461 int Offset) {
462 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
463 }
464
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100465 /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100466 /// on Register will be used instead of the old one. Offset remains the same.
467 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
468 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
469 }
470
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100471 /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100472 /// remains the same, but offset is new. Note that it is the absolute offset
473 /// that will be added to a defined register to the compute CFA address.
474 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
475 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
476 }
477
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100478 /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100479 /// Offset is a relative value that is added/subtracted from the previous
480 /// offset.
481 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
482 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
483 }
484
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100485 /// .cfi_offset Previous value of Register is saved at offset Offset
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100486 /// from CFA.
487 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
488 int Offset) {
489 return MCCFIInstruction(OpOffset, L, Register, Offset, "");
490 }
491
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100492 /// .cfi_rel_offset Previous value of Register is saved at offset
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100493 /// Offset from the current CFA register. This is transformed to .cfi_offset
494 /// using the known displacement of the CFA register from the CFA.
495 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
496 int Offset) {
497 return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
498 }
499
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100500 /// .cfi_register Previous value of Register1 is saved in
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100501 /// register Register2.
502 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
503 unsigned Register2) {
504 return MCCFIInstruction(OpRegister, L, Register1, Register2);
505 }
506
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100507 /// .cfi_window_save SPARC register window is saved.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100508 static MCCFIInstruction createWindowSave(MCSymbol *L) {
509 return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
510 }
511
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100512 /// .cfi_restore says that the rule for Register is now the same as it
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100513 /// was at the beginning of the function, after all initial instructions added
514 /// by .cfi_startproc were executed.
515 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
516 return MCCFIInstruction(OpRestore, L, Register, 0, "");
517 }
518
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100519 /// .cfi_undefined From now on the previous value of Register can't be
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100520 /// restored anymore.
521 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
522 return MCCFIInstruction(OpUndefined, L, Register, 0, "");
523 }
524
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100525 /// .cfi_same_value Current value of Register is the same as in the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100526 /// previous frame. I.e., no restoration is needed.
527 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
528 return MCCFIInstruction(OpSameValue, L, Register, 0, "");
529 }
530
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100531 /// .cfi_remember_state Save all current rules for all registers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100532 static MCCFIInstruction createRememberState(MCSymbol *L) {
533 return MCCFIInstruction(OpRememberState, L, 0, 0, "");
534 }
535
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100536 /// .cfi_restore_state Restore the previously saved state.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100537 static MCCFIInstruction createRestoreState(MCSymbol *L) {
538 return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
539 }
540
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100541 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100542 /// info.
543 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
544 return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
545 }
546
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100547 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100548 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
549 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
550 }
551
552 OpType getOperation() const { return Operation; }
553 MCSymbol *getLabel() const { return Label; }
554
555 unsigned getRegister() const {
556 assert(Operation == OpDefCfa || Operation == OpOffset ||
557 Operation == OpRestore || Operation == OpUndefined ||
558 Operation == OpSameValue || Operation == OpDefCfaRegister ||
559 Operation == OpRelOffset || Operation == OpRegister);
560 return Register;
561 }
562
563 unsigned getRegister2() const {
564 assert(Operation == OpRegister);
565 return Register2;
566 }
567
568 int getOffset() const {
569 assert(Operation == OpDefCfa || Operation == OpOffset ||
570 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
571 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
572 return Offset;
573 }
574
575 StringRef getValues() const {
576 assert(Operation == OpEscape);
577 return StringRef(&Values[0], Values.size());
578 }
579};
580
581struct MCDwarfFrameInfo {
582 MCDwarfFrameInfo() = default;
583
584 MCSymbol *Begin = nullptr;
585 MCSymbol *End = nullptr;
586 const MCSymbol *Personality = nullptr;
587 const MCSymbol *Lsda = nullptr;
588 std::vector<MCCFIInstruction> Instructions;
589 unsigned CurrentCfaRegister = 0;
590 unsigned PersonalityEncoding = 0;
591 unsigned LsdaEncoding = 0;
592 uint32_t CompactUnwindEncoding = 0;
593 bool IsSignalFrame = false;
594 bool IsSimple = false;
595 unsigned RAReg = static_cast<unsigned>(INT_MAX);
596};
597
598class MCDwarfFrameEmitter {
599public:
600 //
601 // This emits the frame info section.
602 //
603 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
604 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
605 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
606 raw_ostream &OS);
607};
608
609} // end namespace llvm
610
611#endif // LLVM_MC_MCDWARF_H