blob: 8eaa1523fe843ecbba5a4cbb1b13701d3ce9b42a [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the declaration of the MCDwarfFile to support the dwarf
10// .file directive and the .loc directive.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_MC_MCDWARF_H
15#define LLVM_MC_MCDWARF_H
16
17#include "llvm/ADT/MapVector.h"
18#include "llvm/ADT/Optional.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringMap.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/MC/MCSection.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/MD5.h"
25#include <cassert>
26#include <cstdint>
27#include <string>
28#include <utility>
29#include <vector>
30
31namespace llvm {
32
33template <typename T> class ArrayRef;
34class MCAsmBackend;
35class MCContext;
36class MCDwarfLineStr;
37class MCObjectStreamer;
38class MCStreamer;
39class MCSymbol;
40class raw_ostream;
41class SMLoc;
42class SourceMgr;
43
Andrew Scullcdfcccc2018-10-05 20:58:37 +010044/// Instances of this class represent the name of the dwarf
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010045/// .file directive and its associated dwarf file number in the MC file,
46/// and MCDwarfFile's are created and uniqued by the MCContext class where
47/// the file number for each is its index into the vector of DwarfFiles (note
48/// index 0 is not used and not a valid dwarf file number).
49struct MCDwarfFile {
Andrew Scullcdfcccc2018-10-05 20:58:37 +010050 // The base name of the file without its directory path.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010051 std::string Name;
52
Andrew Scullcdfcccc2018-10-05 20:58:37 +010053 // The index into the list of directory names for this file name.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010054 unsigned DirIndex;
55
56 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
57 /// in MCContext.
58 MD5::MD5Result *Checksum = nullptr;
59
60 /// The source code of the file. Non-owning reference to data allocated in
61 /// MCContext.
62 Optional<StringRef> Source;
63};
64
Andrew Scullcdfcccc2018-10-05 20:58:37 +010065/// Instances of this class represent the information from a
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010066/// dwarf .loc directive.
67class MCDwarfLoc {
68 uint32_t FileNum;
69 uint32_t Line;
70 uint16_t Column;
71 // Flags (see #define's below)
72 uint8_t Flags;
73 uint8_t Isa;
74 uint32_t Discriminator;
75
76// Flag that indicates the initial value of the is_stmt_start flag.
77#define DWARF2_LINE_DEFAULT_IS_STMT 1
78
79#define DWARF2_FLAG_IS_STMT (1 << 0)
80#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
81#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
82#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
83
84private: // MCContext manages these
85 friend class MCContext;
86 friend class MCDwarfLineEntry;
87
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
93 // Allow the default copy constructor and assignment operator to be used
94 // for an MCDwarfLoc object.
95
96public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +010097 /// Get the FileNum of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098 unsigned getFileNum() const { return FileNum; }
99
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100100 /// Get the Line of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101 unsigned getLine() const { return Line; }
102
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100103 /// Get the Column of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100104 unsigned getColumn() const { return Column; }
105
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100106 /// Get the Flags of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100107 unsigned getFlags() const { return Flags; }
108
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100109 /// Get the Isa of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100110 unsigned getIsa() const { return Isa; }
111
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100112 /// Get the Discriminator of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100113 unsigned getDiscriminator() const { return Discriminator; }
114
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100115 /// Set the FileNum of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
117
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100118 /// Set the Line of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100119 void setLine(unsigned line) { Line = line; }
120
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100121 /// Set the Column of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100122 void setColumn(unsigned column) {
123 assert(column <= UINT16_MAX);
124 Column = column;
125 }
126
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100127 /// Set the Flags of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100128 void setFlags(unsigned flags) {
129 assert(flags <= UINT8_MAX);
130 Flags = flags;
131 }
132
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100133 /// Set the Isa of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100134 void setIsa(unsigned isa) {
135 assert(isa <= UINT8_MAX);
136 Isa = isa;
137 }
138
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100139 /// Set the Discriminator of this MCDwarfLoc.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100140 void setDiscriminator(unsigned discriminator) {
141 Discriminator = discriminator;
142 }
143};
144
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100145/// Instances of this class represent the line information for
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100146/// the dwarf line table entries. Which is created after a machine
147/// instruction is assembled and uses an address from a temporary label
148/// created at the current address in the current section and the info from
149/// the last .loc directive seen as stored in the context.
150class MCDwarfLineEntry : public MCDwarfLoc {
151 MCSymbol *Label;
152
153private:
154 // Allow the default copy constructor and assignment operator to be used
155 // for an MCDwarfLineEntry object.
156
157public:
158 // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
159 MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
160 : MCDwarfLoc(loc), Label(label) {}
161
162 MCSymbol *getLabel() const { return Label; }
163
164 // This is called when an instruction is assembled into the specified
165 // section and if there is information from the last .loc directive that
166 // has yet to have a line entry made for it is made.
167 static void Make(MCObjectStreamer *MCOS, MCSection *Section);
168};
169
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100170/// Instances of this class represent the line information for a compile
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100171/// unit where machine instructions have been assembled after seeing .loc
172/// directives. This is the information used to build the dwarf line
173/// table for a section.
174class MCLineSection {
175public:
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100176 // Add an entry to this MCLineSection's line entries.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100177 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
178 MCLineDivisions[Sec].push_back(LineEntry);
179 }
180
181 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
182 using iterator = MCDwarfLineEntryCollection::iterator;
183 using const_iterator = MCDwarfLineEntryCollection::const_iterator;
184 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
185
186private:
187 // A collection of MCDwarfLineEntry for each section.
188 MCLineDivisionMap MCLineDivisions;
189
190public:
191 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
192 const MCLineDivisionMap &getMCLineEntries() const {
193 return MCLineDivisions;
194 }
195};
196
197struct MCDwarfLineTableParams {
198 /// First special line opcode - leave room for the standard opcodes.
199 /// Note: If you want to change this, you'll have to update the
200 /// "StandardOpcodeLengths" table that is emitted in
201 /// \c Emit().
202 uint8_t DWARF2LineOpcodeBase = 13;
203 /// Minimum line offset in a special line info. opcode. The value
204 /// -5 was chosen to give a reasonable range of values.
205 int8_t DWARF2LineBase = -5;
206 /// Range of line offsets in a special line info. opcode.
207 uint8_t DWARF2LineRange = 14;
208};
209
210struct MCDwarfLineTableHeader {
211 MCSymbol *Label = nullptr;
212 SmallVector<std::string, 3> MCDwarfDirs;
213 SmallVector<MCDwarfFile, 3> MCDwarfFiles;
214 StringMap<unsigned> SourceIdMap;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100215 std::string CompilationDir;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100216 MCDwarfFile RootFile;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100217 bool HasSource = false;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100218private:
219 bool HasAllMD5 = true;
220 bool HasAnyMD5 = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100221
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100222public:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100223 MCDwarfLineTableHeader() = default;
224
225 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
226 MD5::MD5Result *Checksum,
227 Optional<StringRef> &Source,
228 unsigned FileNumber = 0);
229 std::pair<MCSymbol *, MCSymbol *>
230 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
231 Optional<MCDwarfLineStr> &LineStr) const;
232 std::pair<MCSymbol *, MCSymbol *>
233 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
234 ArrayRef<char> SpecialOpcodeLengths,
235 Optional<MCDwarfLineStr> &LineStr) const;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100236 void resetMD5Usage() {
237 HasAllMD5 = true;
238 HasAnyMD5 = false;
239 }
240 void trackMD5Usage(bool MD5Used) {
241 HasAllMD5 &= MD5Used;
242 HasAnyMD5 |= MD5Used;
243 }
244 bool isMD5UsageConsistent() const {
245 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
246 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100247
248private:
249 void emitV2FileDirTables(MCStreamer *MCOS) const;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100250 void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr,
251 StringRef CtxCompilationDir) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100252};
253
254class MCDwarfDwoLineTable {
255 MCDwarfLineTableHeader Header;
256
257public:
258 void maybeSetRootFile(StringRef Directory, StringRef FileName,
259 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
260 if (!Header.RootFile.Name.empty())
261 return;
262 Header.CompilationDir = Directory;
263 Header.RootFile.Name = FileName;
264 Header.RootFile.DirIndex = 0;
265 Header.RootFile.Checksum = Checksum;
266 Header.RootFile.Source = Source;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100267 Header.trackMD5Usage(Checksum);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100268 Header.HasSource = Source.hasValue();
269 }
270
271 unsigned getFile(StringRef Directory, StringRef FileName,
272 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
273 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
274 }
275
276 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
277 MCSection *Section) const;
278};
279
280class MCDwarfLineTable {
281 MCDwarfLineTableHeader Header;
282 MCLineSection MCLineSections;
283
284public:
285 // This emits the Dwarf file and the line tables for all Compile Units.
286 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
287
288 // This emits the Dwarf file and the line tables for a given Compile Unit.
289 void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
290 Optional<MCDwarfLineStr> &LineStr) const;
291
292 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
293 MD5::MD5Result *Checksum,
294 Optional<StringRef> Source,
295 unsigned FileNumber = 0);
296 unsigned getFile(StringRef &Directory, StringRef &FileName,
297 MD5::MD5Result *Checksum, Optional<StringRef> &Source,
298 unsigned FileNumber = 0) {
299 return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
300 FileNumber));
301 }
302
303 void setRootFile(StringRef Directory, StringRef FileName,
304 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
305 Header.CompilationDir = Directory;
306 Header.RootFile.Name = FileName;
307 Header.RootFile.DirIndex = 0;
308 Header.RootFile.Checksum = Checksum;
309 Header.RootFile.Source = Source;
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100310 Header.trackMD5Usage(Checksum);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100311 Header.HasSource = Source.hasValue();
312 }
313
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100314 void resetRootFile() {
315 assert(Header.MCDwarfFiles.empty());
316 Header.RootFile.Name.clear();
317 Header.resetMD5Usage();
318 Header.HasSource = false;
319 }
320
321 bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
322
323 // Report whether MD5 usage has been consistent (all-or-none).
324 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
325
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100326 MCSymbol *getLabel() const {
327 return Header.Label;
328 }
329
330 void setLabel(MCSymbol *Label) {
331 Header.Label = Label;
332 }
333
334 const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
335 return Header.MCDwarfDirs;
336 }
337
338 SmallVectorImpl<std::string> &getMCDwarfDirs() {
339 return Header.MCDwarfDirs;
340 }
341
342 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
343 return Header.MCDwarfFiles;
344 }
345
346 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
347 return Header.MCDwarfFiles;
348 }
349
350 const MCLineSection &getMCLineSections() const {
351 return MCLineSections;
352 }
353 MCLineSection &getMCLineSections() {
354 return MCLineSections;
355 }
356};
357
358class MCDwarfLineAddr {
359public:
360 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
361 static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
362 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
363
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100364 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
365 /// fixed length operands.
366 static bool FixedEncode(MCContext &Context,
367 MCDwarfLineTableParams Params,
368 int64_t LineDelta, uint64_t AddrDelta,
369 raw_ostream &OS, uint32_t *Offset, uint32_t *Size);
370
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100371 /// Utility function to emit the encoding to a streamer.
372 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
373 int64_t LineDelta, uint64_t AddrDelta);
374};
375
376class MCGenDwarfInfo {
377public:
378 //
379 // When generating dwarf for assembly source files this emits the Dwarf
380 // sections.
381 //
382 static void Emit(MCStreamer *MCOS);
383};
384
385// When generating dwarf for assembly source files this is the info that is
386// needed to be gathered for each symbol that will have a dwarf label.
387class MCGenDwarfLabelEntry {
388private:
389 // Name of the symbol without a leading underbar, if any.
390 StringRef Name;
391 // The dwarf file number this symbol is in.
392 unsigned FileNumber;
393 // The line number this symbol is at.
394 unsigned LineNumber;
395 // The low_pc for the dwarf label is taken from this symbol.
396 MCSymbol *Label;
397
398public:
399 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
400 MCSymbol *label)
401 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
402 Label(label) {}
403
404 StringRef getName() const { return Name; }
405 unsigned getFileNumber() const { return FileNumber; }
406 unsigned getLineNumber() const { return LineNumber; }
407 MCSymbol *getLabel() const { return Label; }
408
409 // This is called when label is created when we are generating dwarf for
410 // assembly source files.
411 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
412 SMLoc &Loc);
413};
414
415class MCCFIInstruction {
416public:
417 enum OpType {
418 OpSameValue,
419 OpRememberState,
420 OpRestoreState,
421 OpOffset,
422 OpDefCfaRegister,
423 OpDefCfaOffset,
424 OpDefCfa,
425 OpRelOffset,
426 OpAdjustCfaOffset,
427 OpEscape,
428 OpRestore,
429 OpUndefined,
430 OpRegister,
431 OpWindowSave,
Andrew Walbran16937d02019-10-22 13:54:20 +0100432 OpNegateRAState,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100433 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 Walbran16937d02019-10-22 13:54:20 +0100512 /// .cfi_negate_ra_state AArch64 negate RA state.
513 static MCCFIInstruction createNegateRAState(MCSymbol *L) {
514 return MCCFIInstruction(OpNegateRAState, L, 0, 0, "");
515 }
516
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100517 /// .cfi_restore says that the rule for Register is now the same as it
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100518 /// was at the beginning of the function, after all initial instructions added
519 /// by .cfi_startproc were executed.
520 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
521 return MCCFIInstruction(OpRestore, L, Register, 0, "");
522 }
523
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100524 /// .cfi_undefined From now on the previous value of Register can't be
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100525 /// restored anymore.
526 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
527 return MCCFIInstruction(OpUndefined, L, Register, 0, "");
528 }
529
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100530 /// .cfi_same_value Current value of Register is the same as in the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100531 /// previous frame. I.e., no restoration is needed.
532 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
533 return MCCFIInstruction(OpSameValue, L, Register, 0, "");
534 }
535
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100536 /// .cfi_remember_state Save all current rules for all registers.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100537 static MCCFIInstruction createRememberState(MCSymbol *L) {
538 return MCCFIInstruction(OpRememberState, L, 0, 0, "");
539 }
540
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100541 /// .cfi_restore_state Restore the previously saved state.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100542 static MCCFIInstruction createRestoreState(MCSymbol *L) {
543 return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
544 }
545
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100546 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100547 /// info.
548 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
549 return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
550 }
551
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100552 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100553 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
554 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
555 }
556
557 OpType getOperation() const { return Operation; }
558 MCSymbol *getLabel() const { return Label; }
559
560 unsigned getRegister() const {
561 assert(Operation == OpDefCfa || Operation == OpOffset ||
562 Operation == OpRestore || Operation == OpUndefined ||
563 Operation == OpSameValue || Operation == OpDefCfaRegister ||
564 Operation == OpRelOffset || Operation == OpRegister);
565 return Register;
566 }
567
568 unsigned getRegister2() const {
569 assert(Operation == OpRegister);
570 return Register2;
571 }
572
573 int getOffset() const {
574 assert(Operation == OpDefCfa || Operation == OpOffset ||
575 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
576 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
577 return Offset;
578 }
579
580 StringRef getValues() const {
581 assert(Operation == OpEscape);
582 return StringRef(&Values[0], Values.size());
583 }
584};
585
586struct MCDwarfFrameInfo {
587 MCDwarfFrameInfo() = default;
588
589 MCSymbol *Begin = nullptr;
590 MCSymbol *End = nullptr;
591 const MCSymbol *Personality = nullptr;
592 const MCSymbol *Lsda = nullptr;
593 std::vector<MCCFIInstruction> Instructions;
594 unsigned CurrentCfaRegister = 0;
595 unsigned PersonalityEncoding = 0;
596 unsigned LsdaEncoding = 0;
597 uint32_t CompactUnwindEncoding = 0;
598 bool IsSignalFrame = false;
599 bool IsSimple = false;
600 unsigned RAReg = static_cast<unsigned>(INT_MAX);
Andrew Walbran16937d02019-10-22 13:54:20 +0100601 bool IsBKeyFrame = false;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100602};
603
604class MCDwarfFrameEmitter {
605public:
606 //
607 // This emits the frame info section.
608 //
609 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
610 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
611 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
612 raw_ostream &OS);
613};
614
615} // end namespace llvm
616
617#endif // LLVM_MC_MCDWARF_H