Home | History | Annotate | Download | only in MC
      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;
     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.
     91   unsigned getFileNum() const { return FileNum; }
     92 
     93   /// getLine - Get the Line of this MCDwarfLoc.
     94   unsigned getLine() const { return Line; }
     95 
     96   /// getColumn - Get the Column of this MCDwarfLoc.
     97   unsigned getColumn() const { return Column; }
     98 
     99   /// getFlags - Get the Flags of this MCDwarfLoc.
    100   unsigned getFlags() const { return Flags; }
    101 
    102   /// getIsa - Get the Isa of this MCDwarfLoc.
    103   unsigned getIsa() const { return Isa; }
    104 
    105   /// getDiscriminator - Get the Discriminator of this MCDwarfLoc.
    106   unsigned getDiscriminator() const { return Discriminator; }
    107 
    108   /// setFileNum - Set the FileNum of this MCDwarfLoc.
    109   void setFileNum(unsigned fileNum) { FileNum = fileNum; }
    110 
    111   /// setLine - Set the Line of this MCDwarfLoc.
    112   void setLine(unsigned line) { Line = line; }
    113 
    114   /// setColumn - Set the Column of this MCDwarfLoc.
    115   void setColumn(unsigned column) { Column = column; }
    116 
    117   /// setFlags - Set the Flags of this MCDwarfLoc.
    118   void setFlags(unsigned flags) { Flags = flags; }
    119 
    120   /// setIsa - Set the Isa of this MCDwarfLoc.
    121   void setIsa(unsigned isa) { Isa = isa; }
    122 
    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   }
    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.
    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 };
    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 
    222   MCSymbol *getLabel() const {
    223     return Header.Label;
    224   }
    225 
    226   void setLabel(MCSymbol *Label) {
    227     Header.Label = Label;
    228   }
    229 
    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
    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 
    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),
    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