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/StringRef.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/Dwarf.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include <map> 23 #include <vector> 24 25 namespace llvm { 26 class MCContext; 27 class MCSection; 28 class MCStreamer; 29 class MCSymbol; 30 class SourceMgr; 31 class SMLoc; 32 33 /// MCDwarfFile - Instances of this class represent the name of the dwarf 34 /// .file directive and its associated dwarf file number in the MC file, 35 /// and MCDwarfFile's are created and unique'd by the MCContext class where 36 /// the file number for each is its index into the vector of DwarfFiles (note 37 /// index 0 is not used and not a valid dwarf file number). 38 class MCDwarfFile { 39 // Name - the base name of the file without its directory path. 40 // The StringRef references memory allocated in the MCContext. 41 StringRef Name; 42 43 // DirIndex - the index into the list of directory names for this file name. 44 unsigned DirIndex; 45 46 private: // MCContext creates and uniques these. 47 friend class MCContext; MCDwarfFile(StringRef name,unsigned dirIndex)48 MCDwarfFile(StringRef name, unsigned dirIndex) 49 : Name(name), DirIndex(dirIndex) {} 50 51 MCDwarfFile(const MCDwarfFile&) LLVM_DELETED_FUNCTION; 52 void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; 53 public: 54 /// getName - Get the base name of this MCDwarfFile. getName()55 StringRef getName() const { return Name; } 56 57 /// getDirIndex - Get the dirIndex of this MCDwarfFile. getDirIndex()58 unsigned getDirIndex() const { return DirIndex; } 59 60 61 /// print - Print the value to the stream \p OS. 62 void print(raw_ostream &OS) const; 63 64 /// dump - Print the value to stderr. 65 void dump() const; 66 }; 67 68 inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ 69 DwarfFile.print(OS); 70 return OS; 71 } 72 73 /// MCDwarfLoc - Instances of this class represent the information from a 74 /// dwarf .loc directive. 75 class MCDwarfLoc { 76 // FileNum - the file number. 77 unsigned FileNum; 78 // Line - the line number. 79 unsigned Line; 80 // Column - the column position. 81 unsigned Column; 82 // Flags (see #define's below) 83 unsigned Flags; 84 // Isa 85 unsigned Isa; 86 // Discriminator 87 unsigned Discriminator; 88 89 // Flag that indicates the initial value of the is_stmt_start flag. 90 #define DWARF2_LINE_DEFAULT_IS_STMT 1 91 92 #define DWARF2_FLAG_IS_STMT (1 << 0) 93 #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) 94 #define DWARF2_FLAG_PROLOGUE_END (1 << 2) 95 #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) 96 97 private: // MCContext manages these 98 friend class MCContext; 99 friend class MCLineEntry; MCDwarfLoc(unsigned fileNum,unsigned line,unsigned column,unsigned flags,unsigned isa,unsigned discriminator)100 MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, 101 unsigned isa, unsigned discriminator) 102 : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), 103 Discriminator(discriminator) {} 104 105 // Allow the default copy constructor and assignment operator to be used 106 // for an MCDwarfLoc object. 107 108 public: 109 /// getFileNum - Get the FileNum of this MCDwarfLoc. getFileNum()110 unsigned getFileNum() const { return FileNum; } 111 112 /// getLine - Get the Line of this MCDwarfLoc. getLine()113 unsigned getLine() const { return Line; } 114 115 /// getColumn - Get the Column of this MCDwarfLoc. getColumn()116 unsigned getColumn() const { return Column; } 117 118 /// getFlags - Get the Flags of this MCDwarfLoc. getFlags()119 unsigned getFlags() const { return Flags; } 120 121 /// getIsa - Get the Isa of this MCDwarfLoc. getIsa()122 unsigned getIsa() const { return Isa; } 123 124 /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. getDiscriminator()125 unsigned getDiscriminator() const { return Discriminator; } 126 127 /// setFileNum - Set the FileNum of this MCDwarfLoc. setFileNum(unsigned fileNum)128 void setFileNum(unsigned fileNum) { FileNum = fileNum; } 129 130 /// setLine - Set the Line of this MCDwarfLoc. setLine(unsigned line)131 void setLine(unsigned line) { Line = line; } 132 133 /// setColumn - Set the Column of this MCDwarfLoc. setColumn(unsigned column)134 void setColumn(unsigned column) { Column = column; } 135 136 /// setFlags - Set the Flags of this MCDwarfLoc. setFlags(unsigned flags)137 void setFlags(unsigned flags) { Flags = flags; } 138 139 /// setIsa - Set the Isa of this MCDwarfLoc. setIsa(unsigned isa)140 void setIsa(unsigned isa) { Isa = isa; } 141 142 /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. setDiscriminator(unsigned discriminator)143 void setDiscriminator(unsigned discriminator) { 144 Discriminator = discriminator; 145 } 146 }; 147 148 /// MCLineEntry - 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 MCLineEntry : public MCDwarfLoc { 154 MCSymbol *Label; 155 156 private: 157 // Allow the default copy constructor and assignment operator to be used 158 // for an MCLineEntry object. 159 160 public: 161 // Constructor to create an MCLineEntry given a symbol and the dwarf loc. MCLineEntry(MCSymbol * label,const MCDwarfLoc loc)162 MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), 163 Label(label) {} 164 getLabel()165 MCSymbol *getLabel() const { return Label; } 166 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(MCStreamer *MCOS, const MCSection *Section); 171 }; 172 173 /// MCLineSection - Instances of this class represent the line information 174 /// for a section where machine instructions have been assembled after seeing 175 /// .loc directives. This is the information used to build the dwarf line 176 /// table for a section. 177 class MCLineSection { 178 179 private: 180 MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; 181 void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; 182 183 public: 184 // Constructor to create an MCLineSection with an empty MCLineEntries 185 // vector. MCLineSection()186 MCLineSection() {} 187 188 // addLineEntry - adds an entry to this MCLineSection's line entries addLineEntry(const MCLineEntry & LineEntry,unsigned CUID)189 void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { 190 MCLineDivisions[CUID].push_back(LineEntry); 191 } 192 193 typedef std::vector<MCLineEntry> MCLineEntryCollection; 194 typedef MCLineEntryCollection::iterator iterator; 195 typedef MCLineEntryCollection::const_iterator const_iterator; 196 typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; 197 198 private: 199 // A collection of MCLineEntry for each Compile Unit ID. 200 MCLineDivisionMap MCLineDivisions; 201 202 public: 203 // Returns whether MCLineSection contains entries for a given Compile 204 // Unit ID. containEntriesForID(unsigned CUID)205 bool containEntriesForID(unsigned CUID) const { 206 return MCLineDivisions.count(CUID); 207 } 208 // Returns the collection of MCLineEntry for a given Compile Unit ID. getMCLineEntries(unsigned CUID)209 const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { 210 MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); 211 assert(CIter != MCLineDivisions.end()); 212 return CIter->second; 213 } 214 }; 215 216 class MCDwarfFileTable { 217 public: 218 // 219 // This emits the Dwarf file and the line tables for all Compile Units. 220 // 221 static const MCSymbol *Emit(MCStreamer *MCOS); 222 // 223 // This emits the Dwarf file and the line tables for a given Compile Unit. 224 // 225 static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); 226 }; 227 228 class MCDwarfLineAddr { 229 public: 230 /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. 231 static void Encode(MCContext &Context, int64_t LineDelta, 232 uint64_t AddrDelta, raw_ostream &OS); 233 234 /// Utility function to emit the encoding to a streamer. 235 static void Emit(MCStreamer *MCOS, 236 int64_t LineDelta,uint64_t AddrDelta); 237 }; 238 239 class MCGenDwarfInfo { 240 public: 241 // 242 // When generating dwarf for assembly source files this emits the Dwarf 243 // sections. 244 // 245 static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); 246 }; 247 248 // When generating dwarf for assembly source files this is the info that is 249 // needed to be gathered for each symbol that will have a dwarf label. 250 class MCGenDwarfLabelEntry { 251 private: 252 // Name of the symbol without a leading underbar, if any. 253 StringRef Name; 254 // The dwarf file number this symbol is in. 255 unsigned FileNumber; 256 // The line number this symbol is at. 257 unsigned LineNumber; 258 // The low_pc for the dwarf label is taken from this symbol. 259 MCSymbol *Label; 260 261 public: MCGenDwarfLabelEntry(StringRef name,unsigned fileNumber,unsigned lineNumber,MCSymbol * label)262 MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, 263 unsigned lineNumber, MCSymbol *label) : 264 Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} 265 getName()266 StringRef getName() const { return Name; } getFileNumber()267 unsigned getFileNumber() const { return FileNumber; } getLineNumber()268 unsigned getLineNumber() const { return LineNumber; } getLabel()269 MCSymbol *getLabel() const { return Label; } 270 271 // This is called when label is created when we are generating dwarf for 272 // assembly source files. 273 static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, 274 SMLoc &Loc); 275 }; 276 277 class MCCFIInstruction { 278 public: 279 enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, 280 OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, 281 OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, 282 OpRegister }; 283 private: 284 OpType Operation; 285 MCSymbol *Label; 286 unsigned Register; 287 union { 288 int Offset; 289 unsigned Register2; 290 }; 291 std::vector<char> Values; 292 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R,int O,StringRef V)293 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : 294 Operation(Op), Label(L), Register(R), Offset(O), 295 Values(V.begin(), V.end()) { 296 assert(Op != OpRegister); 297 } 298 MCCFIInstruction(OpType Op,MCSymbol * L,unsigned R1,unsigned R2)299 MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : 300 Operation(Op), Label(L), Register(R1), Register2(R2) { 301 assert(Op == OpRegister); 302 } 303 304 public: 305 static MCCFIInstruction createOffset(MCSymbol * L,unsigned Register,int Offset)306 createOffset(MCSymbol *L, unsigned Register, int Offset) { 307 return MCCFIInstruction(OpOffset, L, Register, Offset, ""); 308 } 309 310 static MCCFIInstruction createDefCfaRegister(MCSymbol * L,unsigned Register)311 createDefCfaRegister(MCSymbol *L, unsigned Register) { 312 return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); 313 } 314 createDefCfaOffset(MCSymbol * L,int Offset)315 static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { 316 return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); 317 } 318 319 static MCCFIInstruction createDefCfa(MCSymbol * L,unsigned Register,int Offset)320 createDefCfa(MCSymbol *L, unsigned Register, int Offset) { 321 return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); 322 } 323 createUndefined(MCSymbol * L,unsigned Register)324 static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { 325 return MCCFIInstruction(OpUndefined, L, Register, 0, ""); 326 } 327 createRestore(MCSymbol * L,unsigned Register)328 static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { 329 return MCCFIInstruction(OpRestore, L, Register, 0, ""); 330 } 331 createSameValue(MCSymbol * L,unsigned Register)332 static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { 333 return MCCFIInstruction(OpSameValue, L, Register, 0, ""); 334 } 335 createRestoreState(MCSymbol * L)336 static MCCFIInstruction createRestoreState(MCSymbol *L) { 337 return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); 338 } 339 createRememberState(MCSymbol * L)340 static MCCFIInstruction createRememberState(MCSymbol *L) { 341 return MCCFIInstruction(OpRememberState, L, 0, 0, ""); 342 } 343 344 static MCCFIInstruction createRelOffset(MCSymbol * L,unsigned Register,int Offset)345 createRelOffset(MCSymbol *L, unsigned Register, int Offset) { 346 return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); 347 } 348 349 static MCCFIInstruction createAdjustCfaOffset(MCSymbol * L,int Adjustment)350 createAdjustCfaOffset(MCSymbol *L, int Adjustment) { 351 return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); 352 } 353 createEscape(MCSymbol * L,StringRef Vals)354 static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { 355 return MCCFIInstruction(OpEscape, L, 0, 0, Vals); 356 } 357 358 static MCCFIInstruction createRegister(MCSymbol * L,unsigned Register1,unsigned Register2)359 createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { 360 return MCCFIInstruction(OpRegister, L, Register1, Register2); 361 } 362 getOperation()363 OpType getOperation() const { return Operation; } getLabel()364 MCSymbol *getLabel() const { return Label; } 365 getRegister()366 unsigned getRegister() const { 367 assert(Operation == OpDefCfa || Operation == OpOffset || 368 Operation == OpRestore || Operation == OpUndefined || 369 Operation == OpSameValue || Operation == OpDefCfaRegister || 370 Operation == OpRelOffset || Operation == OpRegister); 371 return Register; 372 } 373 getRegister2()374 unsigned getRegister2() const { 375 assert(Operation == OpRegister); 376 return Register2; 377 } 378 getOffset()379 int getOffset() const { 380 assert(Operation == OpDefCfa || Operation == OpOffset || 381 Operation == OpRelOffset || Operation == OpDefCfaOffset || 382 Operation == OpAdjustCfaOffset); 383 return Offset; 384 } 385 getValues()386 const StringRef getValues() const { 387 assert(Operation == OpEscape); 388 return StringRef(&Values[0], Values.size()); 389 } 390 }; 391 392 struct MCDwarfFrameInfo { MCDwarfFrameInfoMCDwarfFrameInfo393 MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), 394 Function(0), Instructions(), PersonalityEncoding(), 395 LsdaEncoding(0), CompactUnwindEncoding(0), 396 IsSignalFrame(false) {} 397 MCSymbol *Begin; 398 MCSymbol *End; 399 const MCSymbol *Personality; 400 const MCSymbol *Lsda; 401 const MCSymbol *Function; 402 std::vector<MCCFIInstruction> Instructions; 403 unsigned PersonalityEncoding; 404 unsigned LsdaEncoding; 405 uint32_t CompactUnwindEncoding; 406 bool IsSignalFrame; 407 }; 408 409 class MCDwarfFrameEmitter { 410 public: 411 // 412 // This emits the frame info section. 413 // 414 static void Emit(MCStreamer &streamer, bool usingCFI, 415 bool isEH); 416 static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); 417 static void EncodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, 418 raw_ostream &OS); 419 }; 420 } // end namespace llvm 421 422 #endif 423