using namespace llvm;
+static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
+ if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
+ ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
+ return true;
+ }
+ return false;
+}
+
namespace {
static const char OpPrecedence[] = {
int64_t popOperand() {
assert (!PostfixStack.empty() && "Poped an empty stack!");
ICToken Op = PostfixStack.pop_back_val();
- assert ((Op.first == IC_IMM || Op.first == IC_REGISTER)
- && "Expected and immediate or register!");
+ if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))
+ return -1; // The invalid Scale value will be caught later by checkScale
return Op.second;
}
void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {
}
PrevState = CurrState;
}
- void onPlus() {
+ bool onPlus(StringRef &ErrMsg) {
IntelExprState CurrState = State;
switch (State) {
default:
if (!BaseReg) {
BaseReg = TmpReg;
} else {
- assert (!IndexReg && "BaseReg/IndexReg already set!");
+ if (IndexReg) {
+ ErrMsg = "BaseReg/IndexReg already set!";
+ return true;
+ }
IndexReg = TmpReg;
Scale = 1;
}
break;
}
PrevState = CurrState;
+ return false;
}
- void onMinus() {
+ bool onMinus(StringRef &ErrMsg) {
IntelExprState CurrState = State;
switch (State) {
default:
if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
CurrState == IES_INTEGER || CurrState == IES_RBRAC)
IC.pushOperator(IC_MINUS);
- else
+ else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
+ // We have negate operator for Scale: it's illegal
+ ErrMsg = "Scale can't be negative";
+ return true;
+ } else
IC.pushOperator(IC_NEG);
if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
// If we already have a BaseReg, then assume this is the IndexReg with
if (!BaseReg) {
BaseReg = TmpReg;
} else {
- assert (!IndexReg && "BaseReg/IndexReg already set!");
+ if (IndexReg) {
+ ErrMsg = "BaseReg/IndexReg already set!";
+ return true;
+ }
IndexReg = TmpReg;
Scale = 1;
}
break;
}
PrevState = CurrState;
+ return false;
}
void onNot() {
IntelExprState CurrState = State;
}
PrevState = CurrState;
}
- void onRegister(unsigned Reg) {
+
+ bool onRegister(unsigned Reg, StringRef &ErrMsg) {
IntelExprState CurrState = State;
switch (State) {
default:
case IES_MULTIPLY:
// Index Register - Scale * Register
if (PrevState == IES_INTEGER) {
- assert (!IndexReg && "IndexReg already set!");
+ if (IndexReg) {
+ ErrMsg = "BaseReg/IndexReg already set!";
+ return true;
+ }
State = IES_REGISTER;
IndexReg = Reg;
// Get the scale and replace the 'Scale * Register' with '0'.
Scale = IC.popOperand();
+ if (checkScale(Scale, ErrMsg))
+ return true;
IC.pushOperand(IC_IMM);
IC.popOperator();
} else {
break;
}
PrevState = CurrState;
+ return false;
}
void onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName) {
PrevState = State;
State = IES_INTEGER;
if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
// Index Register - Register * Scale
- assert (!IndexReg && "IndexReg already set!");
+ if (IndexReg) {
+ ErrMsg = "BaseReg/IndexReg already set!";
+ return true;
+ }
IndexReg = TmpReg;
Scale = TmpInt;
- if(Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
- ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
+ if (checkScale(Scale, ErrMsg))
return true;
- }
// Get the scale and replace the 'Register * Scale' with '0'.
IC.popOperator();
} else {
/// }
-static bool CheckBaseRegAndIndexReg(unsigned BaseReg, unsigned IndexReg,
- StringRef &ErrMsg) {
+static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
+ unsigned Scale, StringRef &ErrMsg) {
// If we have both a base register and an index register make sure they are
// both 64-bit or 32-bit registers.
// To support VSIB, IndexReg can be 128-bit or 256-bit registers.
}
}
}
- return false;
+ return checkScale(Scale, ErrMsg);
}
bool X86AsmParser::ParseRegister(unsigned &RegNo,
bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
MCAsmParser &Parser = getParser();
const AsmToken &Tok = Parser.getTok();
+ StringRef ErrMsg;
AsmToken::TokenKind PrevTK = AsmToken::Error;
bool Done = false;
StringRef Identifier = Tok.getString();
UpdateLocLex = false;
if (TK != AsmToken::String && !ParseRegister(TmpReg, IdentLoc, End)) {
- SM.onRegister(TmpReg);
+ if (SM.onRegister(TmpReg, ErrMsg))
+ return Error(Tok.getLoc(), ErrMsg);
} else if (ParseIntelNamedOperator(Identifier, SM)) {
UpdateLocLex = true;
} else if (!isParsingInlineAsm()) {
int64_t Val = ParseIntelOperator(OpKind,SM.getAddImmPrefix());
if (!Val)
return true;
- StringRef ErrMsg;
if (SM.onInteger(Val, ErrMsg))
return Error(IdentLoc, ErrMsg);
} else if (Identifier.find('.') != StringRef::npos &&
break;
}
case AsmToken::Integer: {
- StringRef ErrMsg;
if (isParsingInlineAsm() && SM.getAddImmPrefix())
InstInfo->AsmRewrites->emplace_back(AOK_ImmPrefix, Tok.getLoc());
// Look for 'b' or 'f' following an Integer as a directional label
}
break;
}
- case AsmToken::Plus: SM.onPlus(); break;
- case AsmToken::Minus: SM.onMinus(); break;
+ case AsmToken::Plus:
+ if (SM.onPlus(ErrMsg))
+ return Error(getTok().getLoc(), ErrMsg);
+ break;
+ case AsmToken::Minus:
+ if (SM.onMinus(ErrMsg))
+ return Error(getTok().getLoc(), ErrMsg);
+ break;
case AsmToken::Tilde: SM.onNot(); break;
case AsmToken::Star: SM.onStar(); break;
case AsmToken::Slash: SM.onDivide(); break;
Start, End, Size);
}
StringRef ErrMsg;
- if (CheckBaseRegAndIndexReg(BaseReg, IndexReg, ErrMsg)) {
+ if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, ErrMsg)) {
Error(StartInBrac, ErrMsg);
return nullptr;
}
}
StringRef ErrMsg;
- if (CheckBaseRegAndIndexReg(BaseReg, IndexReg, ErrMsg)) {
+ if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, ErrMsg)) {
Error(BaseLoc, ErrMsg);
return nullptr;
}
--- /dev/null
+// RUN: not llvm-mc -triple x86_64-unknown-unknown -x86-asm-syntax=intel %s 2> %t.err
+// RUN: FileCheck --check-prefix=CHECK-STDERR < %t.err %s
+
+_test:
+// CHECK-LABEL: _test:
+// CHECK: xorl %eax, %eax
+
+ xor EAX, EAX
+ ret
+
+.set number, 8
+.global _foo
+
+.text
+ .global main
+main:
+
+// CHECK-STDERR: error: unknown token in expression
+ lea RDX, [RAX * number + RBX + _foo]
+
+// CHECK-STDERR: error: unknown token in expression
+ lea RDX, [_foo + RAX * number + RBX]
+
+// CHECK-STDERR: error: unknown token in expression
+ lea RDX, [number + RAX * number + RCX]
+
+// CHECK-STDERR: error: unknown token in expression
+ lea RDX, [_foo + RAX * number]
+
+// CHECK-STDERR: error: unknown token in expression
+ lea RDX, [_foo + RAX * number + RBX]
+
+// CHECK-STDERR: scale factor in address must be 1, 2, 4 or 8
+ lea RDX, [number * RAX + RBX + _foo]
+
+// CHECK-STDERR: scale factor in address must be 1, 2, 4 or 8
+ lea RDX, [_foo + number * RAX + RBX]
+
+// CHECK-STDERR: scale factor in address must be 1, 2, 4 or 8
+ lea RDX, [8 + number * RAX + RCX]
+
+// CHECK-STDERR: scale factor in address must be 1, 2, 4 or 8
+lea RDX, [unknown_number * RAX + RBX + _foo]
+
+// CHECK-STDERR: error: BaseReg/IndexReg already set!
+lea RDX, [4 * RAX + 27 * RBX + _pat]
xor EAX, EAX
ret
-_main:
+.set number, 8
+.global _foo
+
+.text
+ .global main
+main:
+
+// CHECK: leaq _foo(%rbx,%rax,8), %rdx
+ lea RDX, [8 * RAX + RBX + _foo]
+
+// CHECK: leaq _foo(%rbx,%rax,8), %rdx
+ lea RDX, [_foo + 8 * RAX + RBX]
+
+// CHECK: leaq 8(%rcx,%rax,8), %rdx
+ lea RDX, [8 + RAX * 8 + RCX]
+
+// CHECK: leaq 8(%rcx,%rax,8), %rdx
+ lea RDX, [number + 8 * RAX + RCX]
+
+// CHECK: leaq _foo(,%rax,8), %rdx
+ lea RDX, [_foo + RAX * 8]
+
+// CHECK: leaq _foo(%rbx,%rax,8), %rdx
+ lea RDX, [_foo + RAX * 8 + RBX]
+
+// CHECK: leaq 8(%rax), %rdx
+ lea RDX, [RAX - number]
+// CHECK: leaq -8(%rax), %rdx
+ lea RDX, [RAX - 8]
+
+// CHECK: leaq _foo(%rax), %rdx
+ lea RDX, [RAX + _foo]
+// CHECK: leaq 8(%rax), %rdx
+ lea RDX, [RAX + number]
+// CHECK: leaq 8(%rax), %rdx
+ lea RDX, [RAX + 8]
+
+// CHECK: leaq _foo(%rax), %rdx
+ lea RDX, [_foo + RAX]
+// CHECK: leaq 8(%rax), %rdx
+ lea RDX, [number + RAX]
+// CHECK: leaq 8(%rax), %rdx
+ lea RDX, [8 + RAX]
+
// CHECK: movl $257, -4(%rsp)
mov DWORD PTR [RSP - 4], 257
// CHECK: movl $258, 4(%rsp)