Skip to content

Commit

Permalink
ms inline asm: Fix {call,jmp} fptr (#73207)
Browse files Browse the repository at this point in the history
https://reviews.llvm.org/D151863 (2023-05) removed
`BaseReg = BaseReg ? BaseReg : 1` (introduced in commit
175d0ae (2013)) and caused a
regression: ensuring a non-zero `BaseReg` was to treat
`static void (*fptr)(); __asm { call fptr }` as non-`AbsMem`
`AsmOperandClass` and generate `call $0`/`callq *fptr(%rip)` instead of
`call ${0:P}`/`callq *fptr`
(The asm template argument modifier `P` is for call targets, while
no modifier is used by other instructions like `mov rax, fptr`)

This patch reinstates the BaseReg-setting statement but places it inside
`if (IsGlobalLV)` for clarify.

The special case is unfortunate, but we also have special case in
similar places (https://reviews.llvm.org/D149920).

Fix: #73033
  • Loading branch information
MaskRay committed Nov 27, 2023
1 parent bf95a0c commit c449460
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
7 changes: 6 additions & 1 deletion clang/test/CodeGen/ms-inline-asm-64.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,22 @@ int t4(void) {
}

void bar() {}
static void (*fptr)();

void t5(void) {
__asm {
call bar
jmp bar
call fptr
jmp fptr
}
// CHECK: t5
// CHECK: call void asm sideeffect inteldialect
// CHECK-SAME: call ${0:P}
// CHECK-SAME: jmp ${1:P}
// CHECK-SAME: "*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(void (...)) @bar, ptr elementtype(void (...)) @bar)
// CHECK-SAME: call $2
// CHECK-SAME: jmp $3
// CHECK-SAME: "*m,*m,*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr elementtype(void (...)) @bar, ptr elementtype(void (...)) @bar, ptr elementtype(ptr) @fptr, ptr elementtype(ptr) @fptr)
}

void t47(void) {
Expand Down
38 changes: 23 additions & 15 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1143,8 +1143,8 @@ class X86AsmParser : public MCTargetAsmParser {
bool ParseIntelMemoryOperandSize(unsigned &Size);
bool CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End,
unsigned Size, StringRef Identifier,
unsigned Scale, bool NonAbsMem, SMLoc Start,
SMLoc End, unsigned Size, StringRef Identifier,
const InlineAsmIdentifierInfo &Info,
OperandVector &Operands);

Expand Down Expand Up @@ -1744,10 +1744,13 @@ bool X86AsmParser::parseOperand(OperandVector &Operands, StringRef Name) {
return parseATTOperand(Operands);
}

bool X86AsmParser::CreateMemForMSInlineAsm(
unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg,
unsigned Scale, SMLoc Start, SMLoc End, unsigned Size, StringRef Identifier,
const InlineAsmIdentifierInfo &Info, OperandVector &Operands) {
bool X86AsmParser::CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,
unsigned BaseReg, unsigned IndexReg,
unsigned Scale, bool NonAbsMem,
SMLoc Start, SMLoc End,
unsigned Size, StringRef Identifier,
const InlineAsmIdentifierInfo &Info,
OperandVector &Operands) {
// If we found a decl other than a VarDecl, then assume it is a FuncDecl or
// some other label reference.
if (Info.isKind(InlineAsmIdentifierInfo::IK_Label)) {
Expand All @@ -1772,11 +1775,15 @@ bool X86AsmParser::CreateMemForMSInlineAsm(
}
// It is widely common for MS InlineAsm to use a global variable and one/two
// registers in a mmory expression, and though unaccessible via rip/eip.
if (IsGlobalLV && (BaseReg || IndexReg)) {
Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
End, Size, Identifier, Decl, 0,
BaseReg && IndexReg));
return false;
if (IsGlobalLV) {
if (BaseReg || IndexReg) {
Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
End, Size, Identifier, Decl, 0,
BaseReg && IndexReg));
return false;
}
if (NonAbsMem)
BaseReg = 1; // Make isAbsMem() false
}
Operands.push_back(X86Operand::CreateMem(
getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End,
Expand Down Expand Up @@ -2620,18 +2627,19 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
ErrMsg))
return Error(Start, ErrMsg);
bool IsUnconditionalBranch =
Name.equals_insensitive("jmp") || Name.equals_insensitive("call");
if (isParsingMSInlineAsm())
return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start,
End, Size, SM.getSymName(),
return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale,
IsUnconditionalBranch && is64BitMode(),
Start, End, Size, SM.getSymName(),
SM.getIdentifierInfo(), Operands);

// When parsing x64 MS-style assembly, all non-absolute references to a named
// variable default to RIP-relative.
unsigned DefaultBaseReg = X86::NoRegister;
bool MaybeDirectBranchDest = true;

bool IsUnconditionalBranch =
Name.equals_insensitive("jmp") || Name.equals_insensitive("call");
if (Parser.isParsingMasm()) {
if (is64BitMode() && SM.getElementSize() > 0) {
DefaultBaseReg = X86::RIP;
Expand Down

0 comments on commit c449460

Please sign in to comment.