[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / include / llvm / MC / MCDwarf.h
bloba33b4b31bb06d2640b4a198a11bc7fc76273e313
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 .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;
56 // The index into the list of directory names for this file name.
57 unsigned DirIndex;
59 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
60 /// in MCContext.
61 Optional<MD5::MD5Result> Checksum;
63 /// The source code of the file. Non-owning reference to data allocated in
64 /// MCContext.
65 Optional<StringRef> Source;
68 /// Instances of this class represent the information from a
69 /// dwarf .loc directive.
70 class MCDwarfLoc {
71 uint32_t FileNum;
72 uint32_t Line;
73 uint16_t Column;
74 // Flags (see #define's below)
75 uint8_t Flags;
76 uint8_t Isa;
77 uint32_t Discriminator;
79 // Flag that indicates the initial value of the is_stmt_start flag.
80 #define DWARF2_LINE_DEFAULT_IS_STMT 1
82 #define DWARF2_FLAG_IS_STMT (1 << 0)
83 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
84 #define DWARF2_FLAG_PROLOGUE_END (1 << 2)
85 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
87 private: // MCContext manages these
88 friend class MCContext;
89 friend class MCDwarfLineEntry;
91 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
92 unsigned isa, unsigned discriminator)
93 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
94 Discriminator(discriminator) {}
96 // Allow the default copy constructor and assignment operator to be used
97 // for an MCDwarfLoc object.
99 public:
100 /// Get the FileNum of this MCDwarfLoc.
101 unsigned getFileNum() const { return FileNum; }
103 /// Get the Line of this MCDwarfLoc.
104 unsigned getLine() const { return Line; }
106 /// Get the Column of this MCDwarfLoc.
107 unsigned getColumn() const { return Column; }
109 /// Get the Flags of this MCDwarfLoc.
110 unsigned getFlags() const { return Flags; }
112 /// Get the Isa of this MCDwarfLoc.
113 unsigned getIsa() const { return Isa; }
115 /// Get the Discriminator of this MCDwarfLoc.
116 unsigned getDiscriminator() const { return Discriminator; }
118 /// Set the FileNum of this MCDwarfLoc.
119 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
121 /// Set the Line of this MCDwarfLoc.
122 void setLine(unsigned line) { Line = line; }
124 /// Set the Column of this MCDwarfLoc.
125 void setColumn(unsigned column) {
126 assert(column <= UINT16_MAX);
127 Column = column;
130 /// Set the Flags of this MCDwarfLoc.
131 void setFlags(unsigned flags) {
132 assert(flags <= UINT8_MAX);
133 Flags = flags;
136 /// Set the Isa of this MCDwarfLoc.
137 void setIsa(unsigned isa) {
138 assert(isa <= UINT8_MAX);
139 Isa = isa;
142 /// Set the Discriminator of this MCDwarfLoc.
143 void setDiscriminator(unsigned discriminator) {
144 Discriminator = discriminator;
148 /// Instances of this class represent the line information for
149 /// the dwarf line table entries. Which is created after a machine
150 /// instruction is assembled and uses an address from a temporary label
151 /// created at the current address in the current section and the info from
152 /// the last .loc directive seen as stored in the context.
153 class MCDwarfLineEntry : public MCDwarfLoc {
154 MCSymbol *Label;
156 private:
157 // Allow the default copy constructor and assignment operator to be used
158 // for an MCDwarfLineEntry object.
160 public:
161 // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
162 MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
163 : MCDwarfLoc(loc), Label(label) {}
165 MCSymbol *getLabel() const { return Label; }
167 // This is called when an instruction is assembled into the specified
168 // section and if there is information from the last .loc directive that
169 // has yet to have a line entry made for it is made.
170 static void Make(MCObjectStreamer *MCOS, MCSection *Section);
173 /// Instances of this class represent the line information for a compile
174 /// unit where machine instructions have been assembled after seeing .loc
175 /// directives. This is the information used to build the dwarf line
176 /// table for a section.
177 class MCLineSection {
178 public:
179 // Add an entry to this MCLineSection's line entries.
180 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
181 MCLineDivisions[Sec].push_back(LineEntry);
184 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
185 using iterator = MCDwarfLineEntryCollection::iterator;
186 using const_iterator = MCDwarfLineEntryCollection::const_iterator;
187 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
189 private:
190 // A collection of MCDwarfLineEntry for each section.
191 MCLineDivisionMap MCLineDivisions;
193 public:
194 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
195 const MCLineDivisionMap &getMCLineEntries() const {
196 return MCLineDivisions;
200 struct MCDwarfLineTableParams {
201 /// First special line opcode - leave room for the standard opcodes.
202 /// Note: If you want to change this, you'll have to update the
203 /// "StandardOpcodeLengths" table that is emitted in
204 /// \c Emit().
205 uint8_t DWARF2LineOpcodeBase = 13;
206 /// Minimum line offset in a special line info. opcode. The value
207 /// -5 was chosen to give a reasonable range of values.
208 int8_t DWARF2LineBase = -5;
209 /// Range of line offsets in a special line info. opcode.
210 uint8_t DWARF2LineRange = 14;
213 struct MCDwarfLineTableHeader {
214 MCSymbol *Label = nullptr;
215 SmallVector<std::string, 3> MCDwarfDirs;
216 SmallVector<MCDwarfFile, 3> MCDwarfFiles;
217 StringMap<unsigned> SourceIdMap;
218 std::string CompilationDir;
219 MCDwarfFile RootFile;
220 bool HasSource = false;
221 private:
222 bool HasAllMD5 = true;
223 bool HasAnyMD5 = false;
225 public:
226 MCDwarfLineTableHeader() = default;
228 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
229 Optional<MD5::MD5Result> Checksum,
230 Optional<StringRef> Source,
231 uint16_t DwarfVersion,
232 unsigned FileNumber = 0);
233 std::pair<MCSymbol *, MCSymbol *>
234 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
235 Optional<MCDwarfLineStr> &LineStr) const;
236 std::pair<MCSymbol *, MCSymbol *>
237 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
238 ArrayRef<char> SpecialOpcodeLengths,
239 Optional<MCDwarfLineStr> &LineStr) const;
240 void resetMD5Usage() {
241 HasAllMD5 = true;
242 HasAnyMD5 = false;
244 void trackMD5Usage(bool MD5Used) {
245 HasAllMD5 &= MD5Used;
246 HasAnyMD5 |= MD5Used;
248 bool isMD5UsageConsistent() const {
249 return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
252 void setRootFile(StringRef Directory, StringRef FileName,
253 Optional<MD5::MD5Result> Checksum,
254 Optional<StringRef> Source) {
255 CompilationDir = Directory;
256 RootFile.Name = FileName;
257 RootFile.DirIndex = 0;
258 RootFile.Checksum = Checksum;
259 RootFile.Source = Source;
260 trackMD5Usage(Checksum.hasValue());
261 HasSource = Source.hasValue();
264 void resetFileTable() {
265 MCDwarfDirs.clear();
266 MCDwarfFiles.clear();
267 RootFile.Name.clear();
268 resetMD5Usage();
269 HasSource = false;
272 private:
273 void emitV2FileDirTables(MCStreamer *MCOS) const;
274 void emitV5FileDirTables(MCStreamer *MCOS, Optional<MCDwarfLineStr> &LineStr) const;
277 class MCDwarfDwoLineTable {
278 MCDwarfLineTableHeader Header;
279 bool HasSplitLineTable = false;
281 public:
282 void maybeSetRootFile(StringRef Directory, StringRef FileName,
283 Optional<MD5::MD5Result> Checksum,
284 Optional<StringRef> Source) {
285 if (!Header.RootFile.Name.empty())
286 return;
287 Header.setRootFile(Directory, FileName, Checksum, Source);
290 unsigned getFile(StringRef Directory, StringRef FileName,
291 Optional<MD5::MD5Result> Checksum, uint16_t DwarfVersion,
292 Optional<StringRef> Source) {
293 HasSplitLineTable = true;
294 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source,
295 DwarfVersion));
298 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
299 MCSection *Section) const;
302 class MCDwarfLineTable {
303 MCDwarfLineTableHeader Header;
304 MCLineSection MCLineSections;
306 public:
307 // This emits the Dwarf file and the line tables for all Compile Units.
308 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
310 // This emits the Dwarf file and the line tables for a given Compile Unit.
311 void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
312 Optional<MCDwarfLineStr> &LineStr) const;
314 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
315 Optional<MD5::MD5Result> Checksum,
316 Optional<StringRef> Source,
317 uint16_t DwarfVersion,
318 unsigned FileNumber = 0);
319 unsigned getFile(StringRef &Directory, StringRef &FileName,
320 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
321 uint16_t DwarfVersion, unsigned FileNumber = 0) {
322 return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
323 DwarfVersion, FileNumber));
326 void setRootFile(StringRef Directory, StringRef FileName,
327 Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source) {
328 Header.CompilationDir = Directory;
329 Header.RootFile.Name = FileName;
330 Header.RootFile.DirIndex = 0;
331 Header.RootFile.Checksum = Checksum;
332 Header.RootFile.Source = Source;
333 Header.trackMD5Usage(Checksum.hasValue());
334 Header.HasSource = Source.hasValue();
337 void resetFileTable() { Header.resetFileTable(); }
339 bool hasRootFile() const { return !Header.RootFile.Name.empty(); }
341 const MCDwarfFile &getRootFile() const { return Header.RootFile; }
343 // Report whether MD5 usage has been consistent (all-or-none).
344 bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
346 MCSymbol *getLabel() const {
347 return Header.Label;
350 void setLabel(MCSymbol *Label) {
351 Header.Label = Label;
354 const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
355 return Header.MCDwarfDirs;
358 SmallVectorImpl<std::string> &getMCDwarfDirs() {
359 return Header.MCDwarfDirs;
362 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
363 return Header.MCDwarfFiles;
366 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
367 return Header.MCDwarfFiles;
370 const MCLineSection &getMCLineSections() const {
371 return MCLineSections;
373 MCLineSection &getMCLineSections() {
374 return MCLineSections;
378 class MCDwarfLineAddr {
379 public:
380 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
381 static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
382 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
384 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas using
385 /// fixed length operands.
386 static bool FixedEncode(MCContext &Context,
387 MCDwarfLineTableParams Params,
388 int64_t LineDelta, uint64_t AddrDelta,
389 raw_ostream &OS, uint32_t *Offset, uint32_t *Size);
391 /// Utility function to emit the encoding to a streamer.
392 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
393 int64_t LineDelta, uint64_t AddrDelta);
396 class MCGenDwarfInfo {
397 public:
399 // When generating dwarf for assembly source files this emits the Dwarf
400 // sections.
402 static void Emit(MCStreamer *MCOS);
405 // When generating dwarf for assembly source files this is the info that is
406 // needed to be gathered for each symbol that will have a dwarf label.
407 class MCGenDwarfLabelEntry {
408 private:
409 // Name of the symbol without a leading underbar, if any.
410 StringRef Name;
411 // The dwarf file number this symbol is in.
412 unsigned FileNumber;
413 // The line number this symbol is at.
414 unsigned LineNumber;
415 // The low_pc for the dwarf label is taken from this symbol.
416 MCSymbol *Label;
418 public:
419 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
420 MCSymbol *label)
421 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
422 Label(label) {}
424 StringRef getName() const { return Name; }
425 unsigned getFileNumber() const { return FileNumber; }
426 unsigned getLineNumber() const { return LineNumber; }
427 MCSymbol *getLabel() const { return Label; }
429 // This is called when label is created when we are generating dwarf for
430 // assembly source files.
431 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
432 SMLoc &Loc);
435 class MCCFIInstruction {
436 public:
437 enum OpType {
438 OpSameValue,
439 OpRememberState,
440 OpRestoreState,
441 OpOffset,
442 OpDefCfaRegister,
443 OpDefCfaOffset,
444 OpDefCfa,
445 OpRelOffset,
446 OpAdjustCfaOffset,
447 OpEscape,
448 OpRestore,
449 OpUndefined,
450 OpRegister,
451 OpWindowSave,
452 OpNegateRAState,
453 OpGnuArgsSize
456 private:
457 OpType Operation;
458 MCSymbol *Label;
459 unsigned Register;
460 union {
461 int Offset;
462 unsigned Register2;
464 std::vector<char> Values;
466 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
467 : Operation(Op), Label(L), Register(R), Offset(O),
468 Values(V.begin(), V.end()) {
469 assert(Op != OpRegister);
472 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
473 : Operation(Op), Label(L), Register(R1), Register2(R2) {
474 assert(Op == OpRegister);
477 public:
478 /// .cfi_def_cfa defines a rule for computing CFA as: take address from
479 /// Register and add Offset to it.
480 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
481 int Offset) {
482 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
485 /// .cfi_def_cfa_register modifies a rule for computing CFA. From now
486 /// on Register will be used instead of the old one. Offset remains the same.
487 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
488 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
491 /// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
492 /// remains the same, but offset is new. Note that it is the absolute offset
493 /// that will be added to a defined register to the compute CFA address.
494 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
495 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
498 /// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
499 /// Offset is a relative value that is added/subtracted from the previous
500 /// offset.
501 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
502 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
505 /// .cfi_offset Previous value of Register is saved at offset Offset
506 /// from CFA.
507 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
508 int Offset) {
509 return MCCFIInstruction(OpOffset, L, Register, Offset, "");
512 /// .cfi_rel_offset Previous value of Register is saved at offset
513 /// Offset from the current CFA register. This is transformed to .cfi_offset
514 /// using the known displacement of the CFA register from the CFA.
515 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
516 int Offset) {
517 return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
520 /// .cfi_register Previous value of Register1 is saved in
521 /// register Register2.
522 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
523 unsigned Register2) {
524 return MCCFIInstruction(OpRegister, L, Register1, Register2);
527 /// .cfi_window_save SPARC register window is saved.
528 static MCCFIInstruction createWindowSave(MCSymbol *L) {
529 return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
532 /// .cfi_negate_ra_state AArch64 negate RA state.
533 static MCCFIInstruction createNegateRAState(MCSymbol *L) {
534 return MCCFIInstruction(OpNegateRAState, L, 0, 0, "");
537 /// .cfi_restore says that the rule for Register is now the same as it
538 /// was at the beginning of the function, after all initial instructions added
539 /// by .cfi_startproc were executed.
540 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
541 return MCCFIInstruction(OpRestore, L, Register, 0, "");
544 /// .cfi_undefined From now on the previous value of Register can't be
545 /// restored anymore.
546 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
547 return MCCFIInstruction(OpUndefined, L, Register, 0, "");
550 /// .cfi_same_value Current value of Register is the same as in the
551 /// previous frame. I.e., no restoration is needed.
552 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
553 return MCCFIInstruction(OpSameValue, L, Register, 0, "");
556 /// .cfi_remember_state Save all current rules for all registers.
557 static MCCFIInstruction createRememberState(MCSymbol *L) {
558 return MCCFIInstruction(OpRememberState, L, 0, 0, "");
561 /// .cfi_restore_state Restore the previously saved state.
562 static MCCFIInstruction createRestoreState(MCSymbol *L) {
563 return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
566 /// .cfi_escape Allows the user to add arbitrary bytes to the unwind
567 /// info.
568 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
569 return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
572 /// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
573 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
574 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
577 OpType getOperation() const { return Operation; }
578 MCSymbol *getLabel() const { return Label; }
580 unsigned getRegister() const {
581 assert(Operation == OpDefCfa || Operation == OpOffset ||
582 Operation == OpRestore || Operation == OpUndefined ||
583 Operation == OpSameValue || Operation == OpDefCfaRegister ||
584 Operation == OpRelOffset || Operation == OpRegister);
585 return Register;
588 unsigned getRegister2() const {
589 assert(Operation == OpRegister);
590 return Register2;
593 int getOffset() const {
594 assert(Operation == OpDefCfa || Operation == OpOffset ||
595 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
596 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
597 return Offset;
600 StringRef getValues() const {
601 assert(Operation == OpEscape);
602 return StringRef(&Values[0], Values.size());
606 struct MCDwarfFrameInfo {
607 MCDwarfFrameInfo() = default;
609 MCSymbol *Begin = nullptr;
610 MCSymbol *End = nullptr;
611 const MCSymbol *Personality = nullptr;
612 const MCSymbol *Lsda = nullptr;
613 std::vector<MCCFIInstruction> Instructions;
614 unsigned CurrentCfaRegister = 0;
615 unsigned PersonalityEncoding = 0;
616 unsigned LsdaEncoding = 0;
617 uint32_t CompactUnwindEncoding = 0;
618 bool IsSignalFrame = false;
619 bool IsSimple = false;
620 unsigned RAReg = static_cast<unsigned>(INT_MAX);
621 bool IsBKeyFrame = false;
624 class MCDwarfFrameEmitter {
625 public:
627 // This emits the frame info section.
629 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
630 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
631 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
632 raw_ostream &OS, uint32_t *Offset = nullptr,
633 uint32_t *Size = nullptr);
636 } // end namespace llvm
638 #endif // LLVM_MC_MCDWARF_H