[x86] Make AsmParser validate registers for memory operands a bit better

We can't do a perfect job here. We *have* to allow (%dx) even in 64-bit
mode, for example, because it might be used for an unofficial form of
the in/out instructions. We actually want to do a better job of validation
*later*. Perhaps *instead* of doing it where we are at the moment.

But for now, doing what validation we *can* do in the place that the code
already has its validation, is an improvement.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198760 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Woodhouse 2014-01-08 12:58:28 +00:00
parent aab59870a4
commit ab5b9489e9
2 changed files with 54 additions and 4 deletions

View File

@ -1853,10 +1853,11 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
// If we reached here, then we just ate the ( of the memory operand. Process
// the rest of the memory operand.
unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
SMLoc IndexLoc;
SMLoc IndexLoc, BaseLoc;
if (getLexer().is(AsmToken::Percent)) {
SMLoc StartLoc, EndLoc;
BaseLoc = Parser.getTok().getLoc();
if (ParseRegister(BaseReg, StartLoc, EndLoc)) return 0;
if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
Error(StartLoc, "eiz and riz can only be used as index registers",
@ -1899,6 +1900,11 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
}
// Validate the scale amount.
if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
ScaleVal != 1) {
Error(Loc, "scale factor in 16-bit address must be 1");
return 0;
}
if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
return 0;
@ -1929,6 +1935,21 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
SMLoc MemEnd = Parser.getTok().getEndLoc();
Parser.Lex(); // Eat the ')'.
// Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
// and then only in non-64-bit modes. Except for DX, which is a special case
// because an unofficial form of in/out instructions uses it.
if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
(is64BitMode() || (BaseReg != X86::BX && BaseReg != X86::BP &&
BaseReg != X86::SI && BaseReg != X86::DI)) &&
BaseReg != X86::DX) {
Error(BaseLoc, "invalid 16-bit base register");
return 0;
}
if (BaseReg == 0 &&
X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {
Error(IndexLoc, "16-bit memory operand may not include only index register");
return 0;
}
// If we have both a base register and an index register make sure they are
// both 64-bit or 32-bit registers.
// To support VSIB, IndexReg can be 128-bit or 256-bit registers.
@ -1937,16 +1958,30 @@ X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg)) &&
IndexReg != X86::RIZ) {
Error(IndexLoc, "index register is 32-bit, but base register is 64-bit");
Error(BaseLoc, "base register is 64-bit, but index register is not");
return 0;
}
if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&
(X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) &&
IndexReg != X86::EIZ){
Error(IndexLoc, "index register is 64-bit, but base register is 32-bit");
Error(BaseLoc, "base register is 32-bit, but index register is not");
return 0;
}
if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {
if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {
Error(BaseLoc, "base register is 16-bit, but index register is not");
return 0;
}
if (((BaseReg == X86::BX || BaseReg == X86::BP) &&
IndexReg != X86::SI && IndexReg != X86::DI) ||
((BaseReg == X86::SI || BaseReg == X86::DI) &&
IndexReg != X86::BX && IndexReg != X86::BP)) {
Error(BaseLoc, "invalid 16-bit base/index register combination");
return 0;
}
}
}
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,

View File

@ -26,8 +26,23 @@ sysexitq
lea (%rsp, %rbp, $4), %rax
// rdar://10423777
// 64: error: index register is 32-bit, but base register is 64-bit
// 64: error: base register is 64-bit, but index register is not
movq (%rsi,%ecx),%xmm0
// 64: error: invalid 16-bit base register
movl %eax,(%bp,%si)
// 32: error: scale factor in 16-bit address must be 1
movl %eax,(%bp,%si,2)
// 32: error: invalid 16-bit base register
movl %eax,(%cx)
// 32: error: invalid 16-bit base/index register combination
movl %eax,(%bp,%bx)
// 32: error: 16-bit memory operand may not include only index register
movl %eax,(,%bx)
// 32: error: invalid operand for instruction
outb al, 4