#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"
class MCSymbol;
class MCLabel;
class MCDwarfFile;
+ class MCDwarfLoc;
class StringRef;
class Twine;
class MCSectionMachO;
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
/// 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;
}
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; }
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;
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;
SecureLogFile = getenv("AS_SECURE_LOG_FILE");
SecureLog = 0;
SecureLogUsed = false;
+
+ DwarfLocSeen = false;
}
MCContext::~MCContext() {
// 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;
+}
/// 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;
}