Skip to content

Commit

Permalink
[X86] Fix intel syntax push parsing bug
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283457 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
niravhdave committed Oct 6, 2016
1 parent 54de287 commit c8f9ada
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 2 deletions.
31 changes: 29 additions & 2 deletions lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -2810,11 +2811,37 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
}
}

SmallVector<unsigned, 8> 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<X86Operand *>(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<MCConstantExpr>(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<unsigned, 8> 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) {
Expand Down
23 changes: 23 additions & 0 deletions test/MC/X86/pr22028.s
Original file line number Diff line number Diff line change
@@ -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]

0 comments on commit c8f9ada

Please sign in to comment.