diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -1831,13 +1831,17 @@ while (true) { AsmToken::TokenKind TokKind = Lexer.getKind(); if (Lexer.getKind() == AsmToken::Identifier) { - StringRef Identifier = Lexer.getTok().getString(); - if (Identifier.equals_lower("and")) - TokKind = AsmToken::Amp; - else if (Identifier.equals_lower("not")) - TokKind = AsmToken::Exclaim; - else if (Identifier.equals_lower("or")) - TokKind = AsmToken::Pipe; + TokKind = StringSwitch(Lexer.getTok().getString()) + .CaseLower("and", AsmToken::Amp) + .CaseLower("not", AsmToken::Exclaim) + .CaseLower("or", AsmToken::Pipe) + .CaseLower("eq", AsmToken::EqualEqual) + .CaseLower("ne", AsmToken::ExclaimEqual) + .CaseLower("lt", AsmToken::Less) + .CaseLower("le", AsmToken::LessEqual) + .CaseLower("gt", AsmToken::Greater) + .CaseLower("ge", AsmToken::GreaterEqual) + .Default(TokKind); } MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add; unsigned TokPrec = getBinOpPrecedence(TokKind, Kind); diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -57,22 +57,28 @@ namespace { static const char OpPrecedence[] = { - 0, // IC_OR - 1, // IC_XOR - 2, // IC_AND - 3, // IC_LSHIFT - 3, // IC_RSHIFT - 4, // IC_PLUS - 4, // IC_MINUS - 5, // IC_MULTIPLY - 5, // IC_DIVIDE - 5, // IC_MOD - 6, // IC_NOT - 7, // IC_NEG - 8, // IC_RPAREN - 9, // IC_LPAREN - 0, // IC_IMM - 0 // IC_REGISTER + 0, // IC_OR + 1, // IC_XOR + 2, // IC_AND + 4, // IC_LSHIFT + 4, // IC_RSHIFT + 5, // IC_PLUS + 5, // IC_MINUS + 6, // IC_MULTIPLY + 6, // IC_DIVIDE + 6, // IC_MOD + 7, // IC_NOT + 8, // IC_NEG + 9, // IC_RPAREN + 10, // IC_LPAREN + 0, // IC_IMM + 0, // IC_REGISTER + 3, // IC_EQ + 3, // IC_NE + 3, // IC_LT + 3, // IC_LE + 3, // IC_GT + 3 // IC_GE }; class X86AsmParser : public MCTargetAsmParser { @@ -143,7 +149,13 @@ IC_RPAREN, IC_LPAREN, IC_IMM, - IC_REGISTER + IC_REGISTER, + IC_EQ, + IC_NE, + IC_LT, + IC_LE, + IC_GT, + IC_GE }; enum IntelOperatorKind { @@ -332,6 +344,44 @@ Val = Op1.second >> Op2.second; OperandStack.push_back(std::make_pair(IC_IMM, Val)); break; + case IC_EQ: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Equals operation with an immediate and a register!"); + Val = (Op1.second == Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_NE: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Not-equals operation with an immediate and a register!"); + Val = (Op1.second != Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_LT: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Less-than operation with an immediate and a register!"); + Val = (Op1.second < Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_LE: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Less-than-or-equal operation with an immediate and a " + "register!"); + Val = (Op1.second <= Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_GT: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Greater-than operation with an immediate and a register!"); + Val = (Op1.second > Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_GE: + assert(Op1.first == IC_IMM && Op2.first == IC_IMM && + "Greater-than-or-equal operation with an immediate and a " + "register!"); + Val = (Op1.second >= Op2.second) ? -1 : 0; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; } } } @@ -345,6 +395,12 @@ IES_OR, IES_XOR, IES_AND, + IES_EQ, + IES_NE, + IES_LT, + IES_LE, + IES_GT, + IES_GE, IES_LSHIFT, IES_RSHIFT, IES_PLUS, @@ -461,6 +517,96 @@ } PrevState = CurrState; } + void onEq() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_EQ; + IC.pushOperator(IC_EQ); + break; + } + PrevState = CurrState; + } + void onNE() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_NE; + IC.pushOperator(IC_NE); + break; + } + PrevState = CurrState; + } + void onLT() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_LT; + IC.pushOperator(IC_LT); + break; + } + PrevState = CurrState; + } + void onLE() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_LE; + IC.pushOperator(IC_LE); + break; + } + PrevState = CurrState; + } + void onGT() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_GT; + IC.pushOperator(IC_GT); + break; + } + PrevState = CurrState; + } + void onGE() { + IntelExprState CurrState = State; + switch (State) { + default: + State = IES_ERROR; + break; + case IES_INTEGER: + case IES_RPAREN: + case IES_REGISTER: + State = IES_GE; + IC.pushOperator(IC_GE); + break; + } + PrevState = CurrState; + } void onLShift() { IntelExprState CurrState = State; switch (State) { @@ -531,6 +677,12 @@ case IES_OR: case IES_XOR: case IES_AND: + case IES_EQ: + case IES_NE: + case IES_LT: + case IES_LE: + case IES_GT: + case IES_GE: case IES_LSHIFT: case IES_RSHIFT: case IES_PLUS: @@ -586,6 +738,12 @@ case IES_OR: case IES_XOR: case IES_AND: + case IES_EQ: + case IES_NE: + case IES_LT: + case IES_LE: + case IES_GT: + case IES_GE: case IES_LSHIFT: case IES_RSHIFT: case IES_PLUS: @@ -686,6 +844,12 @@ case IES_OR: case IES_XOR: case IES_AND: + case IES_EQ: + case IES_NE: + case IES_LT: + case IES_LE: + case IES_GT: + case IES_GE: case IES_LSHIFT: case IES_RSHIFT: case IES_DIVIDE: @@ -822,6 +986,12 @@ case IES_OR: case IES_XOR: case IES_AND: + case IES_EQ: + case IES_NE: + case IES_LT: + case IES_LE: + case IES_GT: + case IES_GE: case IES_LSHIFT: case IES_RSHIFT: case IES_MULTIPLY: @@ -932,6 +1102,8 @@ bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands); bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM, bool &ParseError, SMLoc &End); + bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM, + bool &ParseError, SMLoc &End); void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start, SMLoc End); bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); @@ -1608,8 +1780,10 @@ bool X86AsmParser::ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM, bool &ParseError, SMLoc &End) { - // A named operator should be either lower or upper case, but not a mix - if (Name.compare(Name.lower()) && Name.compare(Name.upper())) + // A named operator should be either lower or upper case, but not a mix... + // except in MASM, which uses full case-insensitivity. + if (Name.compare(Name.lower()) && Name.compare(Name.upper()) && + !getParser().isParsingMasm()) return false; if (Name.equals_lower("not")) { SM.onNot(); @@ -1645,6 +1819,27 @@ End = consumeToken(); return true; } +bool X86AsmParser::ParseMasmNamedOperator(StringRef Name, + IntelExprStateMachine &SM, + bool &ParseError, SMLoc &End) { + if (Name.equals_lower("eq")) { + SM.onEq(); + } else if (Name.equals_lower("ne")) { + SM.onNE(); + } else if (Name.equals_lower("lt")) { + SM.onLT(); + } else if (Name.equals_lower("le")) { + SM.onLE(); + } else if (Name.equals_lower("gt")) { + SM.onGT(); + } else if (Name.equals_lower("ge")) { + SM.onGE(); + } else { + return false; + } + End = consumeToken(); + return true; +} bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { MCAsmParser &Parser = getParser(); @@ -1787,6 +1982,12 @@ return true; break; } + if (Parser.isParsingMasm() && + ParseMasmNamedOperator(Identifier, SM, ParseError, End)) { + if (ParseError) + return true; + break; + } // Symbol reference, when parsing assembly content InlineAsmIdentifierInfo Info; AsmFieldInfo FieldInfo; diff --git a/llvm/test/tools/llvm-ml/named_bitwise_operators.test b/llvm/test/tools/llvm-ml/named_bitwise_operators.test deleted file mode 100644 --- a/llvm/test/tools/llvm-ml/named_bitwise_operators.test +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: llvm-ml -filetype=asm %s | FileCheck %s - -.data - -t1 BYTE NOT 1 -; CHECK: t1: -; CHECK-NEXT: .byte -2 - -t2 BYTE 1 OR 2 -; CHECK: t2: -; CHECK-NEXT: .byte 3 - -t3 BYTE 6 AND 10 -; CHECK: t3: -; CHECK-NEXT: .byte 2 - -.code -xor eax, eax - -END diff --git a/llvm/test/tools/llvm-ml/named_operators.test b/llvm/test/tools/llvm-ml/named_operators.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/named_operators.test @@ -0,0 +1,143 @@ +; RUN: llvm-ml -filetype=asm %s | FileCheck %s + +.data + +t1 BYTE NOT 1 +; CHECK-LABEL: t1: +; CHECK-NEXT: .byte -2 +; CHECK-NOT: .byte + +t2 BYTE 1 OR 2 +; CHECK-LABEL: t2: +; CHECK-NEXT: .byte 3 + +t3 BYTE 6 AND 10 +; CHECK-LABEL: t3: +; CHECK-NEXT: .byte 2 + +t4 BYTE 5 EQ 6 + BYTE 6 EQ 6 + BYTE 7 EQ 6 +; CHECK-LABEL: t4: +; CHECK-NEXT: .byte 0 +; CHECK: .byte -1 +; CHECK: .byte 0 +; CHECK-NOT: .byte + +t5 BYTE 5 NE 6 + BYTE 6 NE 6 + BYTE 7 NE 6 +; CHECK-LABEL: t5: +; CHECK-NEXT: .byte -1 +; CHECK: .byte 0 +; CHECK: .byte -1 +; CHECK-NOT: .byte + +t6 BYTE 5 LT 6 + BYTE 6 LT 6 + BYTE 7 LT 6 +; CHECK-LABEL: t6: +; CHECK-NEXT: .byte -1 +; CHECK: .byte 0 +; CHECK: .byte 0 +; CHECK-NOT: .byte + +t7 BYTE 5 LE 6 + BYTE 6 LE 6 + BYTE 7 LE 6 +; CHECK-LABEL: t7: +; CHECK-NEXT: .byte -1 +; CHECK: .byte -1 +; CHECK: .byte 0 +; CHECK-NOT: .byte + +t8 BYTE 5 GT 6 + BYTE 6 GT 6 + BYTE 7 GT 6 +; CHECK-LABEL: t8: +; CHECK-NEXT: .byte 0 +; CHECK: .byte 0 +; CHECK: .byte -1 +; CHECK-NOT: .byte + +t9 BYTE 5 GE 6 + BYTE 6 GE 6 + BYTE 7 GE 6 +; CHECK-LABEL: t9: +; CHECK-NEXT: .byte 0 +; CHECK: .byte -1 +; CHECK: .byte -1 +; CHECK-NOT: .byte + +.code + +t10: +xor eax, Not 1 +; CHECK-LABEL: t10: +; CHECK-NEXT: xor eax, -2 + +t11: +xor eax, 1 oR 2 +; CHECK-LABEL: t11: +; CHECK-NEXT: xor eax, 3 + +t12: +xor eax, 6 ANd 10 +; CHECK-LABEL: t12: +; CHECK-NEXT: xor eax, 2 + +t13: +xor eax, 5 Eq 6 +xor eax, 6 eQ 6 +xor eax, 7 eq 6 +; CHECK-LABEL: t13: +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, 0 + +t14: +xor eax, 5 Ne 6 +xor eax, 6 nE 6 +xor eax, 7 ne 6 +; CHECK-LABEL: t14: +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, -1 + +t15: +xor eax, 5 Lt 6 +xor eax, 6 lT 6 +xor eax, 7 lt 6 +; CHECK-LABEL: t15: +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, 0 + +t16: +xor eax, 5 Le 6 +xor eax, 6 lE 6 +xor eax, 7 le 6 +; CHECK-LABEL: t16: +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, 0 + +t17: +xor eax, 5 Gt 6 +xor eax, 6 gT 6 +xor eax, 7 gt 6 +; CHECK-LABEL: t17: +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, -1 + +t18: +xor eax, 5 Ge 6 +xor eax, 6 gE 6 +xor eax, 7 ge 6 +; CHECK-LABEL: t18: +; CHECK-NEXT: xor eax, 0 +; CHECK-NEXT: xor eax, -1 +; CHECK-NEXT: xor eax, -1 + +END