Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -430,6 +430,13 @@ } PrevState = CurrState; } + bool checkIndexReg(StringRef &ErrMsg) { + if (IndexReg) { + ErrMsg = "BaseReg/IndexReg already set!"; + return true; + } + return false; + } bool onPlus(StringRef &ErrMsg) { IntelExprState CurrState = State; switch (State) { @@ -447,10 +454,8 @@ if (!BaseReg) { BaseReg = TmpReg; } else { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; + if (checkIndexReg(ErrMsg)) return true; - } IndexReg = TmpReg; Scale = 1; } @@ -499,10 +504,8 @@ if (!BaseReg) { BaseReg = TmpReg; } else { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; + if (checkIndexReg(ErrMsg)) return true; - } IndexReg = TmpReg; Scale = 1; } @@ -543,7 +546,8 @@ switch (State) { default: State = IES_ERROR; - break; + ErrMsg = "Invalid operation with register"; + return true; case IES_PLUS: case IES_LPAREN: State = IES_REGISTER; @@ -553,10 +557,8 @@ case IES_MULTIPLY: // Index Register - Scale * Register if (PrevState == IES_INTEGER) { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; + if (checkIndexReg(ErrMsg)) return true; - } State = IES_REGISTER; IndexReg = Reg; // Get the scale and replace the 'Scale * Register' with '0'. @@ -566,18 +568,45 @@ IC.pushOperand(IC_IMM); IC.popOperator(); } else { - State = IES_ERROR; + ErrMsg = "Invalid operand of multiplication"; + return true; } break; } PrevState = CurrState; return false; } - void onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName) { - PrevState = State; + bool checkSetScale(int64_t _Scale, StringRef &ErrMsg) { + State = IES_INTEGER; + if (checkIndexReg(ErrMsg)) + return true; + IndexReg = TmpReg; + Scale = _Scale; + if (checkScale(Scale, ErrMsg)) + return true; + // Get the scale and replace the 'Register * Scale' with '0'. + IC.popOperator(); + return false; + } + bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName, + StringRef &ErrMsg) { + IntelExprState CurrState = State; switch (State) { default: State = IES_ERROR; + ErrMsg = "invalid address operation"; + return true; + case IES_MULTIPLY: + if (PrevState == IES_REGISTER && + SymRef->getKind() == llvm::MCExpr::Constant) { + // BaseReg + SymbScale * Register + auto *Constant = cast(SymRef); + if (checkSetScale(Constant->getValue(), ErrMsg)) + return true; + } else { + ErrMsg = "invalid scale expression"; + return true; + } break; case IES_PLUS: case IES_MINUS: @@ -585,9 +614,15 @@ State = IES_INTEGER; Sym = SymRef; SymName = SymRefName; - IC.pushOperand(IC_IMM); + if (SymRef->getKind() == llvm::MCExpr::Constant) { + auto *Constant = cast(SymRef); + IC.pushOperand(IC_IMM, Constant->getValue()); + } else + IC.pushOperand(IC_IMM); break; } + PrevState = CurrState; + return false; } bool onInteger(int64_t TmpInt, StringRef &ErrMsg) { IntelExprState CurrState = State; @@ -609,17 +644,8 @@ case IES_LPAREN: State = IES_INTEGER; if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) { - // Index Register - Register * Scale - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; + if (checkSetScale(TmpInt, ErrMsg)) return true; - } - IndexReg = TmpReg; - Scale = TmpInt; - if (checkScale(Scale, ErrMsg)) - return true; - // Get the scale and replace the 'Register * Scale' with '0'. - IC.popOperator(); } else { IC.pushOperand(IC_IMM, TmpInt); } @@ -1422,7 +1448,15 @@ } else if (!isParsingInlineAsm()) { if (getParser().parsePrimaryExpr(Val, End)) return Error(Tok.getLoc(), "Unexpected identifier!"); - SM.onIdentifierExpr(Val, Identifier); + + if (Val->getKind() == MCExpr::Constant) { + int64_t TmpInt; + Val->evaluateAsAbsolute(TmpInt); + StringRef ErrMsg; + if (SM.onInteger(TmpInt, ErrMsg)) + return Error(Tok.getLoc(), ErrMsg); + } else if (SM.onIdentifierExpr(Val, Identifier, ErrMsg)) + return Error(IdentLoc, ErrMsg); } else if (unsigned OpKind = IdentifyIntelOperator(Identifier)) { if (OpKind == IOK_OFFSET) return Error(IdentLoc, "Dealing OFFSET operator as part of" @@ -1440,7 +1474,8 @@ if (ParseIntelIdentifier(Val, Identifier, Info, /*Unevaluated=*/false, End)) return true; - SM.onIdentifierExpr(Val, Identifier); + if (SM.onIdentifierExpr(Val, Identifier, ErrMsg)) + return Error(IdentLoc, ErrMsg); } break; } @@ -1463,7 +1498,8 @@ if (IDVal == "b" && Sym->isUndefined()) return Error(Loc, "invalid reference to undefined symbol"); StringRef Identifier = Sym->getName(); - SM.onIdentifierExpr(Val, Identifier); + if (SM.onIdentifierExpr(Val, Identifier, ErrMsg)) + return Error(Loc, ErrMsg); End = consumeToken(); } else { if (SM.onInteger(IntVal, ErrMsg)) @@ -1529,22 +1565,23 @@ return nullptr; const MCExpr *Disp = nullptr; - if (const MCExpr *Sym = SM.getSym()) { - // A symbolic displacement. - Disp = Sym; - if (isParsingInlineAsm()) - RewriteIntelBracExpression(*InstInfo->AsmRewrites, SM.getSymName(), - ImmDisp, SM.getImm(), BracLoc, StartInBrac, - End); + int64_t ImmVal = SM.getImm(); + if ((Disp = SM.getSym()) && isParsingInlineAsm()) { + RewriteIntelBracExpression(*InstInfo->AsmRewrites, SM.getSymName(), ImmDisp, + ImmVal, BracLoc, StartInBrac, End); } - if (SM.getImm() || !Disp) { - const MCExpr *Imm = MCConstantExpr::create(SM.getImm(), getContext()); - if (Disp) + const MCExpr *Imm = MCConstantExpr::create(ImmVal, getContext()); + if (Disp) { + if (ImmVal && Disp->getKind() == llvm::MCExpr::SymbolRef) + // If we have both Disp and Symbol then [Symbol + ImmDisp]. Disp = MCBinaryExpr::createAdd(Disp, Imm, getContext()); - else - Disp = Imm; // An immediate displacement only. - } + else if (ImmVal && Disp->getKind() == llvm::MCExpr::Constant) { + assert(Disp == SM.getSym() && "It's symbolic disp initialized above"); + Disp = Imm; // The signed value of the symbolic displacement. + } + } else + Disp = Imm; // It can be an immediate displacement only (maybe 0). // Parse struct field access. Intel requires a dot, but MSVC doesn't. MSVC // will in fact do global lookup the field name inside all global typedefs, Index: test/MC/X86/intel-syntax-3.s =================================================================== --- test/MC/X86/intel-syntax-3.s +++ test/MC/X86/intel-syntax-3.s @@ -1,44 +1,12 @@ // 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] Index: test/MC/X86/intel-syntax.s =================================================================== --- test/MC/X86/intel-syntax.s +++ test/MC/X86/intel-syntax.s @@ -14,6 +14,30 @@ main: // CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [RAX * number + RBX + _foo] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + RAX * number + RBX] + +// CHECK: leaq 8(%rcx,%rax,8), %rdx + lea RDX, [number + RAX * number + RCX] + +// CHECK: leaq _foo(,%rax,8), %rdx + lea RDX, [_foo + RAX * number] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + RAX * number + RBX] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [number * RAX + RBX + _foo] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + number * RAX + RBX] + +// CHECK: leaq 8(%rcx,%rax,8), %rdx + lea RDX, [8 + number * RAX + RCX] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx lea RDX, [8 * RAX + RBX + _foo] // CHECK: leaq _foo(%rbx,%rax,8), %rdx @@ -31,7 +55,7 @@ // CHECK: leaq _foo(%rbx,%rax,8), %rdx lea RDX, [_foo + RAX * 8 + RBX] -// CHECK: leaq 8(%rax), %rdx +// CHECK: leaq -8(%rax), %rdx lea RDX, [RAX - number] // CHECK: leaq -8(%rax), %rdx lea RDX, [RAX - 8]