[llvm-commits] [llvm] r74448 - in /llvm/trunk: test/MC/AsmParser/exprs.s tools/llvm-mc/AsmLexer.cpp tools/llvm-mc/AsmLexer.h tools/llvm-mc/AsmParser.cpp tools/llvm-mc/AsmParser.h tools/llvm-mc/MC-X86Specific.cpp

Daniel Dunbar daniel at zuster.org
Mon Jun 29 13:37:28 PDT 2009


Author: ddunbar
Date: Mon Jun 29 15:37:27 2009
New Revision: 74448

URL: http://llvm.org/viewvc/llvm-project?rev=74448&view=rev
Log:
MC: Improve expression parsing and implement evaluation of absolute expressions.

Added:
    llvm/trunk/test/MC/AsmParser/exprs.s
Modified:
    llvm/trunk/tools/llvm-mc/AsmLexer.cpp
    llvm/trunk/tools/llvm-mc/AsmLexer.h
    llvm/trunk/tools/llvm-mc/AsmParser.cpp
    llvm/trunk/tools/llvm-mc/AsmParser.h
    llvm/trunk/tools/llvm-mc/MC-X86Specific.cpp

Added: llvm/trunk/test/MC/AsmParser/exprs.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/exprs.s?rev=74448&view=auto

==============================================================================
--- llvm/trunk/test/MC/AsmParser/exprs.s (added)
+++ llvm/trunk/test/MC/AsmParser/exprs.s Mon Jun 29 15:37:27 2009
@@ -0,0 +1,39 @@
+# FIXME: For now this test just checks that llvm-mc works. Once we have .macro,
+# .if, and .abort we can write a better test (without resorting to miles of
+# greps).
+        
+# RUN: llvm-mc %s > %t
+        
+        .byte !1 + 2
+        .byte !0
+        .byte ~0
+        .byte -1
+        .byte +1
+        .byte 1 + 2
+        .byte 1 & 3
+        .byte 4 / 2
+        .byte 4 / -2
+        .byte 1 == 1
+        .byte 1 == 0
+        .byte 1 > 0
+        .byte 1 >= 1
+        .byte 1 < 2
+        .byte 1 <= 1
+        .byte 4 % 3
+        .byte 2 * 2
+        .byte 2 != 2
+        .byte 2 <> 2
+        .byte 1 | 2
+        .byte 1 << 1
+        .byte 2 >> 1
+        .byte ~0 >> 1
+        .byte 3 - 2
+        .byte 1 ^ 3
+        .byte 1 && 2
+        .byte 3 && 0
+        .byte 1 || 2
+        .byte 0 || 0
+
+        .set c, 10
+        .byte c + 1
+        
\ No newline at end of file

Modified: llvm/trunk/tools/llvm-mc/AsmLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmLexer.cpp?rev=74448&r1=74447&r2=74448&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmLexer.cpp (original)
+++ llvm/trunk/tools/llvm-mc/AsmLexer.cpp Mon Jun 29 15:37:27 2009
@@ -262,11 +262,23 @@
   case '*': return asmtok::Star;
   case ',': return asmtok::Comma;
   case '$': return asmtok::Dollar;
-  case '=': return asmtok::Equal;
-  case '|': return asmtok::Pipe;
+  case '=': 
+    if (*CurPtr == '=')
+      return ++CurPtr, asmtok::EqualEqual;
+    return asmtok::Equal;
+  case '|': 
+    if (*CurPtr == '|')
+      return ++CurPtr, asmtok::PipePipe;
+    return asmtok::Pipe;
   case '^': return asmtok::Caret;
-  case '&': return asmtok::Amp;
-  case '!': return asmtok::Exclaim;
+  case '&': 
+    if (*CurPtr == '&')
+      return ++CurPtr, asmtok::AmpAmp;
+    return asmtok::Amp;
+  case '!': 
+    if (*CurPtr == '=')
+      return ++CurPtr, asmtok::ExclaimEqual;
+    return asmtok::Exclaim;
   case '%': return LexPercent();
   case '/': return LexSlash();
   case '#': return LexHash();
@@ -275,19 +287,18 @@
   case '5': case '6': case '7': case '8': case '9':
     return LexDigit();
   case '<':
-    if (*CurPtr == '<') {
-      ++CurPtr;
-      return asmtok::LessLess;
+    switch (*CurPtr) {
+    case '<': return ++CurPtr, asmtok::LessLess;
+    case '=': return ++CurPtr, asmtok::LessEqual;
+    case '>': return ++CurPtr, asmtok::LessGreater;
+    default: return asmtok::Less;
     }
-    // Don't have any use for bare '<' yet.
-    return ReturnError(TokStart, "invalid character in input");
   case '>':
-    if (*CurPtr == '>') {
-      ++CurPtr;
-      return asmtok::GreaterGreater;
+    switch (*CurPtr) {
+    case '>': return ++CurPtr, asmtok::GreaterGreater;      
+    case '=': return ++CurPtr, asmtok::GreaterEqual;      
+    default: return asmtok::Greater;
     }
-    // Don't have any use for bare '>' yet.
-    return ReturnError(TokStart, "invalid character in input");
       
   // TODO: Quoted identifiers (objc methods etc)
   // local labels: [0-9][:]

Modified: llvm/trunk/tools/llvm-mc/AsmLexer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmLexer.h?rev=74448&r1=74447&r2=74448&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmLexer.h (original)
+++ llvm/trunk/tools/llvm-mc/AsmLexer.h Mon Jun 29 15:37:27 2009
@@ -42,10 +42,12 @@
     Plus, Minus, Tilde,
     Slash,    // '/'
     LParen, RParen,
-    Star, Comma, Dollar, Equal,
+    Star, Comma, Dollar, Equal, EqualEqual,
     
-    Pipe, Caret, Amp, Exclaim,
-    Percent, LessLess, GreaterGreater
+    Pipe, PipePipe, Caret, 
+    Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, 
+    Less, LessEqual, LessLess, LessGreater,
+    Greater, GreaterEqual, GreaterGreater
   };
 }
 

Modified: llvm/trunk/tools/llvm-mc/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmParser.cpp?rev=74448&r1=74447&r2=74448&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmParser.cpp (original)
+++ llvm/trunk/tools/llvm-mc/AsmParser.cpp Mon Jun 29 15:37:27 2009
@@ -12,6 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "AsmParser.h"
+
+#include "AsmExpr.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCStreamer.h"
@@ -57,7 +59,7 @@
 ///
 /// parenexpr ::= expr)
 ///
-bool AsmParser::ParseParenExpr(int64_t &Res) {
+bool AsmParser::ParseParenExpr(AsmExpr *&Res) {
   if (ParseExpression(Res)) return true;
   if (Lexer.isNot(asmtok::RParen))
     return TokError("expected ')' in parentheses expression");
@@ -70,28 +72,47 @@
 ///  primaryexpr ::= symbol
 ///  primaryexpr ::= number
 ///  primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::ParsePrimaryExpr(int64_t &Res) {
+bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) {
   switch (Lexer.getKind()) {
   default:
     return TokError("unknown token in expression");
+  case asmtok::Exclaim:
+    Lexer.Lex(); // Eat the operator.
+    if (ParsePrimaryExpr(Res))
+      return true;
+    Res = new AsmUnaryExpr(AsmUnaryExpr::LNot, Res);
+    return false;
   case asmtok::Identifier:
     // This is a label, this should be parsed as part of an expression, to
-    // handle things like LFOO+4
-    Res = 0; // FIXME.
+    // handle things like LFOO+4.
+    Res = new AsmSymbolRefExpr(Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()));
     Lexer.Lex(); // Eat identifier.
     return false;
   case asmtok::IntVal:
-    Res = Lexer.getCurIntVal();
+    Res = new AsmConstantExpr(Lexer.getCurIntVal());
     Lexer.Lex(); // Eat identifier.
     return false;
   case asmtok::LParen:
     Lexer.Lex(); // Eat the '('.
     return ParseParenExpr(Res);
-  case asmtok::Tilde:
-  case asmtok::Plus:
   case asmtok::Minus:
     Lexer.Lex(); // Eat the operator.
-    return ParsePrimaryExpr(Res);
+    if (ParsePrimaryExpr(Res))
+      return true;
+    Res = new AsmUnaryExpr(AsmUnaryExpr::Minus, Res);
+    return false;
+  case asmtok::Plus:
+    Lexer.Lex(); // Eat the operator.
+    if (ParsePrimaryExpr(Res))
+      return true;
+    Res = new AsmUnaryExpr(AsmUnaryExpr::Plus, Res);
+    return false;
+  case asmtok::Tilde:
+    Lexer.Lex(); // Eat the operator.
+    if (ParsePrimaryExpr(Res))
+      return true;
+    Res = new AsmUnaryExpr(AsmUnaryExpr::Not, Res);
+    return false;
   }
 }
 
@@ -102,59 +123,125 @@
 ///  expr ::= expr *,/,%,<<,>> expr  -> highest.
 ///  expr ::= primaryexpr
 ///
-bool AsmParser::ParseExpression(int64_t &Res) {
+bool AsmParser::ParseExpression(AsmExpr *&Res) {
+  Res = 0;
   return ParsePrimaryExpr(Res) ||
          ParseBinOpRHS(1, Res);
 }
 
-static unsigned getBinOpPrecedence(asmtok::TokKind K) {
+bool AsmParser::ParseAbsoluteExpression(int64_t &Res) {
+  AsmExpr *Expr;
+  
+  if (ParseExpression(Expr))
+    return true;
+
+  if (!Expr->EvaluateAsAbsolute(Ctx, Res))
+    return TokError("expected absolute expression");
+
+  return false;
+}
+
+static unsigned getBinOpPrecedence(asmtok::TokKind K, 
+                                   AsmBinaryExpr::Opcode &Kind) {
   switch (K) {
   default: return 0;    // not a binop.
+
+    // Lowest Precedence: &&, ||
+  case asmtok::AmpAmp:
+    Kind = AsmBinaryExpr::LAnd;
+    return 1;
+  case asmtok::PipePipe:
+    Kind = AsmBinaryExpr::LOr;
+    return 1;
+
+    // Low Precedence: +, -, ==, !=, <>, <, <=, >, >=
   case asmtok::Plus:
+    Kind = AsmBinaryExpr::Add;
+    return 2;
   case asmtok::Minus:
-    return 1;
+    Kind = AsmBinaryExpr::Sub;
+    return 2;
+  case asmtok::EqualEqual:
+    Kind = AsmBinaryExpr::EQ;
+    return 2;
+  case asmtok::ExclaimEqual:
+  case asmtok::LessGreater:
+    Kind = AsmBinaryExpr::NE;
+    return 2;
+  case asmtok::Less:
+    Kind = AsmBinaryExpr::LT;
+    return 2;
+  case asmtok::LessEqual:
+    Kind = AsmBinaryExpr::LTE;
+    return 2;
+  case asmtok::Greater:
+    Kind = AsmBinaryExpr::GT;
+    return 2;
+  case asmtok::GreaterEqual:
+    Kind = AsmBinaryExpr::GTE;
+    return 2;
+
+    // Intermediate Precedence: |, &, ^
+    //
+    // FIXME: gas seems to support '!' as an infix operator?
   case asmtok::Pipe:
+    Kind = AsmBinaryExpr::Or;
+    return 3;
   case asmtok::Caret:
+    Kind = AsmBinaryExpr::Xor;
+    return 3;
   case asmtok::Amp:
-  case asmtok::Exclaim:
-    return 2;
+    Kind = AsmBinaryExpr::And;
+    return 3;
+
+    // Highest Precedence: *, /, %, <<, >>
   case asmtok::Star:
+    Kind = AsmBinaryExpr::Mul;
+    return 4;
   case asmtok::Slash:
+    Kind = AsmBinaryExpr::Div;
+    return 4;
   case asmtok::Percent:
+    Kind = AsmBinaryExpr::Mod;
+    return 4;
   case asmtok::LessLess:
+    Kind = AsmBinaryExpr::Shl;
+    return 4;
   case asmtok::GreaterGreater:
-    return 3;
+    Kind = AsmBinaryExpr::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, int64_t &Res) {
+bool AsmParser::ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res) {
   while (1) {
-    unsigned TokPrec = getBinOpPrecedence(Lexer.getKind());
+    AsmBinaryExpr::Opcode Kind;
+    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;
     
-    //asmtok::TokKind BinOp = Lexer.getKind();
     Lexer.Lex();
     
     // Eat the next primary expression.
-    int64_t RHS;
+    AsmExpr *RHS;
     if (ParsePrimaryExpr(RHS)) return true;
     
     // If BinOp binds less tightly with RHS than the operator after RHS, let
     // the pending operator take RHS as its LHS.
-    unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind());
+    AsmBinaryExpr::Opcode Dummy;
+    unsigned NextTokPrec = getBinOpPrecedence(Lexer.getKind(), Dummy);
     if (TokPrec < NextTokPrec) {
       if (ParseBinOpRHS(Precedence+1, RHS)) return true;
     }
 
-    // Merge LHS/RHS: fixme use the right operator etc.
-    Res += RHS;
+    // Merge LHS and RHS according to operator.
+    Res = new AsmBinaryExpr(Kind, Res, RHS);
   }
 }
 
@@ -354,7 +441,7 @@
 
 bool AsmParser::ParseAssignment(const char *Name, bool IsDotSet) {
   int64_t Value;
-  if (ParseExpression(Value))
+  if (ParseAbsoluteExpression(Value))
     return true;
   
   if (Lexer.isNot(asmtok::EndOfStatement))
@@ -433,7 +520,7 @@
 }
 
 /// ParseDirectiveAscii:
-///   ::= ( .ascii | .asciiz ) [ "string" ( , "string" )* ]
+///   ::= ( .ascii | .asciz ) [ "string" ( , "string" )* ]
 bool AsmParser::ParseDirectiveAscii(bool ZeroTerminated) {
   if (Lexer.isNot(asmtok::EndOfStatement)) {
     for (;;) {
@@ -469,7 +556,7 @@
   if (Lexer.isNot(asmtok::EndOfStatement)) {
     for (;;) {
       int64_t Expr;
-      if (ParseExpression(Expr))
+      if (ParseAbsoluteExpression(Expr))
         return true;
 
       Out.EmitValue(MCValue::get(Expr), Size);
@@ -492,7 +579,7 @@
 ///  ::= .space expression [ , expression ]
 bool AsmParser::ParseDirectiveSpace() {
   int64_t NumBytes;
-  if (ParseExpression(NumBytes))
+  if (ParseAbsoluteExpression(NumBytes))
     return true;
 
   int64_t FillExpr = 0;
@@ -502,7 +589,7 @@
       return TokError("unexpected token in '.space' directive");
     Lexer.Lex();
     
-    if (ParseExpression(FillExpr))
+    if (ParseAbsoluteExpression(FillExpr))
       return true;
 
     HasFillExpr = true;
@@ -527,7 +614,7 @@
 ///  ::= .fill expression , expression , expression
 bool AsmParser::ParseDirectiveFill() {
   int64_t NumValues;
-  if (ParseExpression(NumValues))
+  if (ParseAbsoluteExpression(NumValues))
     return true;
 
   if (Lexer.isNot(asmtok::Comma))
@@ -535,7 +622,7 @@
   Lexer.Lex();
   
   int64_t FillSize;
-  if (ParseExpression(FillSize))
+  if (ParseAbsoluteExpression(FillSize))
     return true;
 
   if (Lexer.isNot(asmtok::Comma))
@@ -543,7 +630,7 @@
   Lexer.Lex();
   
   int64_t FillExpr;
-  if (ParseExpression(FillExpr))
+  if (ParseAbsoluteExpression(FillExpr))
     return true;
 
   if (Lexer.isNot(asmtok::EndOfStatement))
@@ -564,7 +651,7 @@
 ///  ::= .org expression [ , expression ]
 bool AsmParser::ParseDirectiveOrg() {
   int64_t Offset;
-  if (ParseExpression(Offset))
+  if (ParseAbsoluteExpression(Offset))
     return true;
 
   // Parse optional fill expression.
@@ -574,7 +661,7 @@
       return TokError("unexpected token in '.org' directive");
     Lexer.Lex();
     
-    if (ParseExpression(FillExpr))
+    if (ParseAbsoluteExpression(FillExpr))
       return true;
 
     if (Lexer.isNot(asmtok::EndOfStatement))

Modified: llvm/trunk/tools/llvm-mc/AsmParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/AsmParser.h?rev=74448&r1=74447&r2=74448&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/AsmParser.h (original)
+++ llvm/trunk/tools/llvm-mc/AsmParser.h Mon Jun 29 15:37:27 2009
@@ -17,6 +17,7 @@
 #include "AsmLexer.h"
 
 namespace llvm {
+class AsmExpr;
 class MCContext;
 class MCInst;
 class MCStreamer;
@@ -44,10 +45,24 @@
   void EatToEndOfStatement();
   
   bool ParseAssignment(const char *Name, bool IsDotSet);
-  bool ParseExpression(int64_t &Res);
-  bool ParsePrimaryExpr(int64_t &Res);
-  bool ParseBinOpRHS(unsigned Precedence, int64_t &Res);
-  bool ParseParenExpr(int64_t &Res);
+
+  /// ParseExpression - Parse a general assembly expression.
+  ///
+  /// @param Res - The resulting expression. The pointer value is null on error.
+  /// @result - False on success.
+  bool ParseExpression(AsmExpr *&Res);
+  
+  /// ParseAbsoluteExpr - Parse an expression which must evaluate to an absolute
+  /// value.
+  ///
+  /// @param Res - The value of the absolute expression. The result is undefined
+  /// on error.
+  /// @result - False on success.
+  bool ParseAbsoluteExpression(int64_t &Res);
+
+  bool ParsePrimaryExpr(AsmExpr *&Res);
+  bool ParseBinOpRHS(unsigned Precedence, AsmExpr *&Res);
+  bool ParseParenExpr(AsmExpr *&Res);
   
   // X86 specific.
   bool ParseX86InstOperands(MCInst &Inst);

Modified: llvm/trunk/tools/llvm-mc/MC-X86Specific.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mc/MC-X86Specific.cpp?rev=74448&r1=74447&r2=74448&view=diff

==============================================================================
--- llvm/trunk/tools/llvm-mc/MC-X86Specific.cpp (original)
+++ llvm/trunk/tools/llvm-mc/MC-X86Specific.cpp Mon Jun 29 15:37:27 2009
@@ -87,7 +87,7 @@
     // $42 -> immediate.
     Lexer.Lex();
     int64_t Val;
-    if (ParseExpression(Val))
+    if (ParseAbsoluteExpression(Val))
       return TokError("expected integer constant");
     Op = X86Operand::CreateReg(Val);
     return false;
@@ -118,7 +118,7 @@
   // it.
   int64_t Disp = 0;
   if (Lexer.isNot(asmtok::LParen)) {
-    if (ParseExpression(Disp)) return true;
+    if (ParseAbsoluteExpression(Disp)) return true;
     
     // After parsing the base expression we could either have a parenthesized
     // memory address or not.  If not, return now.  If so, eat the (.
@@ -139,8 +139,7 @@
       // memory operand consumed.
     } else {
       // It must be an parenthesized expression, parse it now.
-      if (ParseParenExpr(Disp) ||
-          ParseBinOpRHS(1, Disp))
+      if (ParseAbsoluteExpression(Disp))
         return true;
       
       // After parsing the base expression we could either have a parenthesized





More information about the llvm-commits mailing list