From 60bee70ca59cb1a67b7e20f6d3d4222ef503e6fe Mon Sep 17 00:00:00 2001 From: Eric Astor Date: Wed, 1 Jul 2020 12:39:28 -0400 Subject: [PATCH] [ms] [llvm-ml] Use default RIP-relative addressing for x64 MASM. Summary: When parsing 64-bit MASM, treat memory operands with unspecified base register as RIP-based. Documented in several places, including https://software.intel.com/en-us/articles/introduction-to-x64-assembly: "Unfortunately, MASM does not allow this form of opcode, but other assemblers like FASM and YASM do. Instead, MASM embeds RIP-relative addressing implicitly." Reviewed By: thakis Differential Revision: https://reviews.llvm.org/D73227 --- include/llvm/MC/MCParser/MCAsmParser.h | 2 ++ lib/MC/MCParser/MasmParser.cpp | 2 ++ lib/Target/X86/AsmParser/X86AsmParser.cpp | 13 ++++++++++-- lib/Target/X86/AsmParser/X86Operand.h | 21 +++++++++++++++---- .../llvm-ml/rip-relative-addressing.test | 8 +++++++ 5 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 test/tools/llvm-ml/rip-relative-addressing.test diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 7d57dd605fc..f02578e451b 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -168,6 +168,8 @@ public: 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/lib/MC/MCParser/MasmParser.cpp b/lib/MC/MCParser/MasmParser.cpp index ad44fd51712..423230962de 100644 --- a/lib/MC/MCParser/MasmParser.cpp +++ b/lib/MC/MCParser/MasmParser.cpp @@ -245,6 +245,8 @@ public: } 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/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index a9577e67def..7de2b2079b8 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1509,8 +1509,9 @@ std::unique_ptr X86AsmParser::CreateMemForMSInlineAsm( } 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 @@ std::unique_ptr X86AsmParser::ParseIntelOperand() { 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/lib/Target/X86/AsmParser/X86Operand.h b/lib/Target/X86/AsmParser/X86Operand.h index fb5f3355532..5393d90f16b 100644 --- a/lib/Target/X86/AsmParser/X86Operand.h +++ b/lib/Target/X86/AsmParser/X86Operand.h @@ -58,6 +58,7 @@ struct X86Operand final : public MCParsedAsmOperand { unsigned SegReg; const MCExpr *Disp; unsigned BaseReg; + unsigned DefaultBaseReg; unsigned IndexReg; unsigned Scale; unsigned Size; @@ -182,6 +183,10 @@ struct X86Operand final : public MCParsedAsmOperand { 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; @@ -546,7 +551,10 @@ struct X86Operand final : public MCParsedAsmOperand { 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()); @@ -639,6 +647,7 @@ struct X86Operand final : public MCParsedAsmOperand { 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; @@ -654,11 +663,14 @@ struct X86Operand final : public MCParsedAsmOperand { 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)) && @@ -667,6 +679,7 @@ struct X86Operand final : public MCParsedAsmOperand { 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/test/tools/llvm-ml/rip-relative-addressing.test b/test/tools/llvm-ml/rip-relative-addressing.test new file mode 100644 index 00000000000..81e5676d041 --- /dev/null +++ b/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