1 //===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
33 template <typename T
> class ArrayRef
;
37 class MCObjectStreamer
;
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
53 // The base name of the file without its directory path.
56 // The index into the list of directory names for this file name.
59 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
61 Optional
<MD5::MD5Result
> Checksum
;
63 /// The source code of the file. Non-owning reference to data allocated in
65 Optional
<StringRef
> Source
;
68 /// Instances of this class represent the information from a
69 /// dwarf .loc directive.
74 // Flags (see #define's below)
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.
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
);
130 /// Set the Flags of this MCDwarfLoc.
131 void setFlags(unsigned flags
) {
132 assert(flags
<= UINT8_MAX
);
136 /// Set the Isa of this MCDwarfLoc.
137 void setIsa(unsigned isa
) {
138 assert(isa
<= UINT8_MAX
);
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
{
157 // Allow the default copy constructor and assignment operator to be used
158 // for an MCDwarfLineEntry object.
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
{
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
>;
190 // A collection of MCDwarfLineEntry for each section.
191 MCLineDivisionMap MCLineDivisions
;
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
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;
222 bool HasAllMD5
= true;
223 bool HasAnyMD5
= false;
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() {
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() {
266 MCDwarfFiles
.clear();
267 RootFile
.Name
.clear();
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;
282 void maybeSetRootFile(StringRef Directory
, StringRef FileName
,
283 Optional
<MD5::MD5Result
> Checksum
,
284 Optional
<StringRef
> Source
) {
285 if (!Header
.RootFile
.Name
.empty())
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
,
298 void Emit(MCStreamer
&MCOS
, MCDwarfLineTableParams Params
,
299 MCSection
*Section
) const;
302 class MCDwarfLineTable
{
303 MCDwarfLineTableHeader Header
;
304 MCLineSection MCLineSections
;
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 {
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
{
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
{
399 // When generating dwarf for assembly source files this emits the Dwarf
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
{
409 // Name of the symbol without a leading underbar, if any.
411 // The dwarf file number this symbol is in.
413 // The line number this symbol is at.
415 // The low_pc for the dwarf label is taken from this symbol.
419 MCGenDwarfLabelEntry(StringRef name
, unsigned fileNumber
, unsigned lineNumber
,
421 : Name(name
), FileNumber(fileNumber
), LineNumber(lineNumber
),
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
,
435 class MCCFIInstruction
{
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
);
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
,
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
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
507 static MCCFIInstruction
createOffset(MCSymbol
*L
, unsigned Register
,
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
,
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
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
);
588 unsigned getRegister2() const {
589 assert(Operation
== OpRegister
);
593 int getOffset() const {
594 assert(Operation
== OpDefCfa
|| Operation
== OpOffset
||
595 Operation
== OpRelOffset
|| Operation
== OpDefCfaOffset
||
596 Operation
== OpAdjustCfaOffset
|| Operation
== OpGnuArgsSize
);
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
{
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