From a8e5e7371173cd13813bdefef537d502c0ecbe58 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 10 Aug 2019 04:28:52 +0000 Subject: [PATCH] [X86] Improve the diagnostic for larger than 4-bit immediate for vpermil2pd/ps. Only allow MCConstantExprs. llvm-svn: 368505 --- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 18 ++++++++++++++++++ llvm/lib/Target/X86/AsmParser/X86Operand.h | 6 +++--- llvm/lib/Target/X86/X86InstrInfo.td | 1 + llvm/test/MC/X86/x86_errors.s | 4 ++-- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 95cbf46..c369c16 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -955,6 +955,8 @@ private: public: enum X86MatchResultTy { Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY, +#define GET_OPERAND_DIAGNOSTIC_TYPES +#include "X86GenAsmMatcher.inc" }; X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser, @@ -3173,6 +3175,13 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, EmitInstruction(Inst, Operands, Out); Opcode = Inst.getOpcode(); return false; + case Match_InvalidImmUnsignedi4: { + SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + return Error(ErrorLoc, "immediate must be an integer in range [0, 15]", + EmptyRange, MatchingInlineAsm); + } case Match_MissingFeature: return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm); case Match_InvalidOperand: @@ -3520,6 +3529,15 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, MatchingInlineAsm); } + if (std::count(std::begin(Match), std::end(Match), + Match_InvalidImmUnsignedi4) == 1) { + SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + return Error(ErrorLoc, "immediate must be an integer in range [0, 15]", + EmptyRange, MatchingInlineAsm); + } + // If all of these were an outright failure, report it in a useless way. return Error(IDLoc, "unknown instruction mnemonic", EmptyRange, MatchingInlineAsm); diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h index 591e6f4..3747995 100644 --- a/llvm/lib/Target/X86/AsmParser/X86Operand.h +++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h @@ -262,10 +262,10 @@ struct X86Operand final : public MCParsedAsmOperand { bool isImmUnsignedi4() const { if (!isImm()) return false; - // If this isn't a constant expr, just assume it fits and let relaxation - // handle it. + // If this isn't a constant expr, reject it. The immediate byte is shared + // with a register encoding. We can't have it affected by a relocation. const MCConstantExpr *CE = dyn_cast(getImm()); - if (!CE) return true; + if (!CE) return false; return isImmUnsignedi4Value(CE->getValue()); } diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 7b765a1..5a5df5e 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -678,6 +678,7 @@ def ImmSExti64i8AsmOperand : ImmSExtAsmOperandClass { def ImmUnsignedi4AsmOperand : AsmOperandClass { let Name = "ImmUnsignedi4"; let RenderMethod = "addImmOperands"; + let DiagnosticType = "InvalidImmUnsignedi4"; } // Unsigned immediate used by SSE/AVX instructions diff --git a/llvm/test/MC/X86/x86_errors.s b/llvm/test/MC/X86/x86_errors.s index 5e44aaa..f9cdc15 100644 --- a/llvm/test/MC/X86/x86_errors.s +++ b/llvm/test/MC/X86/x86_errors.s @@ -180,6 +180,6 @@ cmpxchg16b (%eax) // 64: error: unsupported instruction {evex} vmovdqu %xmm0, %xmm0 -// 32: 12: error: invalid operand for instruction -// 64: 12: error: invalid operand for instruction +// 32: 12: error: immediate must be an integer in range [0, 15] +// 64: 12: error: immediate must be an integer in range [0, 15] vpermil2pd $16, %xmm3, %xmm5, %xmm1, %xmm2 -- 2.7.4