Skip to content

Commit 353a169

Browse files
committed
[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
1 parent 0f9d623 commit 353a169

File tree

5 files changed

+40
-6
lines changed

5 files changed

+40
-6
lines changed

llvm/include/llvm/MC/MCParser/MCAsmParser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ class MCAsmParser {
168168
virtual void setParsingMSInlineAsm(bool V) = 0;
169169
virtual bool isParsingMSInlineAsm() = 0;
170170

171+
virtual bool isParsingMasm() const { return false; }
172+
171173
/// Parse MS-style inline assembly.
172174
virtual bool parseMSInlineAsm(
173175
void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,

llvm/lib/MC/MCParser/MasmParser.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ class MasmParser : public MCAsmParser {
245245
}
246246
bool isParsingMSInlineAsm() override { return ParsingMSInlineAsm; }
247247

248+
bool isParsingMasm() const override { return true; }
249+
248250
bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
249251
unsigned &NumOutputs, unsigned &NumInputs,
250252
SmallVectorImpl<std::pair<void *,bool>> &OpDecls,

llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,8 +1509,9 @@ std::unique_ptr<X86Operand> X86AsmParser::CreateMemForMSInlineAsm(
15091509
} else {
15101510
BaseReg = BaseReg ? BaseReg : 1;
15111511
return X86Operand::CreateMem(getPointerWidth(), SegReg, Disp, BaseReg,
1512-
IndexReg, Scale, Start, End, Size, Identifier,
1513-
Decl, FrontendSize);
1512+
IndexReg, Scale, Start, End, Size,
1513+
/*DefaultBaseReg=*/X86::RIP, Identifier, Decl,
1514+
FrontendSize);
15141515
}
15151516
}
15161517

@@ -2073,6 +2074,14 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOperand() {
20732074
return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start,
20742075
End, Size, SM.getSymName(),
20752076
SM.getIdentifierInfo());
2077+
2078+
// When parsing x64 MS-style assembly, all memory operands default to
2079+
// RIP-relative when interpreted as non-absolute references.
2080+
if (Parser.isParsingMasm() && is64BitMode())
2081+
return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp, BaseReg,
2082+
IndexReg, Scale, Start, End, Size,
2083+
/*DefaultBaseReg=*/X86::RIP);
2084+
20762085
if (!(BaseReg || IndexReg || RegNo))
20772086
return X86Operand::CreateMem(getPointerWidth(), Disp, Start, End, Size);
20782087
return X86Operand::CreateMem(getPointerWidth(), RegNo, Disp,

llvm/lib/Target/X86/AsmParser/X86Operand.h

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct X86Operand final : public MCParsedAsmOperand {
5858
unsigned SegReg;
5959
const MCExpr *Disp;
6060
unsigned BaseReg;
61+
unsigned DefaultBaseReg;
6162
unsigned IndexReg;
6263
unsigned Scale;
6364
unsigned Size;
@@ -182,6 +183,10 @@ struct X86Operand final : public MCParsedAsmOperand {
182183
assert(Kind == Memory && "Invalid access!");
183184
return Mem.BaseReg;
184185
}
186+
unsigned getMemDefaultBaseReg() const {
187+
assert(Kind == Memory && "Invalid access!");
188+
return Mem.DefaultBaseReg;
189+
}
185190
unsigned getMemIndexReg() const {
186191
assert(Kind == Memory && "Invalid access!");
187192
return Mem.IndexReg;
@@ -546,7 +551,10 @@ struct X86Operand final : public MCParsedAsmOperand {
546551

547552
void addMemOperands(MCInst &Inst, unsigned N) const {
548553
assert((N == 5) && "Invalid number of operands!");
549-
Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
554+
if (getMemBaseReg())
555+
Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
556+
else
557+
Inst.addOperand(MCOperand::createReg(getMemDefaultBaseReg()));
550558
Inst.addOperand(MCOperand::createImm(getMemScale()));
551559
Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
552560
addExpr(Inst, getMemDisp());
@@ -639,6 +647,7 @@ struct X86Operand final : public MCParsedAsmOperand {
639647
Res->Mem.SegReg = 0;
640648
Res->Mem.Disp = Disp;
641649
Res->Mem.BaseReg = 0;
650+
Res->Mem.DefaultBaseReg = 0;
642651
Res->Mem.IndexReg = 0;
643652
Res->Mem.Scale = 1;
644653
Res->Mem.Size = Size;
@@ -654,11 +663,14 @@ struct X86Operand final : public MCParsedAsmOperand {
654663
static std::unique_ptr<X86Operand>
655664
CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
656665
unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
657-
SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
658-
void *OpDecl = nullptr, unsigned FrontendSize = 0) {
666+
SMLoc EndLoc, unsigned Size = 0,
667+
unsigned DefaultBaseReg = X86::NoRegister,
668+
StringRef SymName = StringRef(), void *OpDecl = nullptr,
669+
unsigned FrontendSize = 0) {
659670
// We should never just have a displacement, that should be parsed as an
660671
// absolute memory operand.
661-
assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
672+
assert((SegReg || BaseReg || IndexReg || DefaultBaseReg) &&
673+
"Invalid memory operand!");
662674

663675
// The scale should always be one of {1,2,4,8}.
664676
assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
@@ -667,6 +679,7 @@ struct X86Operand final : public MCParsedAsmOperand {
667679
Res->Mem.SegReg = SegReg;
668680
Res->Mem.Disp = Disp;
669681
Res->Mem.BaseReg = BaseReg;
682+
Res->Mem.DefaultBaseReg = DefaultBaseReg;
670683
Res->Mem.IndexReg = IndexReg;
671684
Res->Mem.Scale = Scale;
672685
Res->Mem.Size = Size;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# RUN: llvm-ml -m32 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-32
2+
# RUN: llvm-ml -m64 -filetype=asm %s | FileCheck %s --check-prefix=CHECK-64
3+
4+
.code
5+
mov eax, [4]
6+
; CHECK-32: mov eax, dword ptr [4]
7+
; CHECK-64: mov eax, dword ptr [rip + 4]
8+
END

0 commit comments

Comments
 (0)