forked from OSchip/llvm-project
[ms] [llvm-ml] Support MASM's relational operators (EQ, LT, etc.)
Support the named relational operators (EQ, LT, etc.). Reviewed By: thakis Differential Revision: https://reviews.llvm.org/D89733
This commit is contained in:
parent
a97e357e8e
commit
d657f7cd30
|
@ -1831,13 +1831,17 @@ bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
|
|||
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<AsmToken::TokenKind>(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);
|
||||
|
|
|
@ -57,22 +57,28 @@ static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
}
|
||||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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 @@ private:
|
|||
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::CreateMemForMSInlineAsm(
|
|||
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 @@ bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,
|
|||
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 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
|
|||
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;
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue