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 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/MapVector.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/Compiler.h" 23 #include "llvm/Support/Dwarf.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <map> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 namespace llvm { 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; 69 70 // Flag that indicates the initial value of the is_stmt_start flag. 71 #define DWARF2_LINE_DEFAULT_IS_STMT 1 72 73 #define DWARF2_FLAG_IS_STMT (1 << 0) 74 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) 75 #define DWARF2_FLAG_PROLOGUE_END (1 << 2) 76 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) 77 78 private: // MCContext manages these 79 friend class MCContext; 80 friend class MCLineEntry; MCDwarfLoc(unsigned fileNum,unsigned line,unsigned column,unsigned flags,unsigned isa,unsigned discriminator)81 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, 82 unsigned isa, unsigned discriminator) 83 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), 84 Discriminator(discriminator) {} 85 86 // Allow the default copy constructor and assignment operator to be used 87 // for an MCDwarfLoc object. 88 89 public: 90 /// getFileNum - Get the FileNum of this MCDwarfLoc. getFileNum()91 unsigned getFileNum() const { return FileNum; } 92 93 /// getLine - Get the Line of this MCDwarfLoc. getLine()94 unsigned getLine() const { return Line; } 95 96 /// getColumn - Get the Column of this MCDwarfLoc. getColumn()97 unsigned getColumn() const { return Column; } 98 99 /// getFlags - Get the Flags of this MCDwarfLoc. getFlags()100 unsigned getFlags() const { return Flags; } 101 102 /// getIsa - Get the Isa of this MCDwarfLoc. getIsa()103 unsigned getIsa() const { return Isa; } 104 105 /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. getDiscriminator()106 unsigned getDiscriminator() const { return Discriminator; } 107 108 /// setFileNum - Set the FileNum of this MCDwarfLoc. setFileNum(unsigned fileNum)109 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 110 111 /// setLine - Set the Line of this MCDwarfLoc. setLine(unsigned line)112 void setLine(unsigned line) { Line = line; } 113 114 /// setColumn - Set the Column of this MCDwarfLoc. setColumn(unsigned column)115 void setColumn(unsigned column) { Column = column; } 116 117 /// setFlags - Set the Flags of this MCDwarfLoc. setFlags(unsigned flags)118 void setFlags(unsigned flags) { Flags = flags; } 119 120 /// setIsa - Set the Isa of this MCDwarfLoc. setIsa(unsigned isa)121 void setIsa(unsigned isa) { Isa = isa; } 122 123 /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. setDiscriminator(unsigned discriminator)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. MCLineEntry(MCSymbol * label,const MCDwarfLoc loc)143 MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) 144 : MCDwarfLoc(loc), Label(label) {} 145 getLabel()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 addLineEntry(const MCLineEntry & LineEntry,const MCSection * Sec)161 void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) { 162 MCLineDivisions[Sec].push_back(LineEntry); 163 } 164 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; 169 170 private: 171 // A collection of MCLineEntry for each section. 172 MCLineDivisionMap MCLineDivisions; 173 174 public: 175 // Returns the collection of MCLineEntry for a given Compile Unit ID. getMCLineEntries()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 MCDwarfLineTableHeaderMCDwarfLineTableHeader188 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: setCompilationDir(StringRef CompilationDir)199 void setCompilationDir(StringRef CompilationDir) { 200 Header.CompilationDir = CompilationDir; 201 } getFile(StringRef Directory,StringRef FileName)202 unsigned getFile(StringRef Directory, StringRef FileName) { 203 return Header.getFile(Directory, FileName); 204 } 205 void Emit(MCStreamer &MCOS) const; 206 }; 207 208 class MCDwarfLineTable { 209 MCDwarfLineTableHeader Header; 210 MCLineSection MCLineSections; 211 212 public: 213 // This emits the Dwarf file and the line tables for all Compile Units. 214 static void Emit(MCObjectStreamer *MCOS); 215 216 // This emits the Dwarf file and the line tables for a given Compile Unit. 217 void EmitCU(MCObjectStreamer *MCOS) const; 218 219 unsigned getFile(StringRef &Directory, StringRef &FileName, 220 unsigned FileNumber = 0); 221 getLabel()222 MCSymbol *getLabel() const { 223 return Header.Label; 224 } 225 setLabel(MCSymbol * Label)226 void setLabel(MCSymbol *Label) { 227 Header.Label = Label; 228 } 229 setCompilationDir(StringRef CompilationDir)230 void setCompilationDir(StringRef CompilationDir) { 231 Header.CompilationDir = CompilationDir; 232 } 233 getMCDwarfDirs()234 const SmallVectorImpl<std::string> &getMCDwarfDirs() const { 235 return Header.MCDwarfDirs; 236 } 237 getMCDwarfDirs()238 SmallVectorImpl<std::string> &getMCDwarfDirs() { 239 return Header.MCDwarfDirs; 240 } 241 getMCDwarfFiles()242 const SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() const { 243 return Header.MCDwarfFiles; 244 } 245 getMCDwarfFiles()246 SmallVectorImpl<MCDwarfFile> &getMCDwarfFiles() { 247 return Header.MCDwarfFiles; 248 } 249 getMCLineSections()250 const MCLineSection &getMCLineSections() const { 251 return MCLineSections; 252 } getMCLineSections()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: MCGenDwarfLabelEntry(StringRef name,unsigned fileNumber,unsigned lineNumber,MCSymbol * label)291 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, 292 MCSymbol *label) 293 : Name(name), FileNumber(fileNumber), LineNumber(lineNumber), 294 Label(label) {} 295 getName()296 StringRef getName() const { return Name; } getFileNumber()297 unsigned getFileNumber() const { return FileNumber; } getLineNumber()298 unsigned getLineNumber() const { return LineNumber; } getLabel()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 324 }; 325 326 private: 327 OpType Operation; 328 MCSymbol *Label; 329 unsigned Register; 330 union { 331 int Offset; 332 unsigned Register2; 333 }; 334 std::vector<char> Values; 335 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R,int O,StringRef V)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 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R1,unsigned R2)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. createDefCfa(MCSymbol * L,unsigned Register,int Offset)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. createDefCfaRegister(MCSymbol * L,unsigned Register)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. createDefCfaOffset(MCSymbol * L,int Offset)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. createAdjustCfaOffset(MCSymbol * L,int Adjustment)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. createOffset(MCSymbol * L,unsigned Register,int Offset)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. createRelOffset(MCSymbol * L,unsigned Register,int Offset)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. createRegister(MCSymbol * L,unsigned Register1,unsigned 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. createWindowSave(MCSymbol * L)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. createRestore(MCSymbol * L,unsigned Register)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. createUndefined(MCSymbol * L,unsigned Register)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. createSameValue(MCSymbol * L,unsigned Register)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. createRememberState(MCSymbol * L)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. createRestoreState(MCSymbol * L)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. createEscape(MCSymbol * L,StringRef Vals)433 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { 434 return MCCFIInstruction(OpEscape, L, 0, 0, Vals); 435 } 436 getOperation()437 OpType getOperation() const { return Operation; } getLabel()438 MCSymbol *getLabel() const { return Label; } 439 getRegister()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 getRegister2()448 unsigned getRegister2() const { 449 assert(Operation == OpRegister); 450 return Register2; 451 } 452 getOffset()453 int getOffset() const { 454 assert(Operation == OpDefCfa || Operation == OpOffset || 455 Operation == OpRelOffset || Operation == OpDefCfaOffset || 456 Operation == OpAdjustCfaOffset); 457 return Offset; 458 } 459 getValues()460 StringRef getValues() const { 461 assert(Operation == OpEscape); 462 return StringRef(&Values[0], Values.size()); 463 } 464 }; 465 466 struct MCDwarfFrameInfo { MCDwarfFrameInfoMCDwarfFrameInfo467 MCDwarfFrameInfo() 468 : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), 469 Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), 470 LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), 471 IsSimple(false) {} 472 MCSymbol *Begin; 473 MCSymbol *End; 474 const MCSymbol *Personality; 475 const MCSymbol *Lsda; 476 std::vector<MCCFIInstruction> Instructions; 477 unsigned CurrentCfaRegister; 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 }; 495 } // end namespace llvm 496 497 #endif 498