diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h --- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h +++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h @@ -168,6 +168,8 @@ virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; + virtual bool isParsingMasm() const { return false; } + /// Parse MS-style inline assembly. virtual bool parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -248,6 +248,8 @@ } bool isParsingInlineAsm() override { return ParsingInlineAsm; } + bool isParsingMasm() const override { return true; } + bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl> &OpDecls, diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1607,7 +1607,8 @@ } else { BaseReg = BaseReg ? BaseReg : 1; return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, - IndexReg, Scale, Start, End, Size, Identifier, + IndexReg, Scale, Start, End, Size, + /*DefaultBaseReg=*/X86::NoRegister, Identifier, Decl, FrontendSize); } } @@ -2171,6 +2172,14 @@ return CreateMemForInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start, End, Size, SM.getSymName(), SM.getIdentifierInfo()); + + // When parsing x64 MASM, all memory operands default to RIP-relative when + // interpreted as non-absolute references. + if (Parser.isParsingMasm() && is64BitMode()) + return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, BaseReg, + IndexReg, Scale, Start, End, Size, + /*DefaultBaseReg=*/X86::RIP); + if (!(BaseReg || IndexReg || RegNo)) return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size); return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -60,6 +60,7 @@ unsigned SegReg; const MCExpr *Disp; unsigned BaseReg; + unsigned DefaultBaseReg; unsigned IndexReg; unsigned Scale; unsigned Size; @@ -184,6 +185,10 @@ assert(Kind == Memory && "Invalid access!"); return Mem.BaseReg; } + unsigned getMemDefaultBaseReg() const { + assert(Kind == Memory && "Invalid access!"); + return Mem.DefaultBaseReg; + } unsigned getMemIndexReg() const { assert(Kind == Memory && "Invalid access!"); return Mem.IndexReg; @@ -540,7 +545,10 @@ void addMemOperands(MCInst &Inst, unsigned N) const { assert((N == 5) && "Invalid number of operands!"); - Inst.addOperand(MCOperand::createReg(getMemBaseReg())); + if (getMemBaseReg()) + Inst.addOperand(MCOperand::createReg(getMemBaseReg())); + else + Inst.addOperand(MCOperand::createReg(getMemDefaultBaseReg())); Inst.addOperand(MCOperand::createImm(getMemScale())); Inst.addOperand(MCOperand::createReg(getMemIndexReg())); addExpr(Inst, getMemDisp()); @@ -633,6 +641,7 @@ Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; Res->Mem.BaseReg = 0; + Res->Mem.DefaultBaseReg = 0; Res->Mem.IndexReg = 0; Res->Mem.Scale = 1; Res->Mem.Size = Size; @@ -648,11 +657,14 @@ static std::unique_ptr CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, - SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), - void *OpDecl = nullptr, unsigned FrontendSize = 0) { + SMLoc EndLoc, unsigned Size = 0, + unsigned DefaultBaseReg = X86::NoRegister, + StringRef SymName = StringRef(), void *OpDecl = nullptr, + unsigned FrontendSize = 0) { // We should never just have a displacement, that should be parsed as an // absolute memory operand. - assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); + assert((SegReg || BaseReg || IndexReg || DefaultBaseReg) && + "Invalid memory operand!"); // The scale should always be one of {1,2,4,8}. assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) && @@ -661,6 +673,7 @@ Res->Mem.SegReg = SegReg; Res->Mem.Disp = Disp; Res->Mem.BaseReg = BaseReg; + Res->Mem.DefaultBaseReg = DefaultBaseReg; Res->Mem.IndexReg = IndexReg; Res->Mem.Scale = Scale; Res->Mem.Size = Size;