[ms-inline asm] Add support for the minus unary operator. Previously, we were

unable to handle cases such as __asm mov eax, 8*-8.

This patch also attempts to simplify the state machine.  Further, the error
reporting has been improved.  Test cases included, but more will be added to
the clang side shortly.
rdar://13668445


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179719 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chad Rosier
2013-04-17 21:01:45 +00:00
parent b271b120d0
commit d58f773b96
2 changed files with 114 additions and 73 deletions

View File

@@ -193,15 +193,13 @@ private:
IES_LPAREN, IES_LPAREN,
IES_RPAREN, IES_RPAREN,
IES_REGISTER, IES_REGISTER,
IES_REGISTER_STAR,
IES_INTEGER, IES_INTEGER,
IES_INTEGER_STAR,
IES_IDENTIFIER, IES_IDENTIFIER,
IES_ERROR IES_ERROR
}; };
class IntelExprStateMachine { class IntelExprStateMachine {
IntelExprState State; IntelExprState State, PrevState;
unsigned BaseReg, IndexReg, TmpReg, Scale; unsigned BaseReg, IndexReg, TmpReg, Scale;
int64_t Imm; int64_t Imm;
const MCExpr *Sym; const MCExpr *Sym;
@@ -210,8 +208,9 @@ private:
InfixCalculator IC; InfixCalculator IC;
public: public:
IntelExprStateMachine(int64_t imm, bool stoponlbrac, bool addimmprefix) : IntelExprStateMachine(int64_t imm, bool stoponlbrac, bool addimmprefix) :
State(IES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Imm(imm), State(IES_PLUS), PrevState(IES_ERROR), BaseReg(0), IndexReg(0), TmpReg(0),
Sym(0), StopOnLBrac(stoponlbrac), AddImmPrefix(addimmprefix) {} Scale(1), Imm(imm), Sym(0), StopOnLBrac(stoponlbrac),
AddImmPrefix(addimmprefix) {}
unsigned getBaseReg() { return BaseReg; } unsigned getBaseReg() { return BaseReg; }
unsigned getIndexReg() { return IndexReg; } unsigned getIndexReg() { return IndexReg; }
@@ -222,21 +221,22 @@ private:
bool isValidEndState() { return State == IES_RBRAC; } bool isValidEndState() { return State == IES_RBRAC; }
bool getStopOnLBrac() { return StopOnLBrac; } bool getStopOnLBrac() { return StopOnLBrac; }
bool getAddImmPrefix() { return AddImmPrefix; } bool getAddImmPrefix() { return AddImmPrefix; }
bool hadError() { return State == IES_ERROR; }
void onPlus() { void onPlus() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_INTEGER: case IES_INTEGER:
case IES_RPAREN: case IES_RPAREN:
State = IES_PLUS;
IC.pushOperator(IC_PLUS);
break;
case IES_REGISTER: case IES_REGISTER:
State = IES_PLUS; State = IES_PLUS;
// If we already have a BaseReg, then assume this is the IndexReg with a IC.pushOperator(IC_PLUS);
// scale of 1. if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
// If we already have a BaseReg, then assume this is the IndexReg with
// a scale of 1.
if (!BaseReg) { if (!BaseReg) {
BaseReg = TmpReg; BaseReg = TmpReg;
} else { } else {
@@ -244,27 +244,35 @@ private:
IndexReg = TmpReg; IndexReg = TmpReg;
Scale = 1; Scale = 1;
} }
IC.pushOperator(IC_PLUS); }
break; break;
} }
PrevState = CurrState;
} }
void onMinus() { void onMinus() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_PLUS: case IES_PLUS:
case IES_MULTIPLY:
case IES_DIVIDE:
case IES_LPAREN: case IES_LPAREN:
IC.pushOperand(IC_IMM);
case IES_INTEGER:
case IES_RPAREN: case IES_RPAREN:
State = IES_MINUS; case IES_LBRAC:
IC.pushOperator(IC_MINUS); case IES_RBRAC:
break; case IES_INTEGER:
case IES_REGISTER: case IES_REGISTER:
State = IES_MINUS; State = IES_MINUS;
// If we already have a BaseReg, then assume this is the IndexReg with a // Only push the minus operator if it is not a unary operator.
// scale of 1. if (!(CurrState == IES_PLUS || CurrState == IES_MINUS ||
CurrState == IES_MULTIPLY || CurrState == IES_DIVIDE ||
CurrState == IES_LPAREN || CurrState == IES_LBRAC))
IC.pushOperator(IC_MINUS);
if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
// If we already have a BaseReg, then assume this is the IndexReg with
// a scale of 1.
if (!BaseReg) { if (!BaseReg) {
BaseReg = TmpReg; BaseReg = TmpReg;
} else { } else {
@@ -272,11 +280,13 @@ private:
IndexReg = TmpReg; IndexReg = TmpReg;
Scale = 1; Scale = 1;
} }
IC.pushOperator(IC_MINUS); }
break; break;
} }
PrevState = CurrState;
} }
void onRegister(unsigned Reg) { void onRegister(unsigned Reg) {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
@@ -287,17 +297,25 @@ private:
TmpReg = Reg; TmpReg = Reg;
IC.pushOperand(IC_REGISTER); IC.pushOperand(IC_REGISTER);
break; break;
case IES_INTEGER_STAR: case IES_MULTIPLY:
// Index Register - Scale * Register
if (PrevState == IES_INTEGER) {
assert (!IndexReg && "IndexReg already set!"); assert (!IndexReg && "IndexReg already set!");
State = IES_INTEGER; State = IES_REGISTER;
IndexReg = Reg; IndexReg = Reg;
// Get the scale and replace the 'Scale * Register' with '0'.
Scale = IC.popOperand(); Scale = IC.popOperand();
IC.pushOperand(IC_IMM); IC.pushOperand(IC_IMM);
IC.popOperator(); IC.popOperator();
} else {
State = IES_ERROR;
}
break; break;
} }
PrevState = CurrState;
} }
void onDispExpr(const MCExpr *SymRef, StringRef SymRefName) { void onDispExpr(const MCExpr *SymRef, StringRef SymRefName) {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
@@ -310,61 +328,72 @@ private:
IC.pushOperand(IC_IMM); IC.pushOperand(IC_IMM);
break; break;
} }
PrevState = CurrState;
} }
void onInteger(int64_t TmpInt) { void onInteger(int64_t TmpInt) {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_PLUS: case IES_PLUS:
case IES_MINUS: case IES_MINUS:
case IES_MULTIPLY:
case IES_DIVIDE: case IES_DIVIDE:
case IES_MULTIPLY:
case IES_LPAREN: case IES_LPAREN:
case IES_INTEGER_STAR:
State = IES_INTEGER; State = IES_INTEGER;
IC.pushOperand(IC_IMM, TmpInt); if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
break; // Index Register - Register * Scale
case IES_REGISTER_STAR:
assert (!IndexReg && "IndexReg already set!"); assert (!IndexReg && "IndexReg already set!");
State = IES_INTEGER;
IndexReg = TmpReg; IndexReg = TmpReg;
Scale = TmpInt; Scale = TmpInt;
// Get the scale and replace the 'Register * Scale' with '0'.
IC.popOperator(); IC.popOperator();
} else if ((PrevState == IES_PLUS || PrevState == IES_MINUS ||
PrevState == IES_MULTIPLY || PrevState == IES_DIVIDE ||
PrevState == IES_LPAREN || PrevState == IES_LBRAC) &&
CurrState == IES_MINUS) {
// Unary minus. No need to pop the minus operand because it was never
// pushed.
IC.pushOperand(IC_IMM, -TmpInt); // Push -Imm.
} else {
IC.pushOperand(IC_IMM, TmpInt);
}
break; break;
} }
PrevState = CurrState;
} }
void onStar() { void onStar() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_INTEGER: case IES_INTEGER:
State = IES_INTEGER_STAR;
IC.pushOperator(IC_MULTIPLY);
break;
case IES_REGISTER: case IES_REGISTER:
State = IES_REGISTER_STAR;
IC.pushOperator(IC_MULTIPLY);
break;
case IES_RPAREN: case IES_RPAREN:
State = IES_MULTIPLY; State = IES_MULTIPLY;
IC.pushOperator(IC_MULTIPLY); IC.pushOperator(IC_MULTIPLY);
break; break;
} }
PrevState = CurrState;
} }
void onDivide() { void onDivide() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_INTEGER: case IES_INTEGER:
case IES_RPAREN:
State = IES_DIVIDE; State = IES_DIVIDE;
IC.pushOperator(IC_DIVIDE); IC.pushOperator(IC_DIVIDE);
break; break;
} }
PrevState = CurrState;
} }
void onLBrac() { void onLBrac() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
@@ -374,20 +403,21 @@ private:
IC.pushOperator(IC_PLUS); IC.pushOperator(IC_PLUS);
break; break;
} }
PrevState = CurrState;
} }
void onRBrac() { void onRBrac() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_RPAREN:
case IES_INTEGER: case IES_INTEGER:
State = IES_RBRAC;
break;
case IES_REGISTER: case IES_REGISTER:
case IES_RPAREN:
State = IES_RBRAC; State = IES_RBRAC;
// If we already have a BaseReg, then assume this is the IndexReg with a if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
// scale of 1. // If we already have a BaseReg, then assume this is the IndexReg with
// a scale of 1.
if (!BaseReg) { if (!BaseReg) {
BaseReg = TmpReg; BaseReg = TmpReg;
} else { } else {
@@ -395,10 +425,13 @@ private:
IndexReg = TmpReg; IndexReg = TmpReg;
Scale = 1; Scale = 1;
} }
}
break; break;
} }
PrevState = CurrState;
} }
void onLParen() { void onLParen() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
@@ -407,29 +440,27 @@ private:
case IES_MINUS: case IES_MINUS:
case IES_MULTIPLY: case IES_MULTIPLY:
case IES_DIVIDE: case IES_DIVIDE:
case IES_INTEGER_STAR:
case IES_LPAREN: case IES_LPAREN:
State = IES_LPAREN; State = IES_LPAREN;
IC.pushOperator(IC_LPAREN); IC.pushOperator(IC_LPAREN);
break; break;
} }
PrevState = CurrState;
} }
void onRParen() { void onRParen() {
IntelExprState CurrState = State;
switch (State) { switch (State) {
default: default:
State = IES_ERROR; State = IES_ERROR;
break; break;
case IES_REGISTER:
case IES_INTEGER: case IES_INTEGER:
case IES_PLUS: case IES_REGISTER:
case IES_MINUS:
case IES_MULTIPLY:
case IES_DIVIDE:
case IES_RPAREN: case IES_RPAREN:
State = IES_RPAREN; State = IES_RPAREN;
IC.pushOperator(IC_RPAREN); IC.pushOperator(IC_RPAREN);
break; break;
} }
PrevState = CurrState;
} }
}; };
@@ -1250,6 +1281,9 @@ X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
case AsmToken::LParen: SM.onLParen(); break; case AsmToken::LParen: SM.onLParen(); break;
case AsmToken::RParen: SM.onRParen(); break; case AsmToken::RParen: SM.onRParen(); break;
} }
if (SM.hadError())
return ErrorOperand(Tok.getLoc(), "Unexpected token!");
if (!Done && UpdateLocLex) { if (!Done && UpdateLocLex) {
End = Tok.getLoc(); End = Tok.getLoc();
Parser.Lex(); // Consume the token. Parser.Lex(); // Consume the token.

View File

@@ -283,5 +283,12 @@ _main:
mov [((-2) * ((8 + 4) - 4)) + eax + ebx*4], ecx mov [((-2) * ((8 + 4) - 4)) + eax + ebx*4], ecx
// CHECK: movl %ecx, -16(%eax,%ebx,4) // CHECK: movl %ecx, -16(%eax,%ebx,4)
mov [eax + ((-2) * ((8 + 4) - 4)) + ebx*4], ecx mov [eax + ((-2) * ((8 + 4) - 4)) + ebx*4], ecx
// CHECK: movl %ecx, 96(%eax,%ebx,4)
mov [eax + ((-2) * ((8 + 4) * -4)) + ebx*4], ecx
// CHECK: movl %ecx, -8(%eax,%ebx,4)
mov [eax][-8][ebx*4], ecx
// CHECK: movl %ecx, -2(%eax,%ebx,4)
mov [eax][16/-8][ebx*4], ecx
// CHECK: movl %ecx, -2(%eax,%ebx,4)
mov [eax][(16)/-8][ebx*4], ecx
ret ret