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,28 +568,64 @@ 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, 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; @@ -609,17 +647,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); } @@ -983,6 +1012,15 @@ if (RegNo == 0) RegNo = MatchRegisterName(Tok.getString().lower()); + // In MS inline-asm we allow variables to be named as registers, and + // give them precedence over actual registers + // However - we require the match to be case sensitive + if (isParsingInlineAsm() && isParsingIntelSyntax() && RegNo) { + StringRef LineBuf(Tok.getIdentifier().data()); + InlineAsmIdentifierInfo Info; + if (SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, false)) + return true; + } // The "flags" register cannot be referenced directly. // Treat it as an identifier instead. if (isParsingInlineAsm() && isParsingIntelSyntax() && RegNo == X86::EFLAGS) @@ -1422,7 +1460,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" @@ -1440,7 +1482,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; } @@ -1463,7 +1508,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)) @@ -1538,13 +1586,18 @@ End); } - if (SM.getImm() || !Disp) { - const MCExpr *Imm = MCConstantExpr::create(SM.getImm(), getContext()); - if (Disp) + int64_t ImmVal = SM.getImm(); + 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 (Disp->getKind() == llvm::MCExpr::Constant && ImmVal) { + 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 @@ -15,28 +15,20 @@ .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 Index: test/MC/X86/intel-syntax.s =================================================================== --- test/MC/X86/intel-syntax.s +++ test/MC/X86/intel-syntax.s @@ -31,7 +31,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]