[MC] Support infix operator !
authorFangrui Song <maskray@google.com>
Fri, 31 Jul 2020 06:24:09 +0000 (23:24 -0700)
committerFangrui Song <maskray@google.com>
Fri, 31 Jul 2020 06:25:53 +0000 (23:25 -0700)
Disabled for Darwin mode.

Also disabled for ARM which has compatible aliases (implied 'sp' operand
in 'srs*' instructions like 'srsda #31!').

llvm/include/llvm/MC/MCExpr.h
llvm/lib/MC/MCExpr.cpp
llvm/lib/MC/MCParser/AsmParser.cpp
llvm/lib/MC/MCParser/MasmParser.cpp
llvm/test/MC/AsmParser/exprs-gnu.s [new file with mode: 0644]

index a424957bb0b22e234555463e089c884db1f8b241..843de5d5be92e421e385315250958f6e05e3a6fe 100644 (file)
@@ -500,6 +500,7 @@ public:
     Mul,  ///< Multiplication.
     NE,   ///< Inequality comparison.
     Or,   ///< Bitwise or.
+    OrNot, ///< Bitwise or not.
     Shl,  ///< Shift left.
     AShr, ///< Arithmetic shift right.
     LShr, ///< Logical shift right.
index 11fd32e48a4aeb06f5fbee57b3b1b7cfccb5bdc1..a0aa7a3b95474e43738565381c120b57d51bd9c3 100644 (file)
@@ -145,6 +145,7 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
     case MCBinaryExpr::Mul:  OS <<  '*'; break;
     case MCBinaryExpr::NE:   OS << "!="; break;
     case MCBinaryExpr::Or:   OS <<  '|'; break;
+    case MCBinaryExpr::OrNot: OS << '!'; break;
     case MCBinaryExpr::Shl:  OS << "<<"; break;
     case MCBinaryExpr::Sub:  OS <<  '-'; break;
     case MCBinaryExpr::Xor:  OS <<  '^'; break;
@@ -920,6 +921,7 @@ bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm,
     case MCBinaryExpr::Mul:  Result = LHS * RHS; break;
     case MCBinaryExpr::NE:   Result = LHS != RHS; break;
     case MCBinaryExpr::Or:   Result = LHS | RHS; break;
+    case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break;
     case MCBinaryExpr::Shl:  Result = uint64_t(LHS) << uint64_t(RHS); break;
     case MCBinaryExpr::Sub:  Result = LHS - RHS; break;
     case MCBinaryExpr::Xor:  Result = LHS ^ RHS; break;
index c05f26cbdda5cb5c66a108872f31397daa70b013..497f73e41105761a7a11b7e1f12c72038969d493 100644 (file)
@@ -1497,8 +1497,6 @@ static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
     return 1;
 
   // Low Precedence: |, &, ^
-  //
-  // FIXME: gas seems to support '!' as an infix operator?
   case AsmToken::Pipe:
     Kind = MCBinaryExpr::Or;
     return 2;
@@ -1559,7 +1557,8 @@ static unsigned getDarwinBinOpPrecedence(AsmToken::TokenKind K,
   }
 }
 
-static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
+static unsigned getGNUBinOpPrecedence(const MCAsmInfo &MAI,
+                                      AsmToken::TokenKind K,
                                       MCBinaryExpr::Opcode &Kind,
                                       bool ShouldUseLogicalShr) {
   switch (K) {
@@ -1603,12 +1602,18 @@ static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
     Kind = MCBinaryExpr::Sub;
     return 4;
 
-  // High Intermediate Precedence: |, &, ^
+  // High Intermediate Precedence: |, !, &, ^
   //
-  // FIXME: gas seems to support '!' as an infix operator?
   case AsmToken::Pipe:
     Kind = MCBinaryExpr::Or;
     return 5;
+  case AsmToken::Exclaim:
+    // Hack to support ARM compatible aliases (implied 'sp' operand in 'srs*'
+    // instructions like 'srsda #31!') and not parse ! as an infix operator.
+    if (MAI.getCommentString() == "@")
+      return 0;
+    Kind = MCBinaryExpr::OrNot;
+    return 5;
   case AsmToken::Caret:
     Kind = MCBinaryExpr::Xor;
     return 5;
@@ -1639,7 +1644,7 @@ unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
                                        MCBinaryExpr::Opcode &Kind) {
   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
   return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
-                  : getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr);
+                  : getGNUBinOpPrecedence(MAI, K, Kind, ShouldUseLogicalShr);
 }
 
 /// Parse all binary operators with precedence >= 'Precedence'.
index fb3bb11d1f4302b1e69c7763c5197e838f9fc20c..fb7aaae295dfa8437797e67a46e8c46eb2f46113 100644 (file)
@@ -1720,8 +1720,6 @@ static unsigned getGNUBinOpPrecedence(AsmToken::TokenKind K,
     return 4;
 
   // High Intermediate Precedence: |, &, ^
-  //
-  // FIXME: gas seems to support '!' as an infix operator?
   case AsmToken::Pipe:
     Kind = MCBinaryExpr::Or;
     return 5;
diff --git a/llvm/test/MC/AsmParser/exprs-gnu.s b/llvm/test/MC/AsmParser/exprs-gnu.s
new file mode 100644 (file)
index 0000000..3b5af48
--- /dev/null
@@ -0,0 +1,4 @@
+# RUN: llvm-mc -triple=x86_64 %s | FileCheck %s
+
+# CHECK: movl %eax, 15
+movl %eax, 3 ! ~12