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 setParsingMSInlineAsm(bool V) = 0; virtual bool isParsingMSInlineAsm() = 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 @@ -245,6 +245,8 @@ } bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } + 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 @@ -1509,8 +1509,9 @@ } else { BaseReg = BaseReg ? BaseReg : 1; return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, - IndexReg, Scale, Start, End, Size, Identifier, - Decl, FrontendSize); + IndexReg, Scale, Start, End, Size, + /*DefaultBaseReg=*/X86::RIP, Identifier, Decl, + FrontendSize); } } @@ -2073,6 +2074,14 @@ return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start, End, Size, SM.getSymName(), SM.getIdentifierInfo()); + + // When parsing x64 MS-style assembly, 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 @@ -58,6 +58,7 @@ unsigned SegReg; const MCExpr *Disp; unsigned BaseReg; + unsigned DefaultBaseReg; unsigned IndexReg; unsigned Scale; unsigned Size; @@ -182,6 +183,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; @@ -538,7 +543,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()); @@ -631,6 +639,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; @@ -646,11 +655,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)) && @@ -659,6 +671,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; diff --git a/llvm/test/tools/llvm-ml/rip-relative-addressing.test b/llvm/test/tools/llvm-ml/rip-relative-addressing.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-ml/rip-relative-addressing.test @@ -0,0 +1,8 @@ +# RUN: llvm-ml -m32 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-32 +# RUN: llvm-ml -m64 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-64 + +.code +mov eax, [4] +; CHECK-32: mov eax, dword ptr [4] +; CHECK-64: mov eax, dword ptr [rip + 4] +END \ No newline at end of file