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:
parent
5e55cc3577
commit
60bee70ca5
@ -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,
|
||||
|
@ -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<std::pair<void *,bool>> &OpDecls,
|
||||
|
@ -1509,8 +1509,9 @@ std::unique_ptr<X86Operand> 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<X86Operand> 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,
|
||||
|
@ -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<X86Operand>
|
||||
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;
|
||||
|
8
test/tools/llvm-ml/rip-relative-addressing.test
Normal file
8
test/tools/llvm-ml/rip-relative-addressing.test
Normal 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
|
Loading…
Reference in New Issue
Block a user