mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 16:17:17 +00:00
[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:
@@ -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.
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user