[llvm-commits] [llvm] r114154 - in /llvm/trunk: lib/MC/MCParser/AsmParser.cpp test/MC/AsmParser/expr_symbol_modifiers.s

Daniel Dunbar daniel at zuster.org
Thu Sep 16 19:47:07 PDT 2010


Author: ddunbar
Date: Thu Sep 16 21:47:07 2010
New Revision: 114154

URL: http://llvm.org/viewvc/llvm-project?rev=114154&view=rev
Log:
MC/AsmParser: Add support for 'a + 4 at GOTPCREL' and friends, by reconsing the
expression to include the modifier.
 - Gross, but this a corner case we don't expect to see often in practice, but
   it is worth accepting.
 - Also improves diagnostics on invalid modifiers.

Added:
    llvm/trunk/test/MC/AsmParser/expr_symbol_modifiers.s
Modified:
    llvm/trunk/lib/MC/MCParser/AsmParser.cpp

Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=114154&r1=114153&r2=114154&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Thu Sep 16 21:47:07 2010
@@ -204,6 +204,9 @@
   /// ParseEscapedString - Parse the current token as a string which may include
   /// escaped characters and return the string contents.
   bool ParseEscapedString(std::string &Data);
+
+  const MCExpr *ApplyModifierToExpr(const MCExpr *E,
+                                    MCSymbolRefExpr::VariantKind Variant);
 };
 
 /// \brief Generic implementations of directive handling, etc. which is shared
@@ -485,8 +488,13 @@
 
     // Lookup the symbol variant if used.
     MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
-    if (Split.first.size() != Identifier.size())
+    if (Split.first.size() != Identifier.size()) {
       Variant = MCSymbolRefExpr::getVariantKindForName(Split.second);
+      if (Variant == MCSymbolRefExpr::VK_Invalid) {
+        Variant = MCSymbolRefExpr::VK_None;
+        TokError("invalid variant '" + Split.second + "'");
+      }
+    }
 
     // If this is an absolute variable reference, substitute it now to preserve
     // semantics in the face of reassignment.
@@ -564,6 +572,52 @@
   return ParseExpression(Res, EndLoc);
 }
 
+const MCExpr *
+AsmParser::ApplyModifierToExpr(const MCExpr *E,
+                               MCSymbolRefExpr::VariantKind Variant) {
+  // Recurse over the given expression, rebuilding it to apply the given variant
+  // if there is exactly one symbol.
+  switch (E->getKind()) {
+  case MCExpr::Target:
+  case MCExpr::Constant:
+    return 0;
+
+  case MCExpr::SymbolRef: {
+    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
+
+    if (SRE->getKind() != MCSymbolRefExpr::VK_None) {
+      TokError("invalid variant on expression '" +
+               getTok().getIdentifier() + "' (already modified)");
+      return E;
+    }
+
+    return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
+  }
+
+  case MCExpr::Unary: {
+    const MCUnaryExpr *UE = cast<MCUnaryExpr>(E);
+    const MCExpr *Sub = ApplyModifierToExpr(UE->getSubExpr(), Variant);
+    if (!Sub)
+      return 0;
+    return MCUnaryExpr::Create(UE->getOpcode(), Sub, getContext());
+  }
+
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
+    const MCExpr *LHS = ApplyModifierToExpr(BE->getLHS(), Variant);
+    const MCExpr *RHS = ApplyModifierToExpr(BE->getRHS(), Variant);
+
+    if (!LHS && !RHS)
+      return 0;
+
+    if (!LHS) LHS = BE->getLHS();
+    if (!RHS) RHS = BE->getRHS();
+
+    return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
+  }
+  }
+}
+
 /// ParseExpression - Parse an expression and return it.
 /// 
 ///  expr ::= expr +,- expr          -> lowest.
@@ -577,6 +631,31 @@
   if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc))
     return true;
 
+  // As a special case, we support 'a op b @ modifier' by rewriting the
+  // expression to include the modifier. This is inefficient, but in general we
+  // expect users to use 'a at modifier op b'.
+  if (Lexer.getKind() == AsmToken::At) {
+    Lex();
+
+    if (Lexer.isNot(AsmToken::Identifier))
+      return TokError("unexpected symbol modifier following '@'");
+
+    MCSymbolRefExpr::VariantKind Variant =
+      MCSymbolRefExpr::getVariantKindForName(getTok().getIdentifier());
+    if (Variant == MCSymbolRefExpr::VK_Invalid)
+      return TokError("invalid variant '" + getTok().getIdentifier() + "'");
+
+    const MCExpr *ModifiedRes = ApplyModifierToExpr(Res, Variant);
+    if (!ModifiedRes) {
+      return TokError("invalid modifier '" + getTok().getIdentifier() +
+                      "' (no symbols present)");
+      return true;
+    }
+     
+    Res = ModifiedRes;
+    Lex();
+  }
+
   // Try to constant fold it up front, if possible.
   int64_t Value;
   if (Res->EvaluateAsAbsolute(Value))
@@ -610,7 +689,7 @@
   default:
     return 0;    // not a binop.
 
-    // Lowest Precedence: &&, ||
+    // Lowest Precedence: &&, ||, @
   case AsmToken::AmpAmp:
     Kind = MCBinaryExpr::LAnd;
     return 1;

Added: llvm/trunk/test/MC/AsmParser/expr_symbol_modifiers.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/expr_symbol_modifiers.s?rev=114154&view=auto
==============================================================================
--- llvm/trunk/test/MC/AsmParser/expr_symbol_modifiers.s (added)
+++ llvm/trunk/test/MC/AsmParser/expr_symbol_modifiers.s Thu Sep 16 21:47:07 2010
@@ -0,0 +1,14 @@
+// RUN: not llvm-mc -triple x86_64-unknown-unknown %s > %t 2> %t.err
+// RUN: FileCheck < %t %s
+// RUN: FileCheck -check-prefix=CHECK-STDERR < %t.err %s
+
+// CHECK: .long 1
+.long 1
+// CHECK-STDERR: invalid modifier 'GOTPCREL' (no symbols present)
+.long 10 + 4 at GOTPCREL
+// CHECK: .long a at GOTPCREL+4
+.long a + 4 at GOTPCREL
+// CHECK: .long a at GOTPCREL+b@GOTPCREL
+.long (a + b)@GOTPCREL
+// CHECK: .long (10+b at GOTPCREL)+4
+.long 10 + b + 4 at GOTPCREL





More information about the llvm-commits mailing list