diff --git a/clang/test/CodeGen/ms-inline-asm-functions.c b/clang/test/CodeGen/ms-inline-asm-functions.c --- a/clang/test/CodeGen/ms-inline-asm-functions.c +++ b/clang/test/CodeGen/ms-inline-asm-functions.c @@ -24,10 +24,9 @@ __asm call kimport; // CHECK: calll *({{.*}}) - // Broken case: Call through a global function pointer. + // Call through a global function pointer. __asm call kptr; - // CHECK: calll _kptr - // CHECK-FIXME: calll *_kptr + // CHECK: calll *_kptr } int bar(void) { diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -433,6 +433,7 @@ InlineAsmIdentifierInfo Info; short BracCount = 0; bool MemExpr = false; + bool BracketUsed = false; bool OffsetOperator = false; bool AttachToOperandIdx = false; bool IsPIC = false; @@ -455,6 +456,7 @@ void addImm(int64_t imm) { Imm += imm; } short getBracCount() const { return BracCount; } bool isMemExpr() const { return MemExpr; } + bool isBracketUsed() const { return BracketUsed; } bool isOffsetOperator() const { return OffsetOperator; } SMLoc getOffsetLoc() const { return OffsetOperatorLoc; } unsigned getBaseReg() const { return BaseReg; } @@ -955,6 +957,7 @@ break; } MemExpr = true; + BracketUsed = true; BracCount++; return false; } @@ -2628,9 +2631,9 @@ unsigned DefaultBaseReg = X86::NoRegister; bool MaybeDirectBranchDest = true; + bool IsUnconditionalBranch = + Name.equals_insensitive("jmp") || Name.equals_insensitive("call"); if (Parser.isParsingMasm()) { - bool IsUnconditionalBranch = - Name.equals_insensitive("jmp") || Name.equals_insensitive("call"); if (is64BitMode() && SM.getElementSize() > 0) { DefaultBaseReg = X86::RIP; } @@ -2652,6 +2655,9 @@ } } } + } else if (IsUnconditionalBranch) { + if (PtrInOperand || SM.isBracketUsed()) + MaybeDirectBranchDest = false; } if ((BaseReg || IndexReg || RegNo || DefaultBaseReg != X86::NoRegister)) diff --git a/llvm/test/MC/X86/intel-syntax-branch.s b/llvm/test/MC/X86/intel-syntax-branch.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/X86/intel-syntax-branch.s @@ -0,0 +1,71 @@ +// RUN: llvm-mc -triple i686-unknown-unknown -x86-asm-syntax=intel %s | FileCheck %s --check-prefixes=CHECK-32,CHECK +// RUN: llvm-mc -triple x86_64-unknown-unknown --defsym X64=1 -x86-asm-syntax=intel %s | FileCheck %s --check-prefixes=CHECK-64,CHECK + +// RUN: not llvm-mc -triple i686-unknown-unknown --defsym ERR=1 -x86-asm-syntax=intel %s 2>&1 | FileCheck %s --check-prefixes=ERR-32 + +t0: +call direct_branch +jmp direct_branch +// CHECK-LABEL: t0: +// CHECK-64: callq direct_branch +// CHECK-32: calll direct_branch +// CHECK: jmp direct_branch + +t1: +call [fn_ref] +jmp [fn_ref] +// CHECK-LABEL: t1: +// CHECK-64: callq *fn_ref +// CHECK-64: jmpq *fn_ref +// CHECK-32: calll *fn_ref +// CHECK-32: jmpl *fn_ref + +.ifdef X64 + + t2: + call qword ptr [fn_ref] + jmp qword ptr [fn_ref] + // CHECK-64-LABEL: t2: + // CHECK-64: callq *fn_ref + // CHECK-64: jmpq *fn_ref + + t3: + call qword ptr [rip + fn_ref] + jmp qword ptr [rip + fn_ref] + // CHECK-64-LABEL: t3: + // CHECK-64: callq *fn_ref(%rip) + // CHECK-64: jmpq *fn_ref(%rip) + +.else + + t4: + call dword ptr [fn_ref] + jmp dword ptr [fn_ref] + // CHECK-32-LABEL: t4: + // CHECK-32: calll *fn_ref + // CHECK-32: jmpl *fn_ref + + t5: + call dword ptr fn_ref + jmp dword ptr fn_ref + // CHECK-32-LABEL: t5: + // CHECK-32: calll *fn_ref + // CHECK-32: jmpl *fn_ref + + t6: + call dword ptr [offset fn_ref] + jmp dword ptr [offset fn_ref] + // CHECK-32-LABEL: t6: + // CHECK-32: calll *fn_ref + // CHECK-32: jmpl *fn_ref + +.ifdef ERR + + call offset fn_ref + // ERR-32: {{.*}}.s:[[#@LINE-1]]:3: error: invalid operand for instruction + jmp offset fn_ref + // ERR-32: {{.*}}.s:[[#@LINE-1]]:3: error: invalid operand for instruction + +.endif + +.endif