Recommit [NFC] Better encapsulation of llvm::Optional Storage
[llvm-complete.git] / include / llvm / MC / MCDwarf.h
blob8eaa1523fe843ecbba5a4cbb1b13701d3ce9b42a
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.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_MC_MCDWARF_H
15 #define LLVM_MC_MCDWARF_H
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>
31 namespace llvm {
33 template <typename T> class ArrayRef;
34 class MCAsmBackend;
35 class MCContext;
36 class MCDwarfLineStr;
37 class MCObjectStreamer;
38 class MCStreamer;
39 class MCSymbol;
40 class raw_ostream;
41 class SMLoc;
42 class SourceMgr;
44 /// Instances of this class represent the name of the dwarf
45 /// .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).
49 struct MCDwarfFile {
50 // The base name of the file without its directory path.
51 std::string Name;
53 // The index into the list of directory names for this file name.
54 unsigned DirIndex;
56 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
57 /// in MCContext.
58 MD5::MD5Result *Checksum = nullptr;
60 /// The source code of the file. Non-owning reference to data allocated in
61 /// MCContext.
62 Optional<StringRef> Source;
65 /// Instances of this class represent the information from a
66 /// dwarf .loc directive.
67 class 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;
76 // Flag that indicates the initial value of the is_stmt_start flag.
77 #define DWARF2_LINE_DEFAULT_IS_STMT 1
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)
84 private: // MCContext manages these
85 friend class MCContext;
86 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) {}
93 // Allow the default copy constructor and assignment operator to be used
94 // for an MCDwarfLoc object.
96 public:
97 /// Get the FileNum of this MCDwarfLoc.
98 unsigned getFileNum() const { return FileNum; }
100 /// Get the Line of this MCDwarfLoc.
101 unsigned getLine() const { return Line; }
103 /// Get the Column of this MCDwarfLoc.
104 unsigned getColumn() const { return Column; }
106 /// Get the Flags of this MCDwarfLoc.
107 unsigned getFlags() const { return Flags; }
109 /// Get the Isa of this MCDwarfLoc.
110 unsigned getIsa() const { return Isa; }
112 /// Get the Discriminator of this MCDwarfLoc.
113 unsigned getDiscriminator() const { return Discriminator; }
115 /// Set the FileNum of this MCDwarfLoc.
116 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
118 /// Set the Line of this MCDwarfLoc.
119 void setLine(unsigned line) { Line = line; }
121 /// Set the Column of this MCDwarfLoc.
122 void setColumn(unsigned column) {
123 assert(column <= UINT16_MAX);
124 Column = column;
127 /// Set the Flags of this MCDwarfLoc.
128 void setFlags(unsigned flags) {
129 assert(flags <= UINT8_MAX);
130 Flags = flags;
133 /// Set the Isa of this MCDwarfLoc.
134 void setIsa(unsigned isa) {
135 assert(isa <= UINT8_MAX);
136 Isa = isa;
139 /// Set the Discriminator of this MCDwarfLoc.
140 void setDiscriminator(unsigned discriminator) {
141 Discriminator = discriminator;
145 /// Instances of this class represent the line information for
146 /// 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.
150 class MCDwarfLineEntry : public MCDwarfLoc {
151 MCSymbol *Label;
153 private:
154 // Allow the default copy constructor and assignment operator to be used
155 // for an MCDwarfLineEntry object.
157 public:
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) {}
162 MCSymbol *getLabel() const { return Label; }
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);
170 /// Instances of this class represent the line information for a compile
171 /// 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.
174 class MCLineSection {
175 public:
176 // Add an entry to this MCLineSection's line entries.
177 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
178 MCLineDivisions[Sec].push_back(LineEntry);
181 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
182 using iterator = MCDwarfLineEntryCollection::iterator;
183 using const_iterator = MCDwarfLineEntryCollection::const_iterator;
184 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
186 private:
187 // A collection of MCDwarfLineEntry for each section.
188 MCLineDivisionMap MCLineDivisions;
190 public:
191 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
192 const MCLineDivisionMap &getMCLineEntries() const {
193 return MCLineDivisions;
197 struct 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;
210 struct MCDwarfLineTableHeader {
211 MCSymbol *Label = nullptr;
212 SmallVector<std::string, 3> MCDwarfDirs;
213 SmallVector<MCDwarfFile, 3> MCDwarfFiles;
214 StringMap<unsigned> SourceIdMap;
215 std::string CompilationDir;
216 MCDwarfFile RootFile;
217 bool HasSource = false;
218 private:
219 bool HasAllMD5 = true;
220 bool HasAnyMD5 = false;
222 public:
223 MCDwarfLineTableHeader() = default;
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;
236 void resetMD5Usage() {
237 HasAllMD5 = true;
238 HasAnyMD5 = false;
240 void trackMD5Usage(bool MD5Used) {
241 HasAllMD5 &= MD5Used;
242 HasAnyMD5 |= MD5Used;
244 bool isMD5UsageConsistent() const {
245 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
248 private:
249 void emitV2FileDirTables(MCStreamer *MCOS) const;
250 void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr,
251 StringRef CtxCompilationDir) const;
254 class MCDwarfDwoLineTable {
255 MCDwarfLineTableHeader Header;
257 public:
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;
267 Header.trackMD5Usage(Checksum);
268 Header.HasSource = Source.hasValue();
271 unsigned getFile(StringRef Directory, StringRef FileName,
272 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
273 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
276 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
277 MCSection *Section) const;
280 class MCDwarfLineTable {
281 MCDwarfLineTableHeader Header;
282 MCLineSection MCLineSections;
284 public:
285 // This emits the Dwarf file and the line tables for all Compile Units.
286 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
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;
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));
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;
310 Header.trackMD5Usage(Checksum);
311 Header.HasSource = Source.hasValue();
314 void resetRootFile() {
315 assert(Header.MCDwarfFiles.empty());
316 Header.RootFile.Name.clear();
317 Header.resetMD5Usage();
318 Header.HasSource = false;
321 bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
323 // Report whether MD5 usage has been consistent (all-or-none).
324 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
326 MCSymbol *getLabel() const {
327 return Header.Label;
330 void setLabel(MCSymbol *Label) {
331 Header.Label = Label;
334 const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
335 return Header.MCDwarfDirs;
338 SmallVectorImpl<std::string> &getMCDwarfDirs() {
339 return Header.MCDwarfDirs;
342 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
343 return Header.MCDwarfFiles;
346 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
347 return Header.MCDwarfFiles;
350 const MCLineSection &getMCLineSections() const {
351 return MCLineSections;
353 MCLineSection &getMCLineSections() {
354 return MCLineSections;
358 class MCDwarfLineAddr {
359 public:
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);
364 /// 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);
371 /// Utility function to emit the encoding to a streamer.
372 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
373 int64_t LineDelta, uint64_t AddrDelta);
376 class MCGenDwarfInfo {
377 public:
379 // When generating dwarf for assembly source files this emits the Dwarf
380 // sections.
382 static void Emit(MCStreamer *MCOS);
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.
387 class MCGenDwarfLabelEntry {
388 private:
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;
398 public:
399 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
400 MCSymbol *label)
401 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
402 Label(label) {}
404 StringRef getName() const { return Name; }
405 unsigned getFileNumber() const { return FileNumber; }
406 unsigned getLineNumber() const { return LineNumber; }
407 MCSymbol *getLabel() const { return Label; }
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);
415 class MCCFIInstruction {
416 public:
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,
432 OpNegateRAState,
433 OpGnuArgsSize
436 private:
437 OpType Operation;
438 MCSymbol *Label;
439 unsigned Register;
440 union {
441 int Offset;
442 unsigned Register2;
444 std::vector<char> Values;
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);
452 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
453 : Operation(Op), Label(L), Register(R1), Register2(R2) {
454 assert(Op == OpRegister);
457 public:
458 /// .cfi_def_cfa defines a rule for computing CFA as: take address from
459 /// Register and add Offset to it.
460 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
461 int Offset) {
462 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
465 /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
466 /// 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, "");
471 /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
472 /// 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, "");
478 /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
479 /// 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, "");
485 /// .cfi_offset Previous value of Register is saved at offset Offset
486 /// from CFA.
487 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
488 int Offset) {
489 return MCCFIInstruction(OpOffset, L, Register, Offset, "");
492 /// .cfi_rel_offset Previous value of Register is saved at offset
493 /// 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, "");
500 /// .cfi_register Previous value of Register1 is saved in
501 /// register Register2.
502 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
503 unsigned Register2) {
504 return MCCFIInstruction(OpRegister, L, Register1, Register2);
507 /// .cfi_window_save SPARC register window is saved.
508 static MCCFIInstruction createWindowSave(MCSymbol *L) {
509 return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
512 /// .cfi_negate_ra_state AArch64 negate RA state.
513 static MCCFIInstruction createNegateRAState(MCSymbol *L) {
514 return MCCFIInstruction(OpNegateRAState, L, 0, 0, "");
517 /// .cfi_restore says that the rule for Register is now the same as it
518 /// 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, "");
524 /// .cfi_undefined From now on the previous value of Register can't be
525 /// restored anymore.
526 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
527 return MCCFIInstruction(OpUndefined, L, Register, 0, "");
530 /// .cfi_same_value Current value of Register is the same as in the
531 /// previous frame. I.e., no restoration is needed.
532 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
533 return MCCFIInstruction(OpSameValue, L, Register, 0, "");
536 /// .cfi_remember_state Save all current rules for all registers.
537 static MCCFIInstruction createRememberState(MCSymbol *L) {
538 return MCCFIInstruction(OpRememberState, L, 0, 0, "");
541 /// .cfi_restore_state Restore the previously saved state.
542 static MCCFIInstruction createRestoreState(MCSymbol *L) {
543 return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
546 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
547 /// info.
548 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
549 return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
552 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
553 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
554 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
557 OpType getOperation() const { return Operation; }
558 MCSymbol *getLabel() const { return Label; }
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;
568 unsigned getRegister2() const {
569 assert(Operation == OpRegister);
570 return Register2;
573 int getOffset() const {
574 assert(Operation == OpDefCfa || Operation == OpOffset ||
575 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
576 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
577 return Offset;
580 StringRef getValues() const {
581 assert(Operation == OpEscape);
582 return StringRef(&Values[0], Values.size());
586 struct MCDwarfFrameInfo {
587 MCDwarfFrameInfo() = default;
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);
601 bool IsBKeyFrame = false;
604 class MCDwarfFrameEmitter {
605 public:
607 // This emits the frame info section.
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);
615 } // end namespace llvm
617 #endif // LLVM_MC_MCDWARF_H