Skip to content

Commit 79a69f5

Browse files
committed
[X86] Error on using h-registers with REX prefix in the assembler instead of leaving it to a fatal error in the encoder.
Using a fatal error is bad for user experience. Reviewed By: pengfei Differential Revision: https://reviews.llvm.org/D89837
1 parent d9f91a3 commit 79a69f5

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,6 @@ bool X86AsmParser::MatchRegisterByName(unsigned &RegNo, StringRef RegName,
12101210
// FIXME: This should be done using Requires<Not64BitMode> and
12111211
// Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
12121212
// checked.
1213-
// FIXME: Check AH, CH, DH, BH cannot be used in an instruction requiring a
1214-
// REX prefix.
12151213
if (RegNo == X86::RIZ || RegNo == X86::RIP ||
12161214
X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
12171215
X86II::isX86_64NonExtLowByteReg(RegNo) ||
@@ -3619,6 +3617,33 @@ bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {
36193617
}
36203618
}
36213619

3620+
const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3621+
// Check that we aren't mixing AH/BH/CH/DH with REX prefix. We only need to
3622+
// check this with the legacy encoding, VEX/EVEX/XOP don't use REX.
3623+
if ((MCID.TSFlags & X86II::EncodingMask) == 0) {
3624+
MCPhysReg HReg = X86::NoRegister;
3625+
bool UsesRex = MCID.TSFlags & X86II::REX_W;
3626+
unsigned NumOps = Inst.getNumOperands();
3627+
for (unsigned i = 0; i != NumOps; ++i) {
3628+
const MCOperand &MO = Inst.getOperand(i);
3629+
if (!MO.isReg())
3630+
continue;
3631+
unsigned Reg = MO.getReg();
3632+
if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
3633+
HReg = Reg;
3634+
if (X86II::isX86_64NonExtLowByteReg(Reg) ||
3635+
X86II::isX86_64ExtendedReg(Reg))
3636+
UsesRex = true;
3637+
}
3638+
3639+
if (UsesRex && HReg != X86::NoRegister) {
3640+
StringRef RegName = X86IntelInstPrinter::getRegisterName(HReg);
3641+
return Error(Ops[0]->getStartLoc(),
3642+
"can't encode '" + RegName + "' in an instruction requiring "
3643+
"REX prefix.");
3644+
}
3645+
}
3646+
36223647
return false;
36233648
}
36243649

@@ -3989,6 +4014,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
39894014
unsigned NumSuccessfulMatches =
39904015
std::count(std::begin(Match), std::end(Match), Match_Success);
39914016
if (NumSuccessfulMatches == 1) {
4017+
if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
4018+
return true;
39924019
// Some instructions need post-processing to, for example, tweak which
39934020
// encoding is selected. Loop on it while changes happen so the
39944021
// individual transformations can chain off each other.

llvm/test/MC/X86/encoder-fail.s

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1-
// RUN: not --crash llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2>&1 | FileCheck %s
2-
// CHECK: LLVM ERROR: Cannot encode high byte register in REX-prefixed instruction
3-
movzx %dh, %rsi
1+
// RUN: not llvm-mc -triple x86_64-unknown-unknown --show-encoding %s 2>&1 | FileCheck %s
2+
3+
// CHECK: error: can't encode 'dh' in an instruction requiring REX prefix.
4+
movzx %dh, %rsi
5+
6+
// CHECK: error: can't encode 'ah' in an instruction requiring REX prefix.
7+
movzx %ah, %r8d
8+
9+
// CHECK: error: can't encode 'bh' in an instruction requiring REX prefix.
10+
add %bh, %sil
11+
12+
// CHECK: error: can't encode 'ch' in an instruction requiring REX prefix.
13+
mov %ch, (%r8)
14+
15+
// CHECK: error: can't encode 'dh' in an instruction requiring REX prefix.
16+
mov %dh, (%rax,%r8)

0 commit comments

Comments
 (0)