| //===- MCDwarf.h - Machine Code Dwarf support -------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file contains the declaration of the MCDwarfFile to support the dwarf |
| // .file directive and the .loc directive. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_MC_MCDWARF_H |
| #define LLVM_MC_MCDWARF_H |
| |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/Compiler.h" |
| #include "llvm/Support/Dwarf.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include <map> |
| #include <vector> |
| |
| namespace llvm { |
| class MCContext; |
| class MCObjectWriter; |
| class MCSection; |
| class MCStreamer; |
| class MCSymbol; |
| class SourceMgr; |
| class SMLoc; |
| |
| /// MCDwarfFile - Instances of this class represent the name of the dwarf |
| /// .file directive and its associated dwarf file number in the MC file, |
| /// and MCDwarfFile's are created and unique'd by the MCContext class where |
| /// the file number for each is its index into the vector of DwarfFiles (note |
| /// index 0 is not used and not a valid dwarf file number). |
| class MCDwarfFile { |
| // Name - the base name of the file without its directory path. |
| // The StringRef references memory allocated in the MCContext. |
| StringRef Name; |
| |
| // DirIndex - the index into the list of directory names for this file name. |
| unsigned DirIndex; |
| |
| private: // MCContext creates and uniques these. |
| friend class MCContext; |
| MCDwarfFile(StringRef name, unsigned dirIndex) |
| : Name(name), DirIndex(dirIndex) {} |
| |
| MCDwarfFile(const MCDwarfFile&) LLVM_DELETED_FUNCTION; |
| void operator=(const MCDwarfFile&) LLVM_DELETED_FUNCTION; |
| public: |
| /// getName - Get the base name of this MCDwarfFile. |
| StringRef getName() const { return Name; } |
| |
| /// getDirIndex - Get the dirIndex of this MCDwarfFile. |
| unsigned getDirIndex() const { return DirIndex; } |
| |
| |
| /// print - Print the value to the stream \p OS. |
| void print(raw_ostream &OS) const; |
| |
| /// dump - Print the value to stderr. |
| void dump() const; |
| }; |
| |
| inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){ |
| DwarfFile.print(OS); |
| return OS; |
| } |
| |
| /// MCDwarfLoc - Instances of this class represent the information from a |
| /// dwarf .loc directive. |
| class MCDwarfLoc { |
| // FileNum - the file number. |
| unsigned FileNum; |
| // Line - the line number. |
| unsigned Line; |
| // Column - the column position. |
| unsigned Column; |
| // Flags (see #define's below) |
| unsigned Flags; |
| // Isa |
| unsigned Isa; |
| // Discriminator |
| unsigned Discriminator; |
| |
| // Flag that indicates the initial value of the is_stmt_start flag. |
| #define DWARF2_LINE_DEFAULT_IS_STMT 1 |
| |
| #define DWARF2_FLAG_IS_STMT (1 << 0) |
| #define DWARF2_FLAG_BASIC_BLOCK (1 << 1) |
| #define DWARF2_FLAG_PROLOGUE_END (1 << 2) |
| #define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3) |
| |
| private: // MCContext manages these |
| friend class MCContext; |
| friend class MCLineEntry; |
| MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags, |
| unsigned isa, unsigned discriminator) |
| : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa), |
| Discriminator(discriminator) {} |
| |
| // Allow the default copy constructor and assignment operator to be used |
| // for an MCDwarfLoc object. |
| |
| public: |
| /// getFileNum - Get the FileNum of this MCDwarfLoc. |
| unsigned getFileNum() const { return FileNum; } |
| |
| /// getLine - Get the Line of this MCDwarfLoc. |
| unsigned getLine() const { return Line; } |
| |
| /// getColumn - Get the Column of this MCDwarfLoc. |
| unsigned getColumn() const { return Column; } |
| |
| /// getFlags - Get the Flags of this MCDwarfLoc. |
| unsigned getFlags() const { return Flags; } |
| |
| /// getIsa - Get the Isa of this MCDwarfLoc. |
| unsigned getIsa() const { return Isa; } |
| |
| /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. |
| unsigned getDiscriminator() const { return Discriminator; } |
| |
| /// setFileNum - Set the FileNum of this MCDwarfLoc. |
| void setFileNum(unsigned fileNum) { FileNum = fileNum; } |
| |
| /// setLine - Set the Line of this MCDwarfLoc. |
| void setLine(unsigned line) { Line = line; } |
| |
| /// setColumn - Set the Column of this MCDwarfLoc. |
| void setColumn(unsigned column) { Column = column; } |
| |
| /// setFlags - Set the Flags of this MCDwarfLoc. |
| void setFlags(unsigned flags) { Flags = flags; } |
| |
| /// setIsa - Set the Isa of this MCDwarfLoc. |
| void setIsa(unsigned isa) { Isa = isa; } |
| |
| /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. |
| void setDiscriminator(unsigned discriminator) { |
| Discriminator = discriminator; |
| } |
| }; |
| |
| /// MCLineEntry - Instances of this class represent the line information for |
| /// the dwarf line table entries. Which is created after a machine |
| /// instruction is assembled and uses an address from a temporary label |
| /// created at the current address in the current section and the info from |
| /// the last .loc directive seen as stored in the context. |
| class MCLineEntry : public MCDwarfLoc { |
| MCSymbol *Label; |
| |
| private: |
| // Allow the default copy constructor and assignment operator to be used |
| // for an MCLineEntry object. |
| |
| public: |
| // Constructor to create an MCLineEntry given a symbol and the dwarf loc. |
| MCLineEntry(MCSymbol *label, const MCDwarfLoc loc) : MCDwarfLoc(loc), |
| Label(label) {} |
| |
| MCSymbol *getLabel() const { return Label; } |
| |
| // This is called when an instruction is assembled into the specified |
| // section and if there is information from the last .loc directive that |
| // has yet to have a line entry made for it is made. |
| static void Make(MCStreamer *MCOS, const MCSection *Section); |
| }; |
| |
| /// MCLineSection - Instances of this class represent the line information |
| /// for a section where machine instructions have been assembled after seeing |
| /// .loc directives. This is the information used to build the dwarf line |
| /// table for a section. |
| class MCLineSection { |
| |
| private: |
| MCLineSection(const MCLineSection&) LLVM_DELETED_FUNCTION; |
| void operator=(const MCLineSection&) LLVM_DELETED_FUNCTION; |
| |
| public: |
| // Constructor to create an MCLineSection with an empty MCLineEntries |
| // vector. |
| MCLineSection() {} |
| |
| // addLineEntry - adds an entry to this MCLineSection's line entries |
| void addLineEntry(const MCLineEntry &LineEntry, unsigned CUID) { |
| MCLineDivisions[CUID].push_back(LineEntry); |
| } |
| |
| typedef std::vector<MCLineEntry> MCLineEntryCollection; |
| typedef MCLineEntryCollection::iterator iterator; |
| typedef MCLineEntryCollection::const_iterator const_iterator; |
| typedef std::map<unsigned, MCLineEntryCollection> MCLineDivisionMap; |
| |
| private: |
| // A collection of MCLineEntry for each Compile Unit ID. |
| MCLineDivisionMap MCLineDivisions; |
| |
| public: |
| // Returns whether MCLineSection contains entries for a given Compile |
| // Unit ID. |
| bool containEntriesForID(unsigned CUID) const { |
| return MCLineDivisions.count(CUID); |
| } |
| // Returns the collection of MCLineEntry for a given Compile Unit ID. |
| const MCLineEntryCollection &getMCLineEntries(unsigned CUID) const { |
| MCLineDivisionMap::const_iterator CIter = MCLineDivisions.find(CUID); |
| assert(CIter != MCLineDivisions.end()); |
| return CIter->second; |
| } |
| }; |
| |
| class MCDwarfFileTable { |
| public: |
| // |
| // This emits the Dwarf file and the line tables for all Compile Units. |
| // |
| static const MCSymbol *Emit(MCStreamer *MCOS); |
| // |
| // This emits the Dwarf file and the line tables for a given Compile Unit. |
| // |
| static const MCSymbol *EmitCU(MCStreamer *MCOS, unsigned ID); |
| }; |
| |
| class MCDwarfLineAddr { |
| public: |
| /// Utility function to encode a Dwarf pair of LineDelta and AddrDeltas. |
| static void Encode(int64_t LineDelta, uint64_t AddrDelta, raw_ostream &OS); |
| |
| /// Utility function to emit the encoding to a streamer. |
| static void Emit(MCStreamer *MCOS, |
| int64_t LineDelta,uint64_t AddrDelta); |
| |
| /// Utility function to write the encoding to an object writer. |
| static void Write(MCObjectWriter *OW, |
| int64_t LineDelta, uint64_t AddrDelta); |
| }; |
| |
| class MCGenDwarfInfo { |
| public: |
| // |
| // When generating dwarf for assembly source files this emits the Dwarf |
| // sections. |
| // |
| static void Emit(MCStreamer *MCOS, const MCSymbol *LineSectionSymbol); |
| }; |
| |
| // When generating dwarf for assembly source files this is the info that is |
| // needed to be gathered for each symbol that will have a dwarf label. |
| class MCGenDwarfLabelEntry { |
| private: |
| // Name of the symbol without a leading underbar, if any. |
| StringRef Name; |
| // The dwarf file number this symbol is in. |
| unsigned FileNumber; |
| // The line number this symbol is at. |
| unsigned LineNumber; |
| // The low_pc for the dwarf label is taken from this symbol. |
| MCSymbol *Label; |
| |
| public: |
| MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, |
| unsigned lineNumber, MCSymbol *label) : |
| Name(name), FileNumber(fileNumber), LineNumber(lineNumber), Label(label){} |
| |
| StringRef getName() const { return Name; } |
| unsigned getFileNumber() const { return FileNumber; } |
| unsigned getLineNumber() const { return LineNumber; } |
| MCSymbol *getLabel() const { return Label; } |
| |
| // This is called when label is created when we are generating dwarf for |
| // assembly source files. |
| static void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, |
| SMLoc &Loc); |
| }; |
| |
| class MCCFIInstruction { |
| public: |
| enum OpType { OpSameValue, OpRememberState, OpRestoreState, OpOffset, |
| OpDefCfaRegister, OpDefCfaOffset, OpDefCfa, OpRelOffset, |
| OpAdjustCfaOffset, OpEscape, OpRestore, OpUndefined, |
| OpRegister }; |
| private: |
| OpType Operation; |
| MCSymbol *Label; |
| unsigned Register; |
| union { |
| int Offset; |
| unsigned Register2; |
| }; |
| std::vector<char> Values; |
| |
| MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, StringRef V) : |
| Operation(Op), Label(L), Register(R), Offset(O), |
| Values(V.begin(), V.end()) { |
| assert(Op != OpRegister); |
| } |
| |
| MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R1, unsigned R2) : |
| Operation(Op), Label(L), Register(R1), Register2(R2) { |
| assert(Op == OpRegister); |
| } |
| |
| public: |
| static MCCFIInstruction |
| createOffset(MCSymbol *L, unsigned Register, int Offset) { |
| return MCCFIInstruction(OpOffset, L, Register, Offset, ""); |
| } |
| |
| static MCCFIInstruction |
| createDefCfaRegister(MCSymbol *L, unsigned Register) { |
| return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, ""); |
| } |
| |
| static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset) { |
| return MCCFIInstruction(OpDefCfaOffset, L, 0, -Offset, ""); |
| } |
| |
| static MCCFIInstruction |
| createDefCfa(MCSymbol *L, unsigned Register, int Offset) { |
| return MCCFIInstruction(OpDefCfa, L, Register, -Offset, ""); |
| } |
| |
| static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register) { |
| return MCCFIInstruction(OpUndefined, L, Register, 0, ""); |
| } |
| |
| static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register) { |
| return MCCFIInstruction(OpRestore, L, Register, 0, ""); |
| } |
| |
| static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register) { |
| return MCCFIInstruction(OpSameValue, L, Register, 0, ""); |
| } |
| |
| static MCCFIInstruction createRestoreState(MCSymbol *L) { |
| return MCCFIInstruction(OpRestoreState, L, 0, 0, ""); |
| } |
| |
| static MCCFIInstruction createRememberState(MCSymbol *L) { |
| return MCCFIInstruction(OpRememberState, L, 0, 0, ""); |
| } |
| |
| static MCCFIInstruction |
| createRelOffset(MCSymbol *L, unsigned Register, int Offset) { |
| return MCCFIInstruction(OpRelOffset, L, Register, Offset, ""); |
| } |
| |
| static MCCFIInstruction |
| createAdjustCfaOffset(MCSymbol *L, int Adjustment) { |
| return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, ""); |
| } |
| |
| static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals) { |
| return MCCFIInstruction(OpEscape, L, 0, 0, Vals); |
| } |
| |
| static MCCFIInstruction |
| createRegister(MCSymbol *L, unsigned Register1, unsigned Register2) { |
| return MCCFIInstruction(OpRegister, L, Register1, Register2); |
| } |
| |
| OpType getOperation() const { return Operation; } |
| MCSymbol *getLabel() const { return Label; } |
| |
| unsigned getRegister() const { |
| assert(Operation == OpDefCfa || Operation == OpOffset || |
| Operation == OpRestore || Operation == OpUndefined || |
| Operation == OpSameValue || Operation == OpDefCfaRegister || |
| Operation == OpRelOffset || Operation == OpRegister); |
| return Register; |
| } |
| |
| unsigned getRegister2() const { |
| assert(Operation == OpRegister); |
| return Register2; |
| } |
| |
| int getOffset() const { |
| assert(Operation == OpDefCfa || Operation == OpOffset || |
| Operation == OpRelOffset || Operation == OpDefCfaOffset || |
| Operation == OpAdjustCfaOffset); |
| return Offset; |
| } |
| |
| const StringRef getValues() const { |
| assert(Operation == OpEscape); |
| return StringRef(&Values[0], Values.size()); |
| } |
| }; |
| |
| struct MCDwarfFrameInfo { |
| MCDwarfFrameInfo() : Begin(0), End(0), Personality(0), Lsda(0), |
| Function(0), Instructions(), PersonalityEncoding(), |
| LsdaEncoding(0), CompactUnwindEncoding(0), |
| IsSignalFrame(false) {} |
| MCSymbol *Begin; |
| MCSymbol *End; |
| const MCSymbol *Personality; |
| const MCSymbol *Lsda; |
| const MCSymbol *Function; |
| std::vector<MCCFIInstruction> Instructions; |
| unsigned PersonalityEncoding; |
| unsigned LsdaEncoding; |
| uint32_t CompactUnwindEncoding; |
| bool IsSignalFrame; |
| }; |
| |
| class MCDwarfFrameEmitter { |
| public: |
| // |
| // This emits the frame info section. |
| // |
| static void Emit(MCStreamer &streamer, bool usingCFI, |
| bool isEH); |
| static void EmitAdvanceLoc(MCStreamer &Streamer, uint64_t AddrDelta); |
| static void EncodeAdvanceLoc(uint64_t AddrDelta, raw_ostream &OS); |
| }; |
| } // end namespace llvm |
| |
| #endif |