From 1cc210383b281e9c78ff82c129d01efb598eee15 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 30 Jul 2020 23:24:09 -0700 Subject: [PATCH] [MC] Support infix operator ! 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 | 1 + llvm/lib/MC/MCExpr.cpp | 2 ++ llvm/lib/MC/MCParser/AsmParser.cpp | 17 +++++++++++------ llvm/lib/MC/MCParser/MasmParser.cpp | 2 -- llvm/test/MC/AsmParser/exprs-gnu.s | 4 ++++ 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 llvm/test/MC/AsmParser/exprs-gnu.s diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h index a424957bb0b22e..843de5d5be92e4 100644 --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -500,6 +500,7 @@ class MCBinaryExpr : public MCExpr { Mul, ///< Multiplication. NE, ///< Inequality comparison. Or, ///< Bitwise or. + OrNot, ///< Bitwise or not. Shl, ///< Shift left. AShr, ///< Arithmetic shift right. LShr, ///< Logical shift right. diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp index 11fd32e48a4aeb..a0aa7a3b95474e 100644 --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -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; diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index c05f26cbdda5cb..497f73e4110576 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -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'. diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp index fb3bb11d1f4302..fb7aaae295dfa8 100644 --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -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 index 00000000000000..3b5af48d36d4fe --- /dev/null +++ b/llvm/test/MC/AsmParser/exprs-gnu.s @@ -0,0 +1,4 @@ +# RUN: llvm-mc -triple=x86_64 %s | FileCheck %s + +# CHECK: movl %eax, 15 +movl %eax, 3 ! ~12