1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[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
This commit is contained in:
Eric Astor 2020-07-01 12:39:28 -04:00
parent 5e55cc3577
commit 60bee70ca5
5 changed files with 40 additions and 6 deletions

View File

@ -168,6 +168,8 @@ public:
virtual void setParsingMSInlineAsm(bool V) = 0; virtual void setParsingMSInlineAsm(bool V) = 0;
virtual bool isParsingMSInlineAsm() = 0; virtual bool isParsingMSInlineAsm() = 0;
virtual bool isParsingMasm() const { return false; }
/// Parse MS-style inline assembly. /// Parse MS-style inline assembly.
virtual bool parseMSInlineAsm( virtual bool parseMSInlineAsm(
void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,

View File

@ -245,6 +245,8 @@ public:
} }
bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; } bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
bool isParsingMasm() const override { return true; }
bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
unsigned &NumOutputs, unsigned &NumInputs, unsigned &NumOutputs, unsigned &NumInputs,
SmallVectorImpl<std::pair<void *,bool>> &OpDecls, SmallVectorImpl<std::pair<void *,bool>> &OpDecls,

View File

@ -1509,8 +1509,9 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForMSInlineAsm(
} else { } else {
BaseReg = BaseReg ? BaseReg : 1; BaseReg = BaseReg ? BaseReg : 1;
return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg, return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg,
IndexReg, Scale, Start, End, Size, Identifier, IndexReg, Scale, Start, End, Size,
Decl, FrontendSize); /*DefaultBaseReg=*/X86::RIP, Identifier, Decl,
FrontendSize);
} }
} }
@ -2073,6 +2074,14 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start, return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start,
End, Size, SM.getSymName(), End, Size, SM.getSymName(),
SM.getIdentifierInfo()); 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)) if (!(BaseReg || IndexReg || RegNo))
return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size); return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size);
return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp,

View File

@ -58,6 +58,7 @@ struct X86Operand final : public MCParsedAsmOperand {
unsigned SegReg; unsigned SegReg;
const MCExpr *Disp; const MCExpr *Disp;
unsigned BaseReg; unsigned BaseReg;
unsigned DefaultBaseReg;
unsigned IndexReg; unsigned IndexReg;
unsigned Scale; unsigned Scale;
unsigned Size; unsigned Size;
@ -182,6 +183,10 @@ struct X86Operand final : public MCParsedAsmOperand {
assert(Kind == Memory && "Invalid access!"); assert(Kind == Memory && "Invalid access!");
return Mem.BaseReg; return Mem.BaseReg;
} }
unsigned getMemDefaultBaseReg() const {
assert(Kind == Memory && "Invalid access!");
return Mem.DefaultBaseReg;
}
unsigned getMemIndexReg() const { unsigned getMemIndexReg() const {
assert(Kind == Memory && "Invalid access!"); assert(Kind == Memory && "Invalid access!");
return Mem.IndexReg; return Mem.IndexReg;
@ -546,7 +551,10 @@ struct X86Operand final : public MCParsedAsmOperand {
void addMemOperands(MCInst &Inst, unsigned N) const { void addMemOperands(MCInst &Inst, unsigned N) const {
assert((N == 5) && "Invalid number of operands!"); 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::createImm(getMemScale()));
Inst.addOperand(MCOperand::createReg(getMemIndexReg())); Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
addExpr(Inst, getMemDisp()); addExpr(Inst, getMemDisp());
@ -639,6 +647,7 @@ struct X86Operand final : public MCParsedAsmOperand {
Res->Mem.SegReg = 0; Res->Mem.SegReg = 0;
Res->Mem.Disp = Disp; Res->Mem.Disp = Disp;
Res->Mem.BaseReg = 0; Res->Mem.BaseReg = 0;
Res->Mem.DefaultBaseReg = 0;
Res->Mem.IndexReg = 0; Res->Mem.IndexReg = 0;
Res->Mem.Scale = 1; Res->Mem.Scale = 1;
Res->Mem.Size = Size; Res->Mem.Size = Size;
@ -654,11 +663,14 @@ struct X86Operand final : public MCParsedAsmOperand {
static std::unique_ptr<X86Operand> static std::unique_ptr<X86Operand>
CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), SMLoc EndLoc, unsigned Size = 0,
void *OpDecl = nullptr, unsigned FrontendSize = 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 // We should never just have a displacement, that should be parsed as an
// absolute memory operand. // 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}. // The scale should always be one of {1,2,4,8}.
assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 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.SegReg = SegReg;
Res->Mem.Disp = Disp; Res->Mem.Disp = Disp;
Res->Mem.BaseReg = BaseReg; Res->Mem.BaseReg = BaseReg;
Res->Mem.DefaultBaseReg = DefaultBaseReg;
Res->Mem.IndexReg = IndexReg; Res->Mem.IndexReg = IndexReg;
Res->Mem.Scale = Scale; Res->Mem.Scale = Scale;
Res->Mem.Size = Size; Res->Mem.Size = Size;

View File

@ -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