Skip to content

Commit ee554e6

Browse files
committedOct 6, 2016
[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
1 parent a5ee898 commit ee554e6

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed
 

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

+29-2
Original file line numberDiff line numberDiff line change
@@ -2784,6 +2784,7 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
27842784
assert(Op.isToken() && "Leading operand should always be a mnemonic!");
27852785
StringRef Mnemonic = Op.getToken();
27862786
SMRange EmptyRange = None;
2787+
StringRef Base = Op.getToken();
27872788

27882789
// First, handle aliases that expand to multiple instructions.
27892790
MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm);
@@ -2810,11 +2811,37 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
28102811
}
28112812
}
28122813

2814+
SmallVector<unsigned, 8> Match;
2815+
uint64_t ErrorInfoMissingFeature = 0;
2816+
2817+
// If unsized push has immediate operand we should default the default pointer
2818+
// size for the size.
2819+
if (Mnemonic == "push" && Operands.size() == 2) {
2820+
auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
2821+
if (X86Op->isImm()) {
2822+
// If it's not a constant fall through and let remainder take care of it.
2823+
const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
2824+
unsigned Size = getPointerWidth();
2825+
if (CE &&
2826+
(isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
2827+
SmallString<16> Tmp;
2828+
Tmp += Base;
2829+
Tmp += (is64BitMode())
2830+
? "q"
2831+
: (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
2832+
Op.setTokenValue(Tmp);
2833+
// Do match in ATT mode to allow explicit suffix usage.
2834+
Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
2835+
MatchingInlineAsm,
2836+
false /*isParsingIntelSyntax()*/));
2837+
Op.setTokenValue(Base);
2838+
}
2839+
}
2840+
}
2841+
28132842
// If an unsized memory operand is present, try to match with each memory
28142843
// operand size. In Intel assembly, the size is not part of the instruction
28152844
// mnemonic.
2816-
SmallVector<unsigned, 8> Match;
2817-
uint64_t ErrorInfoMissingFeature = 0;
28182845
if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
28192846
static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
28202847
for (unsigned Size : MopSizes) {

‎llvm/test/MC/X86/pr22028.s

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: llvm-mc -triple i386-unknown-unknown-code16 -show-encoding %s | FileCheck --check-prefix=CHECK16 %s
2+
// RUN: llvm-mc -triple i386-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s
3+
// RUN: llvm-mc -triple i686-unknown-unknown -show-encoding %s | FileCheck --check-prefix=CHECK %s
4+
5+
.intel_syntax
6+
7+
push 0
8+
push -1
9+
push 30
10+
push 257
11+
push 65536
12+
13+
//CHECK16: pushw $0 # encoding: [0x6a,0x00]
14+
//CHECK16: pushw $-1 # encoding: [0x6a,0xff]
15+
//CHECK16: pushw $30 # encoding: [0x6a,0x1e]
16+
//CHECK16: pushw $257 # encoding: [0x68,0x01,0x01]
17+
//CHECK16: pushl $65536 # encoding: [0x66,0x68,0x00,0x00,0x01,0x00]
18+
19+
//CHECK: pushl $0 # encoding: [0x6a,0x00]
20+
//CHECK: pushl $-1 # encoding: [0x6a,0xff]
21+
//CHECK: pushl $30 # encoding: [0x6a,0x1e]
22+
//CHECK: pushl $257 # encoding: [0x68,0x01,0x01,0x00,0x00]
23+
//CHECK: pushl $65536 # encoding: [0x68,0x00,0x00,0x01,0x00]

0 commit comments

Comments
 (0)
Please sign in to comment.