diff options
Diffstat (limited to 'tools/llvm-mc')
-rw-r--r-- | tools/llvm-mc/AsmCond.h | 40 | ||||
-rw-r--r-- | tools/llvm-mc/AsmLexer.cpp | 304 | ||||
-rw-r--r-- | tools/llvm-mc/AsmLexer.h | 72 | ||||
-rw-r--r-- | tools/llvm-mc/AsmParser.cpp | 1782 | ||||
-rw-r--r-- | tools/llvm-mc/AsmParser.h | 178 | ||||
-rw-r--r-- | tools/llvm-mc/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tools/llvm-mc/llvm-mc.cpp | 2 |
7 files changed, 1 insertions, 2379 deletions
diff --git a/tools/llvm-mc/AsmCond.h b/tools/llvm-mc/AsmCond.h deleted file mode 100644 index 92a115eb80..0000000000 --- a/tools/llvm-mc/AsmCond.h +++ /dev/null @@ -1,40 +0,0 @@ -//===- AsmCond.h - Assembly file conditional assembly ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef ASMCOND_H -#define ASMCOND_H - -namespace llvm { - -/// AsmCond - Class to support conditional assembly -/// -/// The conditional assembly feature (.if, .else, .elseif and .endif) is -/// implemented with AsmCond that tells us what we are in the middle of -/// processing. Ignore can be either true or false. When true we are ignoring -/// the block of code in the middle of a conditional. - -class AsmCond { -public: - enum ConditionalAssemblyType { - NoCond, // no conditional is being processed - IfCond, // inside if conditional - ElseIfCond, // inside elseif conditional - ElseCond // inside else conditional - }; - - ConditionalAssemblyType TheCond; - bool CondMet; - bool Ignore; - - AsmCond() : TheCond(NoCond), CondMet(false), Ignore(false) {} -}; - -} // end namespace llvm - -#endif diff --git a/tools/llvm-mc/AsmLexer.cpp b/tools/llvm-mc/AsmLexer.cpp deleted file mode 100644 index de61e7f5b7..0000000000 --- a/tools/llvm-mc/AsmLexer.cpp +++ /dev/null @@ -1,304 +0,0 @@ -//===- AsmLexer.cpp - Lexer for Assembly Files ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class implements the lexer for assembly files. -// -//===----------------------------------------------------------------------===// - -#include "AsmLexer.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/MC/MCAsmInfo.h" -#include <cerrno> -#include <cstdio> -#include <cstdlib> -using namespace llvm; - -AsmLexer::AsmLexer(const MCAsmInfo &_MAI) : MAI(_MAI) { - CurBuf = NULL; - CurPtr = NULL; - TokStart = 0; -} - -AsmLexer::~AsmLexer() { -} - -void AsmLexer::setBuffer(const MemoryBuffer *buf, const char *ptr) { - CurBuf = buf; - - if (ptr) - CurPtr = ptr; - else - CurPtr = CurBuf->getBufferStart(); - - TokStart = 0; -} - -SMLoc AsmLexer::getLoc() const { - return SMLoc::getFromPointer(TokStart); -} - -/// ReturnError - Set the error to the specified string at the specified -/// location. This is defined to always return AsmToken::Error. -AsmToken AsmLexer::ReturnError(const char *Loc, const std::string &Msg) { - SetError(SMLoc::getFromPointer(Loc), Msg); - - return AsmToken(AsmToken::Error, StringRef(Loc, 0)); -} - -int AsmLexer::getNextChar() { - char CurChar = *CurPtr++; - switch (CurChar) { - default: - return (unsigned char)CurChar; - case 0: - // A nul character in the stream is either the end of the current buffer or - // a random nul in the file. Disambiguate that here. - if (CurPtr-1 != CurBuf->getBufferEnd()) - return 0; // Just whitespace. - - // Otherwise, return end of file. - --CurPtr; // Another call to lex will return EOF again. - return EOF; - } -} - -/// LexIdentifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* -AsmToken AsmLexer::LexIdentifier() { - while (isalnum(*CurPtr) || *CurPtr == '_' || *CurPtr == '$' || - *CurPtr == '.' || *CurPtr == '@') - ++CurPtr; - return AsmToken(AsmToken::Identifier, StringRef(TokStart, CurPtr - TokStart)); -} - -/// LexSlash: Slash: / -/// C-Style Comment: /* ... */ -AsmToken AsmLexer::LexSlash() { - switch (*CurPtr) { - case '*': break; // C style comment. - case '/': return ++CurPtr, LexLineComment(); - default: return AsmToken(AsmToken::Slash, StringRef(CurPtr, 1)); - } - - // C Style comment. - ++CurPtr; // skip the star. - while (1) { - int CurChar = getNextChar(); - switch (CurChar) { - case EOF: - return ReturnError(TokStart, "unterminated comment"); - case '*': - // End of the comment? - if (CurPtr[0] != '/') break; - - ++CurPtr; // End the */. - return LexToken(); - } - } -} - -/// LexLineComment: Comment: #[^\n]* -/// : //[^\n]* -AsmToken AsmLexer::LexLineComment() { - // FIXME: This is broken if we happen to a comment at the end of a file, which - // was .included, and which doesn't end with a newline. - int CurChar = getNextChar(); - while (CurChar != '\n' && CurChar != '\n' && CurChar != EOF) - CurChar = getNextChar(); - - if (CurChar == EOF) - return AsmToken(AsmToken::Eof, StringRef(CurPtr, 0)); - return AsmToken(AsmToken::EndOfStatement, StringRef(CurPtr, 0)); -} - - -/// LexDigit: First character is [0-9]. -/// Local Label: [0-9][:] -/// Forward/Backward Label: [0-9][fb] -/// Binary integer: 0b[01]+ -/// Octal integer: 0[0-7]+ -/// Hex integer: 0x[0-9a-fA-F]+ -/// Decimal integer: [1-9][0-9]* -/// TODO: FP literal. -AsmToken AsmLexer::LexDigit() { - if (*CurPtr == ':') - return ReturnError(TokStart, "FIXME: local label not implemented"); - if (*CurPtr == 'f' || *CurPtr == 'b') - return ReturnError(TokStart, "FIXME: directional label not implemented"); - - // Decimal integer: [1-9][0-9]* - if (CurPtr[-1] != '0') { - while (isdigit(*CurPtr)) - ++CurPtr; - return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), - strtoll(TokStart, 0, 10)); - } - - if (*CurPtr == 'b') { - ++CurPtr; - const char *NumStart = CurPtr; - while (CurPtr[0] == '0' || CurPtr[0] == '1') - ++CurPtr; - - // Requires at least one binary digit. - if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid binary number"); - return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), - strtoll(NumStart, 0, 2)); - } - - if (*CurPtr == 'x') { - ++CurPtr; - const char *NumStart = CurPtr; - while (isxdigit(CurPtr[0])) - ++CurPtr; - - // Requires at least one hex digit. - if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid hexadecimal number"); - - unsigned long long Result; - if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) - return ReturnError(CurPtr-2, "Invalid hexadecimal number"); - - return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), - (int64_t)Result); - } - - // Must be an octal number, it starts with 0. - while (*CurPtr >= '0' && *CurPtr <= '7') - ++CurPtr; - return AsmToken(AsmToken::Integer, StringRef(TokStart, CurPtr - TokStart), - strtoll(TokStart, 0, 8)); -} - -/// LexQuote: String: "..." -AsmToken AsmLexer::LexQuote() { - int CurChar = getNextChar(); - // TODO: does gas allow multiline string constants? - while (CurChar != '"') { - if (CurChar == '\\') { - // Allow \", etc. - CurChar = getNextChar(); - } - - if (CurChar == EOF) - return ReturnError(TokStart, "unterminated string constant"); - - CurChar = getNextChar(); - } - - return AsmToken(AsmToken::String, StringRef(TokStart, CurPtr - TokStart)); -} - -StringRef AsmLexer::LexUntilEndOfStatement() { - TokStart = CurPtr; - - while (!isAtStartOfComment(*CurPtr) && // Start of line comment. - *CurPtr != ';' && // End of statement marker. - *CurPtr != '\n' && - *CurPtr != '\r' && - (*CurPtr != 0 || CurPtr != CurBuf->getBufferEnd())) { - ++CurPtr; - } - return StringRef(TokStart, CurPtr-TokStart); -} - -bool AsmLexer::isAtStartOfComment(char Char) { - // FIXME: This won't work for multi-character comment indicators like "//". - return Char == *MAI.getCommentString(); -} - -AsmToken AsmLexer::LexToken() { - TokStart = CurPtr; - // This always consumes at least one character. - int CurChar = getNextChar(); - - if (isAtStartOfComment(CurChar)) - return LexLineComment(); - - switch (CurChar) { - default: - // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]* - if (isalpha(CurChar) || CurChar == '_' || CurChar == '.') - return LexIdentifier(); - - // Unknown character, emit an error. - return ReturnError(TokStart, "invalid character in input"); - case EOF: return AsmToken(AsmToken::Eof, StringRef(TokStart, 0)); - case 0: - case ' ': - case '\t': - // Ignore whitespace. - return LexToken(); - case '\n': // FALL THROUGH. - case '\r': // FALL THROUGH. - case ';': return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1)); - case ':': return AsmToken(AsmToken::Colon, StringRef(TokStart, 1)); - case '+': return AsmToken(AsmToken::Plus, StringRef(TokStart, 1)); - case '-': return AsmToken(AsmToken::Minus, StringRef(TokStart, 1)); - case '~': return AsmToken(AsmToken::Tilde, StringRef(TokStart, 1)); - case '(': return AsmToken(AsmToken::LParen, StringRef(TokStart, 1)); - case ')': return AsmToken(AsmToken::RParen, StringRef(TokStart, 1)); - case '[': return AsmToken(AsmToken::LBrac, StringRef(TokStart, 1)); - case ']': return AsmToken(AsmToken::RBrac, StringRef(TokStart, 1)); - case '{': return AsmToken(AsmToken::LCurly, StringRef(TokStart, 1)); - case '}': return AsmToken(AsmToken::RCurly, StringRef(TokStart, 1)); - case '*': return AsmToken(AsmToken::Star, StringRef(TokStart, 1)); - case ',': return AsmToken(AsmToken::Comma, StringRef(TokStart, 1)); - case '$': return AsmToken(AsmToken::Dollar, StringRef(TokStart, 1)); - case '=': - if (*CurPtr == '=') - return ++CurPtr, AsmToken(AsmToken::EqualEqual, StringRef(TokStart, 2)); - return AsmToken(AsmToken::Equal, StringRef(TokStart, 1)); - case '|': - if (*CurPtr == '|') - return ++CurPtr, AsmToken(AsmToken::PipePipe, StringRef(TokStart, 2)); - return AsmToken(AsmToken::Pipe, StringRef(TokStart, 1)); - case '^': return AsmToken(AsmToken::Caret, StringRef(TokStart, 1)); - case '&': - if (*CurPtr == '&') - return ++CurPtr, AsmToken(AsmToken::AmpAmp, StringRef(TokStart, 2)); - return AsmToken(AsmToken::Amp, StringRef(TokStart, 1)); - case '!': - if (*CurPtr == '=') - return ++CurPtr, AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2)); - return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1)); - case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1)); - case '/': return LexSlash(); - case '#': return AsmToken(AsmToken::Hash, StringRef(TokStart, 1)); - case '"': return LexQuote(); - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return LexDigit(); - case '<': - switch (*CurPtr) { - case '<': return ++CurPtr, AsmToken(AsmToken::LessLess, - StringRef(TokStart, 2)); - case '=': return ++CurPtr, AsmToken(AsmToken::LessEqual, - StringRef(TokStart, 2)); - case '>': return ++CurPtr, AsmToken(AsmToken::LessGreater, - StringRef(TokStart, 2)); - default: return AsmToken(AsmToken::Less, StringRef(TokStart, 1)); - } - case '>': - switch (*CurPtr) { - case '>': return ++CurPtr, AsmToken(AsmToken::GreaterGreater, - StringRef(TokStart, 2)); - case '=': return ++CurPtr, AsmToken(AsmToken::GreaterEqual, - StringRef(TokStart, 2)); - default: return AsmToken(AsmToken::Greater, StringRef(TokStart, 1)); - } - - // TODO: Quoted identifiers (objc methods etc) - // local labels: [0-9][:] - // Forward/backward labels: [0-9][fb] - // Integers, fp constants, character constants. - } -} diff --git a/tools/llvm-mc/AsmLexer.h b/tools/llvm-mc/AsmLexer.h deleted file mode 100644 index cf6eefb408..0000000000 --- a/tools/llvm-mc/AsmLexer.h +++ /dev/null @@ -1,72 +0,0 @@ -//===- AsmLexer.h - Lexer for Assembly Files --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class declares the lexer for assembly files. -// -//===----------------------------------------------------------------------===// - -#ifndef ASMLEXER_H -#define ASMLEXER_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCParser/MCAsmLexer.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/System/DataTypes.h" -#include <string> -#include <cassert> - -namespace llvm { -class MemoryBuffer; -class SMLoc; -class MCAsmInfo; - -/// AsmLexer - Lexer class for assembly files. -class AsmLexer : public MCAsmLexer { - const MCAsmInfo &MAI; - - const char *CurPtr; - const MemoryBuffer *CurBuf; - - const char *TokStart; - - void operator=(const AsmLexer&); // DO NOT IMPLEMENT - AsmLexer(const AsmLexer&); // DO NOT IMPLEMENT - -protected: - /// LexToken - Read the next token and return its code. - virtual AsmToken LexToken(); - -public: - AsmLexer(const MCAsmInfo &MAI); - ~AsmLexer(); - - void setBuffer(const MemoryBuffer *buf, const char *ptr = NULL); - - SMLoc getLoc() const; - - StringRef LexUntilEndOfStatement(); - - bool isAtStartOfComment(char Char); - - const MCAsmInfo &getMAI() const { return MAI; } - -private: - int getNextChar(); - AsmToken ReturnError(const char *Loc, const std::string &Msg); - - AsmToken LexIdentifier(); - AsmToken LexSlash(); - AsmToken LexLineComment(); - AsmToken LexDigit(); - AsmToken LexQuote(); -}; - -} // end namespace llvm - -#endif diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp deleted file mode 100644 index 503addb5e6..0000000000 --- a/tools/llvm-mc/AsmParser.cpp +++ /dev/null @@ -1,1782 +0,0 @@ -//===- AsmParser.cpp - Parser for Assembly Files --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class implements the parser for assembly files. -// -//===----------------------------------------------------------------------===// - -#include "AsmParser.h" - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCValue.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetAsmParser.h" -using namespace llvm; - - -enum { DEFAULT_ADDRSPACE = 0 }; - -// Mach-O section uniquing. -// -// FIXME: Figure out where this should live, it should be shared by -// TargetLoweringObjectFile. -typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy; - -AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, - const MCAsmInfo &_MAI) - : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), TargetParser(0), - CurBuffer(0), SectionUniquingMap(0) { - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - - // Debugging directives. - AddDirectiveHandler(".file", &AsmParser::ParseDirectiveFile); - AddDirectiveHandler(".line", &AsmParser::ParseDirectiveLine); - AddDirectiveHandler(".loc", &AsmParser::ParseDirectiveLoc); -} - - - -AsmParser::~AsmParser() { - // If we have the MachO uniquing map, free it. - delete (MachOUniqueMapTy*)SectionUniquingMap; -} - -const MCSection *AsmParser::getMachOSection(const StringRef &Segment, - const StringRef &Section, - unsigned TypeAndAttributes, - unsigned Reserved2, - SectionKind Kind) const { - // We unique sections by their segment/section pair. The returned section - // may not have the same flags as the requested section, if so this should be - // diagnosed by the client as an error. - - // Create the map if it doesn't already exist. - if (SectionUniquingMap == 0) - SectionUniquingMap = new MachOUniqueMapTy(); - MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)SectionUniquingMap; - - // Form the name to look up. - SmallString<64> Name; - Name += Segment; - Name.push_back(','); - Name += Section; - - // Do the lookup, if we have a hit, return it. - const MCSectionMachO *&Entry = Map[Name.str()]; - - // FIXME: This should validate the type and attributes. - if (Entry) return Entry; - - // Otherwise, return a new section. - return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, - Reserved2, Kind, Ctx); -} - -void AsmParser::Warning(SMLoc L, const Twine &Msg) { - PrintMessage(L, Msg.str(), "warning"); -} - -bool AsmParser::Error(SMLoc L, const Twine &Msg) { - PrintMessage(L, Msg.str(), "error"); - return true; -} - -bool AsmParser::TokError(const char *Msg) { - PrintMessage(Lexer.getLoc(), Msg, "error"); - return true; -} - -void AsmParser::PrintMessage(SMLoc Loc, const std::string &Msg, - const char *Type) const { - SrcMgr.PrintMessage(Loc, Msg, Type); -} - -bool AsmParser::EnterIncludeFile(const std::string &Filename) { - int NewBuf = SrcMgr.AddIncludeFile(Filename, Lexer.getLoc()); - if (NewBuf == -1) - return true; - - CurBuffer = NewBuf; - - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); - - return false; -} - -const AsmToken &AsmParser::Lex() { - const AsmToken *tok = &Lexer.Lex(); - - if (tok->is(AsmToken::Eof)) { - // If this is the end of an included file, pop the parent file off the - // include stack. - SMLoc ParentIncludeLoc = SrcMgr.getParentIncludeLoc(CurBuffer); - if (ParentIncludeLoc != SMLoc()) { - CurBuffer = SrcMgr.FindBufferContainingLoc(ParentIncludeLoc); - Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer), - ParentIncludeLoc.getPointer()); - tok = &Lexer.Lex(); - } - } - - if (tok->is(AsmToken::Error)) - PrintMessage(Lexer.getErrLoc(), Lexer.getErr(), "error"); - - return *tok; -} - -bool AsmParser::Run() { - // Create the initial section. - // - // FIXME: Support -n. - // FIXME: Target hook & command line option for initial section. - Out.SwitchSection(getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, SectionKind())); - - - // Prime the lexer. - Lex(); - - bool HadError = false; - - AsmCond StartingCondState = TheCondState; - - // While we have input, parse each statement. - while (Lexer.isNot(AsmToken::Eof)) { - // Handle conditional assembly here before calling ParseStatement() - if (Lexer.getKind() == AsmToken::Identifier) { - // If we have an identifier, handle it as the key symbol. - AsmToken ID = getTok(); - SMLoc IDLoc = ID.getLoc(); - StringRef IDVal = ID.getString(); - - if (IDVal == ".if" || - IDVal == ".elseif" || - IDVal == ".else" || - IDVal == ".endif") { - if (!ParseConditionalAssemblyDirectives(IDVal, IDLoc)) - continue; - HadError = true; - EatToEndOfStatement(); - continue; - } - } - if (TheCondState.Ignore) { - EatToEndOfStatement(); - continue; - } - - if (!ParseStatement()) continue; - - // We had an error, remember it and recover by skipping to the next line. - HadError = true; - EatToEndOfStatement(); - } - - if (TheCondState.TheCond != StartingCondState.TheCond || - TheCondState.Ignore != StartingCondState.Ignore) - return TokError("unmatched .ifs or .elses"); - - if (!HadError) - Out.Finish(); - - return HadError; -} - -/// ParseConditionalAssemblyDirectives - parse the conditional assembly -/// directives -bool AsmParser::ParseConditionalAssemblyDirectives(StringRef Directive, - SMLoc DirectiveLoc) { - if (Directive == ".if") - return ParseDirectiveIf(DirectiveLoc); - if (Directive == ".elseif") - return ParseDirectiveElseIf(DirectiveLoc); - if (Directive == ".else") - return ParseDirectiveElse(DirectiveLoc); - if (Directive == ".endif") - return ParseDirectiveEndIf(DirectiveLoc); - return true; -} - -/// EatToEndOfStatement - Throw away the rest of the line for testing purposes. -void AsmParser::EatToEndOfStatement() { - while (Lexer.isNot(AsmToken::EndOfStatement) && - Lexer.isNot(AsmToken::Eof)) - Lex(); - - // Eat EOL. - if (Lexer.is(AsmToken::EndOfStatement)) - Lex(); -} - - -/// ParseParenExpr - Parse a paren expression and return it. -/// NOTE: This assumes the leading '(' has already been consumed. -/// -/// parenexpr ::= expr) -/// -bool AsmParser::ParseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) { - if (ParseExpression(Res)) return true; - if (Lexer.isNot(AsmToken::RParen)) - return TokError("expected ')' in parentheses expression"); - EndLoc = Lexer.getLoc(); - Lex(); - return false; -} - -MCSymbol *AsmParser::CreateSymbol(StringRef Name) { - if (MCSymbol *S = Ctx.LookupSymbol(Name)) - return S; - - // If the label starts with L it is an assembler temporary label. - if (Name.startswith("L")) - return Ctx.CreateTemporarySymbol(Name); - - return Ctx.CreateSymbol(Name); -} - -/// ParsePrimaryExpr - Parse a primary expression and return it. -/// primaryexpr ::= (parenexpr -/// primaryexpr ::= symbol -/// primaryexpr ::= number -/// primaryexpr ::= ~,+,- primaryexpr -bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { - switch (Lexer.getKind()) { - default: - return TokError("unknown token in expression"); - case AsmToken::Exclaim: - Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::CreateLNot(Res, getContext()); - return false; - case AsmToken::String: - case AsmToken::Identifier: { - // This is a symbol reference. - MCSymbol *Sym = CreateSymbol(getTok().getIdentifier()); - EndLoc = Lexer.getLoc(); - Lex(); // Eat identifier. - - // If this is an absolute variable reference, substitute it now to preserve - // semantics in the face of reassignment. - if (Sym->getValue() && isa<MCConstantExpr>(Sym->getValue())) { - Res = Sym->getValue(); - return false; - } - - // Otherwise create a symbol ref. - Res = MCSymbolRefExpr::Create(Sym, getContext()); - return false; - } - case AsmToken::Integer: - Res = MCConstantExpr::Create(getTok().getIntVal(), getContext()); - EndLoc = Lexer.getLoc(); - Lex(); // Eat token. - return false; - case AsmToken::LParen: - Lex(); // Eat the '('. - return ParseParenExpr(Res, EndLoc); - case AsmToken::Minus: - Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::CreateMinus(Res, getContext()); - return false; - case AsmToken::Plus: - Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::CreatePlus(Res, getContext()); - return false; - case AsmToken::Tilde: - Lex(); // Eat the operator. - if (ParsePrimaryExpr(Res, EndLoc)) - return true; - Res = MCUnaryExpr::CreateNot(Res, getContext()); - return false; - } -} - -bool AsmParser::ParseExpression(const MCExpr *&Res) { - SMLoc EndLoc; - return ParseExpression(Res, EndLoc); -} - -/// ParseExpression - Parse an expression and return it. -/// -/// expr ::= expr +,- expr -> lowest. -/// expr ::= expr |,^,&,! expr -> middle. -/// expr ::= expr *,/,%,<<,>> expr -> highest. -/// expr ::= primaryexpr -/// -bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { - Res = 0; - return ParsePrimaryExpr(Res, EndLoc) || - ParseBinOpRHS(1, Res, EndLoc); -} - -bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { - if (ParseParenExpr(Res, EndLoc)) - return true; - - return false; -} - -bool AsmParser::ParseAbsoluteExpression(int64_t &Res) { - const MCExpr *Expr; - - SMLoc StartLoc = Lexer.getLoc(); - if (ParseExpression(Expr)) - return true; - - if (!Expr->EvaluateAsAbsolute(Res)) - return Error(StartLoc, "expected absolute expression"); - - return false; -} - -static unsigned getBinOpPrecedence(AsmToken::TokenKind K, - MCBinaryExpr::Opcode &Kind) { - switch (K) { - default: - return 0; // not a binop. - - // Lowest Precedence: &&, || - case AsmToken::AmpAmp: - Kind = MCBinaryExpr::LAnd; - return 1; - case AsmToken::PipePipe: - Kind = MCBinaryExpr::LOr; - return 1; - - // Low Precedence: +, -, ==, !=, <>, <, <=, >, >= - case AsmToken::Plus: - Kind = MCBinaryExpr::Add; - return 2; - case AsmToken::Minus: - Kind = MCBinaryExpr::Sub; - return 2; - case AsmToken::EqualEqual: - Kind = MCBinaryExpr::EQ; - return 2; - case AsmToken::ExclaimEqual: - case AsmToken::LessGreater: - Kind = MCBinaryExpr::NE; - return 2; - case AsmToken::Less: - Kind = MCBinaryExpr::LT; - return 2; - case AsmToken::LessEqual: - Kind = MCBinaryExpr::LTE; - return 2; - case AsmToken::Greater: - Kind = MCBinaryExpr::GT; - return 2; - case AsmToken::GreaterEqual: - Kind = MCBinaryExpr::GTE; - return 2; - - // Intermediate Precedence: |, &, ^ - // - // FIXME: gas seems to support '!' as an infix operator? - case AsmToken::Pipe: - Kind = MCBinaryExpr::Or; - return 3; - case AsmToken::Caret: - Kind = MCBinaryExpr::Xor; - return 3; - case AsmToken::Amp: - Kind = MCBinaryExpr::And; - return 3; - - // Highest Precedence: *, /, %, <<, >> - case AsmToken::Star: - Kind = MCBinaryExpr::Mul; - return 4; - case AsmToken::Slash: - Kind = MCBinaryExpr::Div; - return 4; - case AsmToken::Percent: - Kind = MCBinaryExpr::Mod; - return 4; - case AsmToken::LessLess: - Kind = MCBinaryExpr::Shl; - return 4; - case AsmToken::GreaterGreater: - Kind = MCBinaryExpr::Shr; - return 4; - } -} - - -/// ParseBinOpRHS - Parse all binary operators with precedence >= 'Precedence'. -/// Res contains the LHS of the expression on input. -bool AsmParser::ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, - SMLoc &EndLoc) { - while (1) { - MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; - unsigned TokPrec = getBinOpPrecedence(Lexer.getKind(), Kind); - - // If the next token is lower precedence than we are allowed to eat, return - // successfully with what we ate already. - if (TokPrec < Precedence) - return false; - - Lex(); - - // Eat the next primary expression. - const MCExpr *RHS; - if (ParsePrimaryExpr(RHS, EndLoc)) return true; - - // If BinOp binds less tightly with RHS than the operator after RHS, let - // the pending operator take RHS as its LHS. - MCBinaryExpr::Opcode Dummy; - unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy); - if (TokPrec < NextTokPrec) { - if (ParseBinOpRHS(Precedence+1, RHS, EndLoc)) return true; - } - - // Merge LHS and RHS according to operator. - Res = MCBinaryExpr::Create(Kind, Res, RHS, getContext()); - } -} - - - - -/// ParseStatement: -/// ::= EndOfStatement -/// ::= Label* Directive ...Operands... EndOfStatement -/// ::= Label* Identifier OperandList* EndOfStatement -bool AsmParser::ParseStatement() { - if (Lexer.is(AsmToken::EndOfStatement)) { - Lex(); - return false; - } - - // Statements always start with an identifier. - AsmToken ID = getTok(); - SMLoc IDLoc = ID.getLoc(); - StringRef IDVal; - if (ParseIdentifier(IDVal)) - return TokError("unexpected token at start of statement"); - - // FIXME: Recurse on local labels? - - // See what kind of statement we have. - switch (Lexer.getKind()) { - case AsmToken::Colon: { - // identifier ':' -> Label. - Lex(); - - // Diagnose attempt to use a variable as a label. - // - // FIXME: Diagnostics. Note the location of the definition as a label. - // FIXME: This doesn't diagnose assignment to a symbol which has been - // implicitly marked as external. - MCSymbol *Sym = CreateSymbol(IDVal); - if (!Sym->isUndefined()) - return Error(IDLoc, "invalid symbol redefinition"); - - // Emit the label. - Out.EmitLabel(Sym); - - return ParseStatement(); - } - - case AsmToken::Equal: - // identifier '=' ... -> assignment statement - Lex(); - - return ParseAssignment(IDVal); - - default: // Normal instruction or directive. - break; - } - - // Otherwise, we have a normal instruction or directive. - if (IDVal[0] == '.') { - // FIXME: This should be driven based on a hash lookup and callback. - if (IDVal == ".section") - return ParseDirectiveDarwinSection(); - if (IDVal == ".text") - // FIXME: This changes behavior based on the -static flag to the - // assembler. - return ParseDirectiveSectionSwitch("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); - if (IDVal == ".const") - return ParseDirectiveSectionSwitch("__TEXT", "__const"); - if (IDVal == ".static_const") - return ParseDirectiveSectionSwitch("__TEXT", "__static_const"); - if (IDVal == ".cstring") - return ParseDirectiveSectionSwitch("__TEXT","__cstring", - MCSectionMachO::S_CSTRING_LITERALS); - if (IDVal == ".literal4") - return ParseDirectiveSectionSwitch("__TEXT", "__literal4", - MCSectionMachO::S_4BYTE_LITERALS, - 4); - if (IDVal == ".literal8") - return ParseDirectiveSectionSwitch("__TEXT", "__literal8", - MCSectionMachO::S_8BYTE_LITERALS, - 8); - if (IDVal == ".literal16") - return ParseDirectiveSectionSwitch("__TEXT","__literal16", - MCSectionMachO::S_16BYTE_LITERALS, - 16); - if (IDVal == ".constructor") - return ParseDirectiveSectionSwitch("__TEXT","__constructor"); - if (IDVal == ".destructor") - return ParseDirectiveSectionSwitch("__TEXT","__destructor"); - if (IDVal == ".fvmlib_init0") - return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init0"); - if (IDVal == ".fvmlib_init1") - return ParseDirectiveSectionSwitch("__TEXT","__fvmlib_init1"); - - // FIXME: The assembler manual claims that this has the self modify code - // flag, at least on x86-32, but that does not appear to be correct. - if (IDVal == ".symbol_stub") - return ParseDirectiveSectionSwitch("__TEXT","__symbol_stub", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - // FIXME: Different on PPC and ARM. - 0, 16); - // FIXME: PowerPC only? - if (IDVal == ".picsymbol_stub") - return ParseDirectiveSectionSwitch("__TEXT","__picsymbol_stub", - MCSectionMachO::S_SYMBOL_STUBS | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, 26); - if (IDVal == ".data") - return ParseDirectiveSectionSwitch("__DATA", "__data"); - if (IDVal == ".static_data") - return ParseDirectiveSectionSwitch("__DATA", "__static_data"); - - // FIXME: The section names of these two are misspelled in the assembler - // manual. - if (IDVal == ".non_lazy_symbol_pointer") - return ParseDirectiveSectionSwitch("__DATA", "__nl_symbol_ptr", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, - 4); - if (IDVal == ".lazy_symbol_pointer") - return ParseDirectiveSectionSwitch("__DATA", "__la_symbol_ptr", - MCSectionMachO::S_LAZY_SYMBOL_POINTERS, - 4); - - if (IDVal == ".dyld") - return ParseDirectiveSectionSwitch("__DATA", "__dyld"); - if (IDVal == ".mod_init_func") - return ParseDirectiveSectionSwitch("__DATA", "__mod_init_func", - MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, - 4); - if (IDVal == ".mod_term_func") - return ParseDirectiveSectionSwitch("__DATA", "__mod_term_func", - MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, - 4); |