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