[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