diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index e4623228b39..e9fc0d7ed1f 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -676,41 +676,180 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) { return Size; } +enum InfixCalculatorTok { + IC_PLUS = 0, + IC_MINUS, + IC_MULTIPLY, + IC_DIVIDE, + IC_RPAREN, + IC_LPAREN, + IC_IMM, + IC_REGISTER +}; +static const char OpPrecedence[] = { + 0, // IC_PLUS + 0, // IC_MINUS + 1, // IC_MULTIPLY + 1, // IC_DIVIDE + 2, // IC_RPAREN + 3, // IC_LPAREN + 0, // IC_IMM + 0 // IC_REGISTER +}; + +class InfixCalculator { + typedef std::pair< InfixCalculatorTok, int64_t > ICToken; + SmallVector InfixOperatorStack; + SmallVector PostfixStack; + +public: + 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!"); + return Op.second; + } + void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) { + assert ((Op == IC_IMM || Op == IC_REGISTER) && + "Unexpected operand!"); + PostfixStack.push_back(std::make_pair(Op, Val)); + } + + void popOperator() { InfixOperatorStack.pop_back_val(); } + void pushOperator(InfixCalculatorTok Op) { + // Push the new operator if the stack is empty. + if (InfixOperatorStack.empty()) { + InfixOperatorStack.push_back(Op); + return; + } + + // Push the new operator if it has a higher precedence than the operator on + // the top of the stack or the operator on the top of the stack is a left + // parentheses. + unsigned Idx = InfixOperatorStack.size() - 1; + InfixCalculatorTok StackOp = InfixOperatorStack[Idx]; + if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) { + InfixOperatorStack.push_back(Op); + return; + } + + // The operator on the top of the stack has higher precedence than the + // new operator. + unsigned ParenCount = 0; + while (1) { + // Nothing to process. + if (InfixOperatorStack.empty()) + break; + + Idx = InfixOperatorStack.size() - 1; + StackOp = InfixOperatorStack[Idx]; + if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount)) + break; + + // If we have an even parentheses count and we see a left parentheses, + // then stop processing. + if (!ParenCount && StackOp == IC_LPAREN) + break; + + if (StackOp == IC_RPAREN) { + ++ParenCount; + InfixOperatorStack.pop_back_val(); + } else if (StackOp == IC_LPAREN) { + --ParenCount; + InfixOperatorStack.pop_back_val(); + } else { + InfixOperatorStack.pop_back_val(); + PostfixStack.push_back(std::make_pair(StackOp, 0)); + } + } + // Push the new operator. + InfixOperatorStack.push_back(Op); + } + int64_t execute() { + // Push any remaining operators onto the postfix stack. + while (!InfixOperatorStack.empty()) { + InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val(); + if (StackOp != IC_LPAREN && StackOp != IC_RPAREN) + PostfixStack.push_back(std::make_pair(StackOp, 0)); + } + + if (PostfixStack.empty()) + return 0; + + SmallVector OperandStack; + for (unsigned i = 0, e = PostfixStack.size(); i != e; ++i) { + ICToken Op = PostfixStack[i]; + if (Op.first == IC_IMM || Op.first == IC_REGISTER) { + OperandStack.push_back(Op); + } else { + assert (OperandStack.size() > 1 && "Too few operands."); + int64_t Val; + ICToken Op2 = OperandStack.pop_back_val(); + ICToken Op1 = OperandStack.pop_back_val(); + switch (Op.first) { + default: + report_fatal_error("Unexpected operator!"); + break; + case IC_PLUS: + Val = Op1.second + Op2.second; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_MINUS: + Val = Op1.second - Op2.second; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_MULTIPLY: + assert (Op1.first == IC_IMM && Op2.first == IC_IMM && + "Multiply operation with an immediate and a register!"); + Val = Op1.second * Op2.second; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + case IC_DIVIDE: + assert (Op1.first == IC_IMM && Op2.first == IC_IMM && + "Divide operation with an immediate and a register!"); + assert (Op2.second != 0 && "Division by zero!"); + Val = Op1.second / Op2.second; + OperandStack.push_back(std::make_pair(IC_IMM, Val)); + break; + } + } + } + assert (OperandStack.size() == 1 && "Expected a single result."); + return OperandStack.pop_back_val().second; + } +}; + enum IntelBracExprState { - IBES_START, + IBES_PLUS, + IBES_MINUS, + IBES_MULTIPLY, + IBES_DIVIDE, IBES_LBRAC, IBES_RBRAC, + IBES_LPAREN, + IBES_RPAREN, IBES_REGISTER, IBES_REGISTER_STAR, - IBES_REGISTER_STAR_INTEGER, IBES_INTEGER, IBES_INTEGER_STAR, - IBES_INDEX_REGISTER, IBES_IDENTIFIER, - IBES_DISP_EXPR, - IBES_MINUS, IBES_ERROR }; class IntelBracExprStateMachine { IntelBracExprState State; - unsigned BaseReg, IndexReg, Scale; + unsigned BaseReg, IndexReg, TmpReg, Scale; int64_t Disp; - - unsigned TmpReg; - int64_t TmpInteger; - - bool isPlus; - + InfixCalculator IC; public: IntelBracExprStateMachine(MCAsmParser &parser, int64_t disp) : - State(IBES_START), BaseReg(0), IndexReg(0), Scale(1), Disp(disp), - TmpReg(0), TmpInteger(0), isPlus(true) {} + State(IBES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp){} unsigned getBaseReg() { return BaseReg; } unsigned getIndexReg() { return IndexReg; } unsigned getScale() { return Scale; } - int64_t getDisp() { return Disp; } + int64_t getDisp() { return Disp + IC.execute(); } bool isValidEndState() { return State == IBES_RBRAC; } void onPlus() { @@ -719,14 +858,12 @@ public: State = IBES_ERROR; break; case IBES_INTEGER: - State = IBES_START; - if (isPlus) - Disp += TmpInteger; - else - Disp -= TmpInteger; + case IBES_RPAREN: + State = IBES_PLUS; + IC.pushOperator(IC_PLUS); break; case IBES_REGISTER: - State = IBES_START; + State = IBES_PLUS; // If we already have a BaseReg, then assume this is the IndexReg with a // scale of 1. if (!BaseReg) { @@ -736,30 +873,25 @@ public: IndexReg = TmpReg; Scale = 1; } - break; - case IBES_INDEX_REGISTER: - State = IBES_START; + IC.pushOperator(IC_PLUS); break; } - isPlus = true; } void onMinus() { switch (State) { default: State = IBES_ERROR; break; - case IBES_START: - State = IBES_MINUS; - break; + case IBES_PLUS: + case IBES_LPAREN: + IC.pushOperand(IC_IMM); case IBES_INTEGER: - State = IBES_START; - if (isPlus) - Disp += TmpInteger; - else - Disp -= TmpInteger; + case IBES_RPAREN: + State = IBES_MINUS; + IC.pushOperator(IC_MINUS); break; case IBES_REGISTER: - State = IBES_START; + State = IBES_MINUS; // If we already have a BaseReg, then assume this is the IndexReg with a // scale of 1. if (!BaseReg) { @@ -769,27 +901,28 @@ public: IndexReg = TmpReg; Scale = 1; } - break; - case IBES_INDEX_REGISTER: - State = IBES_START; + IC.pushOperator(IC_MINUS); break; } - isPlus = false; } void onRegister(unsigned Reg) { switch (State) { default: State = IBES_ERROR; break; - case IBES_START: + case IBES_PLUS: + case IBES_LPAREN: State = IBES_REGISTER; TmpReg = Reg; + IC.pushOperand(IC_REGISTER); break; case IBES_INTEGER_STAR: assert (!IndexReg && "IndexReg already set!"); - State = IBES_INDEX_REGISTER; + State = IBES_INTEGER; IndexReg = Reg; - Scale = TmpInteger; + Scale = IC.popOperand(); + IC.pushOperand(IC_IMM); + IC.popOperator(); break; } } @@ -798,8 +931,10 @@ public: default: State = IBES_ERROR; break; - case IBES_START: - State = IBES_DISP_EXPR; + case IBES_PLUS: + case IBES_MINUS: + State = IBES_INTEGER; + IC.pushOperand(IC_IMM); break; } } @@ -808,19 +943,21 @@ public: default: State = IBES_ERROR; break; - case IBES_START: - State = IBES_INTEGER; - TmpInteger = TmpInt; - break; + case IBES_PLUS: case IBES_MINUS: + case IBES_MULTIPLY: + case IBES_DIVIDE: + case IBES_LPAREN: + case IBES_INTEGER_STAR: State = IBES_INTEGER; - TmpInteger = TmpInt; + IC.pushOperand(IC_IMM, TmpInt); break; case IBES_REGISTER_STAR: assert (!IndexReg && "IndexReg already set!"); - State = IBES_INDEX_REGISTER; + State = IBES_INTEGER; IndexReg = TmpReg; Scale = TmpInt; + IC.popOperator(); break; } } @@ -831,9 +968,26 @@ public: break; case IBES_INTEGER: State = IBES_INTEGER_STAR; + IC.pushOperator(IC_MULTIPLY); break; case IBES_REGISTER: State = IBES_REGISTER_STAR; + IC.pushOperator(IC_MULTIPLY); + break; + case IBES_RPAREN: + State = IBES_MULTIPLY; + IC.pushOperator(IC_MULTIPLY); + break; + } + } + void onDivide() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_INTEGER: + State = IBES_DIVIDE; + IC.pushOperator(IC_DIVIDE); break; } } @@ -843,8 +997,8 @@ public: State = IBES_ERROR; break; case IBES_RBRAC: - State = IBES_START; - isPlus = true; + State = IBES_PLUS; + IC.pushOperator(IC_PLUS); break; } } @@ -853,15 +1007,9 @@ public: default: State = IBES_ERROR; break; - case IBES_DISP_EXPR: - State = IBES_RBRAC; - break; + case IBES_RPAREN: case IBES_INTEGER: State = IBES_RBRAC; - if (isPlus) - Disp += TmpInteger; - else - Disp -= TmpInteger; break; case IBES_REGISTER: State = IBES_RBRAC; @@ -875,8 +1023,38 @@ public: Scale = 1; } break; - case IBES_INDEX_REGISTER: - State = IBES_RBRAC; + } + } + void onLParen() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_PLUS: + case IBES_MINUS: + case IBES_MULTIPLY: + case IBES_DIVIDE: + case IBES_INTEGER_STAR: + case IBES_LPAREN: + State = IBES_LPAREN; + IC.pushOperator(IC_LPAREN); + break; + } + } + void onRParen() { + switch (State) { + default: + State = IBES_ERROR; + break; + case IBES_REGISTER: + case IBES_INTEGER: + case IBES_PLUS: + case IBES_MINUS: + case IBES_MULTIPLY: + case IBES_DIVIDE: + case IBES_RPAREN: + State = IBES_RPAREN; + IC.pushOperator(IC_RPAREN); break; } } @@ -1005,16 +1183,20 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, } return ErrorOperand(Tok.getLoc(), "Unexpected identifier!"); } - case AsmToken::Integer: { - int64_t Val = Tok.getIntVal(); - SM.onInteger(Val); + case AsmToken::Integer: + if (isParsingInlineAsm()) + InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_ImmPrefix, + Tok.getLoc())); + SM.onInteger(Tok.getIntVal()); break; - } case AsmToken::Plus: SM.onPlus(); break; case AsmToken::Minus: SM.onMinus(); break; case AsmToken::Star: SM.onStar(); break; + case AsmToken::Slash: SM.onDivide(); break; case AsmToken::LBrac: SM.onLBrac(); break; case AsmToken::RBrac: SM.onRBrac(); break; + case AsmToken::LParen: SM.onLParen(); break; + case AsmToken::RParen: SM.onRParen(); break; } if (!Done && UpdateLocLex) { End = Tok.getLoc(); diff --git a/test/MC/X86/intel-syntax.s b/test/MC/X86/intel-syntax.s index 8bfa58a4bed..226757b305e 100644 --- a/test/MC/X86/intel-syntax.s +++ b/test/MC/X86/intel-syntax.s @@ -247,4 +247,41 @@ _main: mov [16][eax][ebx*4], ecx // CHECK: movl %ecx, -16(%eax,%ebx,4) mov [eax][ebx*4 - 16], ecx - ret + +// CHECK: prefetchnta 12800(%esi) + prefetchnta [esi + (200*64)] +// CHECK: prefetchnta 32(%esi) + prefetchnta [esi + (64/2)] +// CHECK: prefetchnta 128(%esi) + prefetchnta [esi + (64/2*4)] +// CHECK: prefetchnta 8(%esi) + prefetchnta [esi + (64/(2*4))] +// CHECK: prefetchnta 48(%esi) + prefetchnta [esi + (64/(2*4)+40)] + +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - 2*8], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][4*ebx - 2*8], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax + 4*ebx - 2*8], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [12 + eax + (4*ebx) - 2*14], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - 2*2*2*2], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - (2*8)], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax][ebx*4 - 2 * 8 + 4 - 4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax + ebx*4 - 2 * 8 + 4 - 4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax + ebx*4 - 2 * ((8 + 4) - 4)], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [-2 * ((8 + 4) - 4) + eax + ebx*4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [((-2) * ((8 + 4) - 4)) + eax + ebx*4], ecx +// CHECK: movl %ecx, -16(%eax,%ebx,4) + mov [eax + ((-2) * ((8 + 4) - 4)) + ebx*4], ecx + + ret