Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -546,21 +546,57 @@ } PrevState = CurrState; } - void onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName) { - PrevState = State; + bool checkSetScale(int64_t _Scale, StringRef &ErrMsg) { + State = IES_INTEGER; + assert(!IndexReg && "IndexReg already set!"); + IndexReg = TmpReg; + Scale = _Scale; + if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) { + ErrMsg = "scale factor in address must be 1, 2, 4 or 8"; + 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, bool isParsingInlineAsm, + bool isNextMult = false) { + 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) { + // IndexRegister + SymbolicScale * 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: case IES_NOT: State = IES_INTEGER; - Sym = SymRef; - SymName = SymRefName; - IC.pushOperand(IC_IMM); + if (isParsingInlineAsm || !isNextMult) { + Sym = SymRef; + SymName = SymRefName; + } + 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; @@ -582,16 +618,8 @@ case IES_LPAREN: State = IES_INTEGER; if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) { - // Index Register - Register * Scale - assert (!IndexReg && "IndexReg already set!"); - 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 (checkSetScale(TmpInt, ErrMsg)) return true; - } - // Get the scale and replace the 'Register * Scale' with '0'. - IC.popOperator(); } else { IC.pushOperand(IC_IMM, TmpInt); } @@ -1379,10 +1407,11 @@ } case AsmToken::String: case AsmToken::Identifier: { - // This could be a register or a symbolic displacement. + // This could be a register or a symbolic displacement/scale. unsigned TmpReg; const MCExpr *Val; SMLoc IdentLoc = Tok.getLoc(); + StringRef ErrMsg; StringRef Identifier = Tok.getString(); UpdateLocLex = false; if (TK != AsmToken::String && !ParseRegister(TmpReg, IdentLoc, End)) { @@ -1392,7 +1421,11 @@ } else if (!isParsingInlineAsm()) { if (getParser().parsePrimaryExpr(Val, End)) return Error(Tok.getLoc(), "Unexpected identifier!"); - SM.onIdentifierExpr(Val, Identifier); + bool isNextMult = + getLexer().getTok().getKind() == AsmToken::TokenKind::Star; + if (SM.onIdentifierExpr(Val, Identifier, ErrMsg, isParsingInlineAsm(), + isNextMult)) + return Error(IdentLoc, ErrMsg); } else if (unsigned OpKind = IdentifyIntelOperator(Identifier)) { if (OpKind == IOK_OFFSET) return Error(IdentLoc, "Dealing OFFSET operator as part of" @@ -1400,7 +1433,6 @@ int64_t Val = ParseIntelOperator(OpKind); if (!Val) return true; - StringRef ErrMsg; if (SM.onInteger(Val, ErrMsg)) return Error(IdentLoc, ErrMsg); } else if (Identifier.find('.') != StringRef::npos && @@ -1411,7 +1443,10 @@ if (ParseIntelIdentifier(Val, Identifier, Info, /*Unevaluated=*/false, End)) return true; - SM.onIdentifierExpr(Val, Identifier); + if (SM.onIdentifierExpr(Val, Identifier, ErrMsg, isParsingInlineAsm(), + getLexer().getTok().getKind() == + AsmToken::TokenKind::Star)) + return Error(IdentLoc, ErrMsg); } break; } @@ -1435,7 +1470,10 @@ 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, isParsingInlineAsm(), + getLexer().getTok().getKind() == + AsmToken::TokenKind::Star)) + return Error(Loc, ErrMsg); End = consumeToken(); } else { if (SM.onInteger(IntVal, ErrMsg)) @@ -1504,12 +1542,13 @@ End); } - if (SM.getImm() || !Disp) { - const MCExpr *Imm = MCConstantExpr::create(SM.getImm(), getContext()); - if (Disp) - Disp = MCBinaryExpr::createAdd(Disp, Imm, getContext()); - else - Disp = Imm; // An immediate displacement only. + int64_t ImmVal = SM.getImm(); + const MCExpr *Imm = MCConstantExpr::create(ImmVal, getContext()); + if (ImmVal && Disp && Disp->getKind() == llvm::MCExpr::SymbolRef) + Disp = MCBinaryExpr::createAdd(Disp, Imm, getContext()); + if (!Disp || (Disp->getKind() == llvm::MCExpr::Constant && ImmVal)) { + assert((!Disp || Disp == SM.getSym()) && "Disp has to be symbolic"); + Disp = Imm; // It can be an immediate displacement only (maybe 0). } // Parse struct field access. Intel requires a dot, but MSVC doesn't. MSVC Index: test/MC/X86/intel-syntax.s =================================================================== --- test/MC/X86/intel-syntax.s +++ test/MC/X86/intel-syntax.s @@ -6,7 +6,66 @@ xor EAX, EAX ret -_main: +.set number, 8 +.global _foo + +.text + .global main +main: + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [number * RAX + RBX + _foo] +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [8 * RAX + RBX + _foo] +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [RAX * number + RBX + _foo] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + number * RAX + RBX] +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + 8 * RAX + RBX] +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + RAX * number + RBX] + +// CHECK: leaq 8(%rcx,%rax,8), %rdx + lea RDX, [8 + RAX * 8 + RCX] +// CHECK: leaq 8(%rcx,%rax,8), %rdx + lea RDX, [number + RAX * number + RCX] + +// CHECK: leaq 8(%rcx,%rax,8), %rdx + lea RDX, [8 + number * RAX + 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(,%rax,8), %rdx + lea RDX, [_foo + RAX * number] + +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + RAX * 8 + RBX] +// CHECK: leaq _foo(%rbx,%rax,8), %rdx + lea RDX, [_foo + RAX * number + 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)