From ee554e6155d73714b9ee061b1583c396685ed4ba Mon Sep 17 00:00:00 2001 From: Nirav Dave Date: Thu, 6 Oct 2016 15:28:08 +0000 Subject: [PATCH] [X86] Fix intel syntax push parsing bug Change erroneous parsing of push immediate instructions in intel syntax to default to pointer size by rewriting into the ATT style for matching. This fixes PR22028. Reviewers: majnemer, rnk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D25288 llvm-svn: 283457 --- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 31 ++++++++++++++++++++++++-- llvm/test/MC/X86/pr22028.s | 23 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 llvm/test/MC/X86/pr22028.s diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 170f55c..eae22b8 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -2784,6 +2784,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, assert(Op.isToken() && "Leading operand should always be a mnemonic!"); StringRef Mnemonic = Op.getToken(); SMRange EmptyRange = None; + StringRef Base = Op.getToken(); // First, handle aliases that expand to multiple instructions. MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm); @@ -2810,11 +2811,37 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, } } + SmallVector Match; + uint64_t ErrorInfoMissingFeature = 0; + + // If unsized push has immediate operand we should default the default pointer + // size for the size. + if (Mnemonic == "push" && Operands.size() == 2) { + auto *X86Op = static_cast(Operands[1].get()); + if (X86Op->isImm()) { + // If it's not a constant fall through and let remainder take care of it. + const auto *CE = dyn_cast(X86Op->getImm()); + unsigned Size = getPointerWidth(); + if (CE && + (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) { + SmallString<16> Tmp; + Tmp += Base; + Tmp += (is64BitMode()) + ? "q" + : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " "; + Op.setTokenValue(Tmp); + // Do match in ATT mode to allow explicit suffix usage. + Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo, + MatchingInlineAsm, + false /*isParsingIntelSyntax()*/)); + Op.setTokenValue(Base); + } + } + } + // If an unsized memory operand is present, try to match with each memory // operand size. In Intel assembly, the size is not part of the instruction // mnemonic. - SmallVector Match; - uint64_t ErrorInfoMissingFeature = 0; if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; for (unsigned Size : MopSizes) { diff --git a/llvm/test/MC/X86/pr22028.s b/llvm/test/MC/X86/pr22028.s new file mode 100644 index 0000000..6ce7da0 --- /dev/null +++ b/llvm/test/MC/X86/pr22028.s @@ -0,0 +1,23 @@ +// RUN: llvm-mc -triple i386-unknown-unknown-code16 -show-encoding %s | FileCheck --check-prefix=CHECK16 %s +// RUN: llvm-mc -triple i386-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s +// RUN: llvm-mc -triple i686-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s + +.intel_syntax + +push 0 +push -1 +push 30 +push 257 +push 65536 + +//CHECK16: pushw $0 # encoding: [0x6a,0x00] +//CHECK16: pushw $-1 # encoding: [0x6a,0xff] +//CHECK16: pushw $30 # encoding: [0x6a,0x1e] +//CHECK16: pushw $257 # encoding: [0x68,0x01,0x01] +//CHECK16: pushl $65536 # encoding: [0x66,0x68,0x00,0x00,0x01,0x00] + +//CHECK: pushl $0 # encoding: [0x6a,0x00] +//CHECK: pushl $-1 # encoding: [0x6a,0xff] +//CHECK: pushl $30 # encoding: [0x6a,0x1e] +//CHECK: pushl $257 # encoding: [0x68,0x01,0x01,0x00,0x00] +//CHECK: pushl $65536 # encoding: [0x68,0x00,0x00,0x01,0x00] -- 2.7.4