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
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).
50 // The base name of the file without its directory path.
53 // The index into the list of directory names for this file name.
56 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
58 MD5::MD5Result
*Checksum
= nullptr;
60 /// The source code of the file. Non-owning reference to data allocated in
62 Optional
<StringRef
> Source
;
65 /// Instances of this class represent the information from a
66 /// dwarf .loc directive.
71 // Flags (see #define's below)
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.
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
);
127 /// Set the Flags of this MCDwarfLoc.
128 void setFlags(unsigned flags
) {
129 assert(flags
<= UINT8_MAX
);
133 /// Set the Isa of this MCDwarfLoc.
134 void setIsa(unsigned isa
) {
135 assert(isa
<= UINT8_MAX
);
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
{
154 // Allow the default copy constructor and assignment operator to be used
155 // for an MCDwarfLineEntry object.
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
{
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
>;
187 // A collection of MCDwarfLineEntry for each section.
188 MCLineDivisionMap MCLineDivisions
;
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
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;
219 bool HasAllMD5
= true;
220 bool HasAnyMD5
= false;
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() {
240 void trackMD5Usage(bool MD5Used
) {
241 HasAllMD5
&= MD5Used
;
242 HasAnyMD5
|= MD5Used
;
244 bool isMD5UsageConsistent() const {
245 return MCDwarfFiles
.empty() || (HasAllMD5
== HasAnyMD5
);
249 void emitV2FileDirTables(MCStreamer
*MCOS
) const;
250 void emitV5FileDirTables(MCStreamer
*MCOS
, Optional
<MCDwarfLineStr
> &LineStr
,
251 StringRef CtxCompilationDir
) const;
254 class MCDwarfDwoLineTable
{
255 MCDwarfLineTableHeader Header
;
258 void maybeSetRootFile(StringRef Directory
, StringRef FileName
,
259 MD5::MD5Result
*Checksum
, Optional
<StringRef
> Source
) {
260 if (!Header
.RootFile
.Name
.empty())
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
;
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
,
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 {
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
{
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
{
379 // When generating dwarf for assembly source files this emits the Dwarf
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
{
389 // Name of the symbol without a leading underbar, if any.
391 // The dwarf file number this symbol is in.
393 // The line number this symbol is at.
395 // The low_pc for the dwarf label is taken from this symbol.
399 MCGenDwarfLabelEntry(StringRef name
, unsigned fileNumber
, unsigned lineNumber
,
401 : Name(name
), FileNumber(fileNumber
), LineNumber(lineNumber
),
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
,
415 class MCCFIInstruction
{
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
);
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
,
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
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
487 static MCCFIInstruction
createOffset(MCSymbol
*L
, unsigned Register
,
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
,
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
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
);
568 unsigned getRegister2() const {
569 assert(Operation
== OpRegister
);
573 int getOffset() const {
574 assert(Operation
== OpDefCfa
|| Operation
== OpOffset
||
575 Operation
== OpRelOffset
|| Operation
== OpDefCfaOffset
||
576 Operation
== OpAdjustCfaOffset
|| Operation
== OpGnuArgsSize
);
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
{
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
,
615 } // end namespace llvm
617 #endif // LLVM_MC_MCDWARF_H