First bit of support for the dwarf .loc directive. This patch updates the
authorKevin Enderby <enderby@apple.com>
Tue, 24 Aug 2010 20:32:42 +0000 (20:32 +0000)
committerKevin Enderby <enderby@apple.com>
Tue, 24 Aug 2010 20:32:42 +0000 (20:32 +0000)
needed parsing for the .loc directive and saves the current info from that
into the context.  The next patch will take the current loc info after an
instruction is assembled and save that info into a vector for each section for
use to build the line number tables.  The patch after that will encode the info
from those vectors into the output file as the dwarf line tables.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111956 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCContext.h
include/llvm/MC/MCDwarf.h
lib/MC/MCContext.cpp
lib/MC/MCParser/AsmParser.cpp

index 17e79fb1e9eb8670c2d8aa94d2a8997ec4b78191..6686950b72dcb0ac686cd9c8e82d9d9ba191561a 100644 (file)
@@ -11,6 +11,7 @@
 #define LLVM_MC_MCCONTEXT_H
 
 #include "llvm/MC/SectionKind.h"
+#include "llvm/MC/MCDwarf.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Allocator.h"
@@ -24,6 +25,7 @@ namespace llvm {
   class MCSymbol;
   class MCLabel;
   class MCDwarfFile;
+  class MCDwarfLoc;
   class StringRef;
   class Twine;
   class MCSectionMachO;
@@ -69,6 +71,10 @@ namespace llvm {
     std::vector<MCDwarfFile *> MCDwarfFiles;
     std::vector<StringRef> MCDwarfDirs;
 
+    /// The current dwarf line information from the last dwarf .loc directive.
+    MCDwarfLoc CurrentDwarfLoc;
+    bool DwarfLocSeen;
+
     /// Allocator - Allocator object used for creating machine code objects.
     ///
     /// We use a bump pointer allocator to avoid the need to track all allocated
@@ -149,6 +155,8 @@ namespace llvm {
     /// GetDwarfFile - creates an entry in the dwarf file and directory tables.
     unsigned GetDwarfFile(StringRef FileName, unsigned FileNumber);
 
+    bool ValidateDwarfFileNumber(unsigned FileNumber);
+
     const std::vector<MCDwarfFile *> &getMCDwarfFiles() {
       return MCDwarfFiles;
     }
@@ -156,6 +164,19 @@ namespace llvm {
       return MCDwarfDirs;
     }
 
+    /// setCurrentDwarfLoc - saves the information from the currently parsed
+    /// dwarf .loc directive and sets DwarfLocSeen.  When the next instruction      /// is assembled an entry in the line number table with this information and
+    /// the address of the instruction will be created.
+    void setCurrentDwarfLoc(unsigned FileNum, unsigned Line, unsigned Column,
+                            unsigned Flags, unsigned Isa) {
+      CurrentDwarfLoc.setFileNum(FileNum);
+      CurrentDwarfLoc.setLine(Line);
+      CurrentDwarfLoc.setColumn(Column);
+      CurrentDwarfLoc.setFlags(Flags);
+      CurrentDwarfLoc.setIsa(Isa);
+      DwarfLocSeen = true;
+    }
+
     /// @}
 
     char *getSecureLogFile() { return SecureLogFile; }
index e21b42f7bbf198e5f1de11798b31b6a4991998d6..4f39f7939786fae62e33a4baf30fe33241e30250 100644 (file)
@@ -57,6 +57,50 @@ namespace llvm {
     void dump() const;
   };
 
+  /// 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;
+
+#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;
+    MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
+               unsigned isa)
+      : FileNum(fileNum), Line(line), Column(column), Flags(flags), Isa(isa) {}
+
+    MCDwarfLoc(const MCDwarfLoc&);       // DO NOT IMPLEMENT
+    void operator=(const MCDwarfLoc&); // DO NOT IMPLEMENT
+  public:
+    /// 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; }
+  };
+
   inline raw_ostream &operator<<(raw_ostream &OS, const MCDwarfFile &DwarfFile){
     DwarfFile.print(OS);
     return OS;
index adf476cf3f465416bb0244551696fd37bf349073..13cf9a80482bb0716cbf2e7dd418134d85638d5d 100644 (file)
@@ -24,7 +24,8 @@ typedef StringMap<const MCSectionELF*> ELFUniqueMapTy;
 typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
 
 
-MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0) {
+MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0),
+                     CurrentDwarfLoc(0,0,0,0,0) {
   MachOUniquingMap = 0;
   ELFUniquingMap = 0;
   COFFUniquingMap = 0;
@@ -32,6 +33,8 @@ MCContext::MCContext(const MCAsmInfo &mai) : MAI(mai), NextUniqueID(0) {
   SecureLogFile = getenv("AS_SECURE_LOG_FILE");
   SecureLog = 0;
   SecureLogUsed = false;
+
+  DwarfLocSeen = false;
 }
 
 MCContext::~MCContext() {
@@ -247,3 +250,16 @@ unsigned MCContext::GetDwarfFile(StringRef FileName, unsigned FileNumber) {
   // return the allocated FileNumber.
   return FileNumber;
 }
+
+/// ValidateDwarfFileNumber - takes a dwarf file number and returns true if it
+/// currently is assigned and false otherwise.
+bool MCContext::ValidateDwarfFileNumber(unsigned FileNumber) {
+  if(FileNumber == 0 || FileNumber >= MCDwarfFiles.size())
+    return false;
+
+  MCDwarfFile *&ExistingFile = MCDwarfFiles[FileNumber];
+  if (ExistingFile)
+    return true;
+  else
+    return false;
+}
index 747b0097e1ec1fff970b3f2ef17d242bbba98403..c65becf9741cf038f626cdd1096a46031cf74d90 100644 (file)
@@ -1838,39 +1838,101 @@ bool GenericAsmParser::ParseDirectiveLine(StringRef, SMLoc DirectiveLoc) {
 
 
 /// ParseDirectiveLoc
-/// ::= .loc number [number [number]]
+/// ::= .loc FileNumber LineNumber [ColumnPos] [basic_block] [prologue_end]
+///                                [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+/// The first number is a file number, must have been previously assigned with
+/// a .file directive, the second number is the line number and optionally the
+/// third number is a column position (zero if not specified).  The remaining
+/// optional items are .loc sub-directives.
 bool GenericAsmParser::ParseDirectiveLoc(StringRef, SMLoc DirectiveLoc) {
+
   if (getLexer().isNot(AsmToken::Integer))
     return TokError("unexpected token in '.loc' directive");
-
-  // FIXME: What are these fields?
   int64_t FileNumber = getTok().getIntVal();
-  (void) FileNumber;
-  // FIXME: Validate file.
+  if (FileNumber < 1)
+    return TokError("file number less than one in '.loc' directive");
+  if (!getContext().ValidateDwarfFileNumber(FileNumber))
+    return TokError("unassigned file number in '.loc' directive");
+  Lex();
 
+  if (getLexer().isNot(AsmToken::Integer))
+    return TokError("unexpected token in '.loc' directive");
+  int64_t LineNumber = getTok().getIntVal();
+  if (LineNumber < 1)
+    return TokError("line number less than one in '.loc' directive");
   Lex();
-  if (getLexer().isNot(AsmToken::EndOfStatement)) {
-    if (getLexer().isNot(AsmToken::Integer))
-      return TokError("unexpected token in '.loc' directive");
 
-    int64_t Param2 = getTok().getIntVal();
-    (void) Param2;
+  int64_t ColumnPos = 0;
+  if (getLexer().is(AsmToken::Integer)) {
+    ColumnPos = getTok().getIntVal();
+    if (ColumnPos < 0)
+      return TokError("column position less than zero in '.loc' directive");
     Lex();
+  }
 
-    if (getLexer().isNot(AsmToken::EndOfStatement)) {
-      if (getLexer().isNot(AsmToken::Integer))
+  unsigned Flags = 0;
+  unsigned Isa = 0;
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    for (;;) {
+      if (getLexer().is(AsmToken::EndOfStatement))
+        break;
+
+      StringRef Name;
+      SMLoc Loc = getTok().getLoc();
+      if (getParser().ParseIdentifier(Name))
         return TokError("unexpected token in '.loc' directive");
 
-      int64_t Param3 = getTok().getIntVal();
-      (void) Param3;
-      Lex();
+      if (Name == "basic_block")
+        Flags |= DWARF2_FLAG_BASIC_BLOCK;
+      else if (Name == "prologue_end")
+        Flags |= DWARF2_FLAG_PROLOGUE_END;
+      else if (Name == "epilogue_begin")
+        Flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
+      else if (Name == "is_stmt") {
+        SMLoc Loc = getTok().getLoc();
+        const MCExpr *Value;
+        if (getParser().ParseExpression(Value))
+          return true;
+        // The expression must be the constant 0 or 1.
+        if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+          int Value = MCE->getValue();
+          if (Value == 0)
+            Flags &= ~DWARF2_FLAG_IS_STMT;
+          else if (Value == 1)
+            Flags |= DWARF2_FLAG_IS_STMT;
+          else
+            return Error(Loc, "is_stmt value not 0 or 1");
+       }
+        else {
+          return Error(Loc, "is_stmt value not the constant value of 0 or 1");
+        }
+      }
+      else if (Name == "isa") {
+        SMLoc Loc = getTok().getLoc();
+        const MCExpr *Value;
+        if (getParser().ParseExpression(Value))
+          return true;
+        // The expression must be a constant greater or equal to 0.
+        if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
+          int Value = MCE->getValue();
+          if (Value < 0)
+            return Error(Loc, "isa number less than zero");
+          Isa = Value;
+       }
+        else {
+          return Error(Loc, "isa number not a constant value");
+        }
+      }
+      else {
+        return Error(Loc, "unknown sub-directive in '.loc' directive");
+      }
 
-      // FIXME: Do something with the .loc.
+      if (getLexer().is(AsmToken::EndOfStatement))
+        break;
     }
   }
 
-  if (getLexer().isNot(AsmToken::EndOfStatement))
-    return TokError("unexpected token in '.file' directive");
+  getContext().setCurrentDwarfLoc(FileNumber, LineNumber, ColumnPos, Flags,Isa);
 
   return false;
 }