blob: 5cdb176e8e2477522eacc6d23ca289bd2b5a8ee0 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the declaration of the MCDwarfFile to support the dwarf
11// .file directive and the .loc directive.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_MC_MCDWARF_H
16#define LLVM_MC_MCDWARF_H
17
18#include "llvm/ADT/MapVector.h"
19#include "llvm/ADT/Optional.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
23#include "llvm/MC/MCSection.h"
24#include "llvm/Support/Error.h"
25#include "llvm/Support/MD5.h"
26#include <cassert>
27#include <cstdint>
28#include <string>
29#include <utility>
30#include <vector>
31
32namespace llvm {
33
34template <typename T> class ArrayRef;
35class MCAsmBackend;
36class MCContext;
37class MCDwarfLineStr;
38class MCObjectStreamer;
39class MCStreamer;
40class MCSymbol;
41class raw_ostream;
42class SMLoc;
43class SourceMgr;
44
45/// \brief Instances of this class represent the name of the dwarf
46/// .file directive and its associated dwarf file number in the MC file,
47/// and MCDwarfFile's are created and uniqued by the MCContext class where
48/// the file number for each is its index into the vector of DwarfFiles (note
49/// index 0 is not used and not a valid dwarf file number).
50struct MCDwarfFile {
51 // \brief The base name of the file without its directory path.
52 std::string Name;
53
54 // \brief The index into the list of directory names for this file name.
55 unsigned DirIndex;
56
57 /// The MD5 checksum, if there is one. Non-owning pointer to data allocated
58 /// in MCContext.
59 MD5::MD5Result *Checksum = nullptr;
60
61 /// The source code of the file. Non-owning reference to data allocated in
62 /// MCContext.
63 Optional<StringRef> Source;
64};
65
66/// \brief Instances of this class represent the information from a
67/// dwarf .loc directive.
68class MCDwarfLoc {
69 uint32_t FileNum;
70 uint32_t Line;
71 uint16_t Column;
72 // Flags (see #define's below)
73 uint8_t Flags;
74 uint8_t Isa;
75 uint32_t Discriminator;
76
77// Flag that indicates the initial value of the is_stmt_start flag.
78#define DWARF2_LINE_DEFAULT_IS_STMT 1
79
80#define DWARF2_FLAG_IS_STMT (1 << 0)
81#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
82#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
83#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
84
85private: // MCContext manages these
86 friend class MCContext;
87 friend class MCDwarfLineEntry;
88
89 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
90 unsigned isa, unsigned discriminator)
91 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa),
92 Discriminator(discriminator) {}
93
94 // Allow the default copy constructor and assignment operator to be used
95 // for an MCDwarfLoc object.
96
97public:
98 /// \brief Get the FileNum of this MCDwarfLoc.
99 unsigned getFileNum() const { return FileNum; }
100
101 /// \brief Get the Line of this MCDwarfLoc.
102 unsigned getLine() const { return Line; }
103
104 /// \brief Get the Column of this MCDwarfLoc.
105 unsigned getColumn() const { return Column; }
106
107 /// \brief Get the Flags of this MCDwarfLoc.
108 unsigned getFlags() const { return Flags; }
109
110 /// \brief Get the Isa of this MCDwarfLoc.
111 unsigned getIsa() const { return Isa; }
112
113 /// \brief Get the Discriminator of this MCDwarfLoc.
114 unsigned getDiscriminator() const { return Discriminator; }
115
116 /// \brief Set the FileNum of this MCDwarfLoc.
117 void setFileNum(unsigned fileNum) { FileNum = fileNum; }
118
119 /// \brief Set the Line of this MCDwarfLoc.
120 void setLine(unsigned line) { Line = line; }
121
122 /// \brief Set the Column of this MCDwarfLoc.
123 void setColumn(unsigned column) {
124 assert(column <= UINT16_MAX);
125 Column = column;
126 }
127
128 /// \brief Set the Flags of this MCDwarfLoc.
129 void setFlags(unsigned flags) {
130 assert(flags <= UINT8_MAX);
131 Flags = flags;
132 }
133
134 /// \brief Set the Isa of this MCDwarfLoc.
135 void setIsa(unsigned isa) {
136 assert(isa <= UINT8_MAX);
137 Isa = isa;
138 }
139
140 /// \brief Set the Discriminator of this MCDwarfLoc.
141 void setDiscriminator(unsigned discriminator) {
142 Discriminator = discriminator;
143 }
144};
145
146/// \brief Instances of this class represent the line information for
147/// the dwarf line table entries. Which is created after a machine
148/// instruction is assembled and uses an address from a temporary label
149/// created at the current address in the current section and the info from
150/// the last .loc directive seen as stored in the context.
151class MCDwarfLineEntry : public MCDwarfLoc {
152 MCSymbol *Label;
153
154private:
155 // Allow the default copy constructor and assignment operator to be used
156 // for an MCDwarfLineEntry object.
157
158public:
159 // Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
160 MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
161 : MCDwarfLoc(loc), Label(label) {}
162
163 MCSymbol *getLabel() const { return Label; }
164
165 // This is called when an instruction is assembled into the specified
166 // section and if there is information from the last .loc directive that
167 // has yet to have a line entry made for it is made.
168 static void Make(MCObjectStreamer *MCOS, MCSection *Section);
169};
170
171/// \brief Instances of this class represent the line information for a compile
172/// unit where machine instructions have been assembled after seeing .loc
173/// directives. This is the information used to build the dwarf line
174/// table for a section.
175class MCLineSection {
176public:
177 // \brief Add an entry to this MCLineSection's line entries.
178 void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec) {
179 MCLineDivisions[Sec].push_back(LineEntry);
180 }
181
182 using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
183 using iterator = MCDwarfLineEntryCollection::iterator;
184 using const_iterator = MCDwarfLineEntryCollection::const_iterator;
185 using MCLineDivisionMap = MapVector<MCSection *, MCDwarfLineEntryCollection>;
186
187private:
188 // A collection of MCDwarfLineEntry for each section.
189 MCLineDivisionMap MCLineDivisions;
190
191public:
192 // Returns the collection of MCDwarfLineEntry for a given Compile Unit ID.
193 const MCLineDivisionMap &getMCLineEntries() const {
194 return MCLineDivisions;
195 }
196};
197
198struct MCDwarfLineTableParams {
199 /// First special line opcode - leave room for the standard opcodes.
200 /// Note: If you want to change this, you'll have to update the
201 /// "StandardOpcodeLengths" table that is emitted in
202 /// \c Emit().
203 uint8_t DWARF2LineOpcodeBase = 13;
204 /// Minimum line offset in a special line info. opcode. The value
205 /// -5 was chosen to give a reasonable range of values.
206 int8_t DWARF2LineBase = -5;
207 /// Range of line offsets in a special line info. opcode.
208 uint8_t DWARF2LineRange = 14;
209};
210
211struct MCDwarfLineTableHeader {
212 MCSymbol *Label = nullptr;
213 SmallVector<std::string, 3> MCDwarfDirs;
214 SmallVector<MCDwarfFile, 3> MCDwarfFiles;
215 StringMap<unsigned> SourceIdMap;
216 StringRef CompilationDir;
217 MCDwarfFile RootFile;
218 bool HasMD5 = false;
219 bool HasSource = false;
220
221 MCDwarfLineTableHeader() = default;
222
223 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
224 MD5::MD5Result *Checksum,
225 Optional<StringRef> &Source,
226 unsigned FileNumber = 0);
227 std::pair<MCSymbol *, MCSymbol *>
228 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
229 Optional<MCDwarfLineStr> &LineStr) const;
230 std::pair<MCSymbol *, MCSymbol *>
231 Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
232 ArrayRef<char> SpecialOpcodeLengths,
233 Optional<MCDwarfLineStr> &LineStr) const;
234
235private:
236 void emitV2FileDirTables(MCStreamer *MCOS) const;
237 void emitV5FileDirTables(MCStreamer *MCOS,
238 Optional<MCDwarfLineStr> &LineStr) const;
239};
240
241class MCDwarfDwoLineTable {
242 MCDwarfLineTableHeader Header;
243
244public:
245 void maybeSetRootFile(StringRef Directory, StringRef FileName,
246 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
247 if (!Header.RootFile.Name.empty())
248 return;
249 Header.CompilationDir = Directory;
250 Header.RootFile.Name = FileName;
251 Header.RootFile.DirIndex = 0;
252 Header.RootFile.Checksum = Checksum;
253 Header.RootFile.Source = Source;
254 Header.HasMD5 = (Checksum != nullptr);
255 Header.HasSource = Source.hasValue();
256 }
257
258 unsigned getFile(StringRef Directory, StringRef FileName,
259 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
260 return cantFail(Header.tryGetFile(Directory, FileName, Checksum, Source));
261 }
262
263 void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params,
264 MCSection *Section) const;
265};
266
267class MCDwarfLineTable {
268 MCDwarfLineTableHeader Header;
269 MCLineSection MCLineSections;
270
271public:
272 // This emits the Dwarf file and the line tables for all Compile Units.
273 static void Emit(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params);
274
275 // This emits the Dwarf file and the line tables for a given Compile Unit.
276 void EmitCU(MCObjectStreamer *MCOS, MCDwarfLineTableParams Params,
277 Optional<MCDwarfLineStr> &LineStr) const;
278
279 Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
280 MD5::MD5Result *Checksum,
281 Optional<StringRef> Source,
282 unsigned FileNumber = 0);
283 unsigned getFile(StringRef &Directory, StringRef &FileName,
284 MD5::MD5Result *Checksum, Optional<StringRef> &Source,
285 unsigned FileNumber = 0) {
286 return cantFail(tryGetFile(Directory, FileName, Checksum, Source,
287 FileNumber));
288 }
289
290 void setRootFile(StringRef Directory, StringRef FileName,
291 MD5::MD5Result *Checksum, Optional<StringRef> Source) {
292 Header.CompilationDir = Directory;
293 Header.RootFile.Name = FileName;
294 Header.RootFile.DirIndex = 0;
295 Header.RootFile.Checksum = Checksum;
296 Header.RootFile.Source = Source;
297 Header.HasMD5 = (Checksum != nullptr);
298 Header.HasSource = Source.hasValue();
299 }
300
301 MCSymbol *getLabel() const {
302 return Header.Label;
303 }
304
305 void setLabel(MCSymbol *Label) {
306 Header.Label = Label;
307 }
308
309 const SmallVectorImpl<std::string> &getMCDwarfDirs() const {
310 return Header.MCDwarfDirs;
311 }
312
313 SmallVectorImpl<std::string> &getMCDwarfDirs() {
314 return Header.MCDwarfDirs;
315 }
316
317 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const {
318 return Header.MCDwarfFiles;
319 }
320
321 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() {
322 return Header.MCDwarfFiles;
323 }
324
325 const MCLineSection &getMCLineSections() const {
326 return MCLineSections;
327 }
328 MCLineSection &getMCLineSections() {
329 return MCLineSections;
330 }
331};
332
333class MCDwarfLineAddr {
334public:
335 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
336 static void Encode(MCContext &Context, MCDwarfLineTableParams Params,
337 int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS);
338
339 /// Utility function to emit the encoding to a streamer.
340 static void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
341 int64_t LineDelta, uint64_t AddrDelta);
342};
343
344class MCGenDwarfInfo {
345public:
346 //
347 // When generating dwarf for assembly source files this emits the Dwarf
348 // sections.
349 //
350 static void Emit(MCStreamer *MCOS);
351};
352
353// When generating dwarf for assembly source files this is the info that is
354// needed to be gathered for each symbol that will have a dwarf label.
355class MCGenDwarfLabelEntry {
356private:
357 // Name of the symbol without a leading underbar, if any.
358 StringRef Name;
359 // The dwarf file number this symbol is in.
360 unsigned FileNumber;
361 // The line number this symbol is at.
362 unsigned LineNumber;
363 // The low_pc for the dwarf label is taken from this symbol.
364 MCSymbol *Label;
365
366public:
367 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber,
368 MCSymbol *label)
369 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber),
370 Label(label) {}
371
372 StringRef getName() const { return Name; }
373 unsigned getFileNumber() const { return FileNumber; }
374 unsigned getLineNumber() const { return LineNumber; }
375 MCSymbol *getLabel() const { return Label; }
376
377 // This is called when label is created when we are generating dwarf for
378 // assembly source files.
379 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr,
380 SMLoc &Loc);
381};
382
383class MCCFIInstruction {
384public:
385 enum OpType {
386 OpSameValue,
387 OpRememberState,
388 OpRestoreState,
389 OpOffset,
390 OpDefCfaRegister,
391 OpDefCfaOffset,
392 OpDefCfa,
393 OpRelOffset,
394 OpAdjustCfaOffset,
395 OpEscape,
396 OpRestore,
397 OpUndefined,
398 OpRegister,
399 OpWindowSave,
400 OpGnuArgsSize
401 };
402
403private:
404 OpType Operation;
405 MCSymbol *Label;
406 unsigned Register;
407 union {
408 int Offset;
409 unsigned Register2;
410 };
411 std::vector<char> Values;
412
413 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V)
414 : Operation(Op), Label(L), Register(R), Offset(O),
415 Values(V.begin(), V.end()) {
416 assert(Op != OpRegister);
417 }
418
419 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2)
420 : Operation(Op), Label(L), Register(R1), Register2(R2) {
421 assert(Op == OpRegister);
422 }
423
424public:
425 /// \brief .cfi_def_cfa defines a rule for computing CFA as: take address from
426 /// Register and add Offset to it.
427 static MCCFIInstruction createDefCfa(MCSymbol *L, unsigned Register,
428 int Offset) {
429 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, "");
430 }
431
432 /// \brief .cfi_def_cfa_register modifies a rule for computing CFA. From now
433 /// on Register will be used instead of the old one. Offset remains the same.
434 static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register) {
435 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, "");
436 }
437
438 /// \brief .cfi_def_cfa_offset modifies a rule for computing CFA. Register
439 /// remains the same, but offset is new. Note that it is the absolute offset
440 /// that will be added to a defined register to the compute CFA address.
441 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) {
442 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, "");
443 }
444
445 /// \brief .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
446 /// Offset is a relative value that is added/subtracted from the previous
447 /// offset.
448 static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment) {
449 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, "");
450 }
451
452 /// \brief .cfi_offset Previous value of Register is saved at offset Offset
453 /// from CFA.
454 static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
455 int Offset) {
456 return MCCFIInstruction(OpOffset, L, Register, Offset, "");
457 }
458
459 /// \brief .cfi_rel_offset Previous value of Register is saved at offset
460 /// Offset from the current CFA register. This is transformed to .cfi_offset
461 /// using the known displacement of the CFA register from the CFA.
462 static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
463 int Offset) {
464 return MCCFIInstruction(OpRelOffset, L, Register, Offset, "");
465 }
466
467 /// \brief .cfi_register Previous value of Register1 is saved in
468 /// register Register2.
469 static MCCFIInstruction createRegister(MCSymbol *L, unsigned Register1,
470 unsigned Register2) {
471 return MCCFIInstruction(OpRegister, L, Register1, Register2);
472 }
473
474 /// \brief .cfi_window_save SPARC register window is saved.
475 static MCCFIInstruction createWindowSave(MCSymbol *L) {
476 return MCCFIInstruction(OpWindowSave, L, 0, 0, "");
477 }
478
479 /// \brief .cfi_restore says that the rule for Register is now the same as it
480 /// was at the beginning of the function, after all initial instructions added
481 /// by .cfi_startproc were executed.
482 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) {
483 return MCCFIInstruction(OpRestore, L, Register, 0, "");
484 }
485
486 /// \brief .cfi_undefined From now on the previous value of Register can't be
487 /// restored anymore.
488 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) {
489 return MCCFIInstruction(OpUndefined, L, Register, 0, "");
490 }
491
492 /// \brief .cfi_same_value Current value of Register is the same as in the
493 /// previous frame. I.e., no restoration is needed.
494 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) {
495 return MCCFIInstruction(OpSameValue, L, Register, 0, "");
496 }
497
498 /// \brief .cfi_remember_state Save all current rules for all registers.
499 static MCCFIInstruction createRememberState(MCSymbol *L) {
500 return MCCFIInstruction(OpRememberState, L, 0, 0, "");
501 }
502
503 /// \brief .cfi_restore_state Restore the previously saved state.
504 static MCCFIInstruction createRestoreState(MCSymbol *L) {
505 return MCCFIInstruction(OpRestoreState, L, 0, 0, "");
506 }
507
508 /// \brief .cfi_escape Allows the user to add arbitrary bytes to the unwind
509 /// info.
510 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) {
511 return MCCFIInstruction(OpEscape, L, 0, 0, Vals);
512 }
513
514 /// \brief A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
515 static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size) {
516 return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, "");
517 }
518
519 OpType getOperation() const { return Operation; }
520 MCSymbol *getLabel() const { return Label; }
521
522 unsigned getRegister() const {
523 assert(Operation == OpDefCfa || Operation == OpOffset ||
524 Operation == OpRestore || Operation == OpUndefined ||
525 Operation == OpSameValue || Operation == OpDefCfaRegister ||
526 Operation == OpRelOffset || Operation == OpRegister);
527 return Register;
528 }
529
530 unsigned getRegister2() const {
531 assert(Operation == OpRegister);
532 return Register2;
533 }
534
535 int getOffset() const {
536 assert(Operation == OpDefCfa || Operation == OpOffset ||
537 Operation == OpRelOffset || Operation == OpDefCfaOffset ||
538 Operation == OpAdjustCfaOffset || Operation == OpGnuArgsSize);
539 return Offset;
540 }
541
542 StringRef getValues() const {
543 assert(Operation == OpEscape);
544 return StringRef(&Values[0], Values.size());
545 }
546};
547
548struct MCDwarfFrameInfo {
549 MCDwarfFrameInfo() = default;
550
551 MCSymbol *Begin = nullptr;
552 MCSymbol *End = nullptr;
553 const MCSymbol *Personality = nullptr;
554 const MCSymbol *Lsda = nullptr;
555 std::vector<MCCFIInstruction> Instructions;
556 unsigned CurrentCfaRegister = 0;
557 unsigned PersonalityEncoding = 0;
558 unsigned LsdaEncoding = 0;
559 uint32_t CompactUnwindEncoding = 0;
560 bool IsSignalFrame = false;
561 bool IsSimple = false;
562 unsigned RAReg = static_cast<unsigned>(INT_MAX);
563};
564
565class MCDwarfFrameEmitter {
566public:
567 //
568 // This emits the frame info section.
569 //
570 static void Emit(MCObjectStreamer &streamer, MCAsmBackend *MAB, bool isEH);
571 static void EmitAdvanceLoc(MCObjectStreamer &Streamer, uint64_t AddrDelta);
572 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta,
573 raw_ostream &OS);
574};
575
576} // end namespace llvm
577
578#endif // LLVM_MC_MCDWARF_H