[llvm] [X86][AsmParser] Improve rel8 validation (PR #126073)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 6 06:11:11 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-tablegen

Author: Evgenii Kudriashov (e-kud)

<details>
<summary>Changes</summary>

* Check that input of rel8 operand is either a symbol or 8 bit immediate
* Rename AbsMem16 related names to AbsMemMode16 to disambiguate mem size and mode checks.

---
Full diff: https://github.com/llvm/llvm-project/pull/126073.diff


5 Files Affected:

- (modified) llvm/lib/Target/X86/AsmParser/X86Operand.h (+11-2) 
- (modified) llvm/lib/Target/X86/X86InstrControl.td (+9-6) 
- (modified) llvm/lib/Target/X86/X86InstrOperands.td (+12-3) 
- (modified) llvm/test/MC/X86/validate-inst-intel.s (+36) 
- (modified) llvm/utils/TableGen/X86RecognizableInstr.cpp (+2) 


``````````diff
diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h
index d715fd1903802f6..953ae76b2a63aa7 100644
--- a/llvm/lib/Target/X86/AsmParser/X86Operand.h
+++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h
@@ -416,8 +416,17 @@ struct X86Operand final : public MCParsedAsmOperand {
       return isImm();
   }
 
-  bool isAbsMem16() const {
-    return isAbsMem() && Mem.ModeSize == 16;
+  bool isAbsMemMode16() const { return isAbsMem() && Mem.ModeSize == 16; }
+
+  bool isDispImm8() const {
+    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
+      return isImmSExti64i8Value(CE->getValue());
+    return false;
+  }
+
+  bool isAbsMem8() const {
+    return isAbsMem() && isMem8() &&
+           (isa<MCSymbolRefExpr>(getMemDisp()) || isDispImm8());
   }
 
   bool isMemUseUpRegs() const override { return UseUpRegs; }
diff --git a/llvm/lib/Target/X86/X86InstrControl.td b/llvm/lib/Target/X86/X86InstrControl.td
index 62cc758cc594bda..4907105e6b8ccfd 100644
--- a/llvm/lib/Target/X86/X86InstrControl.td
+++ b/llvm/lib/Target/X86/X86InstrControl.td
@@ -94,14 +94,14 @@ let isBranch = 1, isTerminator = 1, hasSideEffects = 0, SchedRW = [WriteJump] in
   // 32-bit mode, the address size prefix is jcxz and the unprefixed version is
   // jecxz.
   let Uses = [CX] in
-    def JCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst),
+    def JCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins i8imm_brtarget:$dst),
                         "jcxz\t$dst", []>, AdSize16, Requires<[Not64BitMode]>;
   let Uses = [ECX] in
-    def JECXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst),
+    def JECXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins i8imm_brtarget:$dst),
                         "jecxz\t$dst", []>, AdSize32;
 
   let Uses = [RCX] in
-    def JRCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst),
+    def JRCXZ : Ii8PCRel<0xE3, RawFrm, (outs), (ins i8imm_brtarget:$dst),
                          "jrcxz\t$dst", []>, AdSize64, Requires<[In64BitMode]>;
 }
 
@@ -193,9 +193,12 @@ def JMPABS64i : Ii64<0xA1, RawFrm, (outs), (ins i64imm:$dst), "jmpabs\t$dst", []
 
 // Loop instructions
 let isBranch = 1, isTerminator = 1, SchedRW = [WriteJump] in {
-def LOOP   : Ii8PCRel<0xE2, RawFrm, (outs), (ins brtarget8:$dst), "loop\t$dst", []>;
-def LOOPE  : Ii8PCRel<0xE1, RawFrm, (outs), (ins brtarget8:$dst), "loope\t$dst", []>;
-def LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins brtarget8:$dst), "loopne\t$dst", []>;
+  def LOOP   : Ii8PCRel<0xE2, RawFrm, (outs), (ins i8imm_brtarget:$dst),
+                        "loop\t$dst", []>;
+  def LOOPE  : Ii8PCRel<0xE1, RawFrm, (outs), (ins i8imm_brtarget:$dst),
+                        "loope\t$dst", []>;
+  def LOOPNE : Ii8PCRel<0xE0, RawFrm, (outs), (ins i8imm_brtarget:$dst),
+                        "loopne\t$dst", []>;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/X86/X86InstrOperands.td b/llvm/lib/Target/X86/X86InstrOperands.td
index 4f427d6d9d72ea0..266d1dbe6062410 100644
--- a/llvm/lib/Target/X86/X86InstrOperands.td
+++ b/llvm/lib/Target/X86/X86InstrOperands.td
@@ -142,8 +142,14 @@ def i64mem_TC : X86MemOperand<"printqwordmem", X86Mem64AsmOperand, 64> {
 }
 
 // Special parser to detect 16-bit mode to select 16-bit displacement.
-def X86AbsMem16AsmOperand : AsmOperandClass {
-  let Name = "AbsMem16";
+def X86AbsMemMode16AsmOperand : AsmOperandClass {
+  let Name = "AbsMemMode16";
+  let RenderMethod = "addAbsMemOperands";
+  let SuperClasses = [X86AbsMemAsmOperand];
+}
+
+def X86AbsMem8AsmOperand : AsmOperandClass {
+  let Name = "AbsMem8";
   let RenderMethod = "addAbsMemOperands";
   let SuperClasses = [X86AbsMemAsmOperand];
 }
@@ -157,6 +163,9 @@ class BranchTargetOperand<ValueType ty> : Operand<ty> {
 
 def i32imm_brtarget : BranchTargetOperand<i32>;
 def i16imm_brtarget : BranchTargetOperand<i16>;
+def i8imm_brtarget : BranchTargetOperand<i8> {
+  let ParserMatchClass = X86AbsMem8AsmOperand;
+}
 
 // 64-bits but only 32 bits are significant, and those bits are treated as being
 // pc relative.
@@ -165,7 +174,7 @@ def i64i32imm_brtarget : BranchTargetOperand<i64>;
 def brtarget : BranchTargetOperand<OtherVT>;
 def brtarget8 : BranchTargetOperand<OtherVT>;
 def brtarget16 : BranchTargetOperand<OtherVT> {
-  let ParserMatchClass = X86AbsMem16AsmOperand;
+  let ParserMatchClass = X86AbsMemMode16AsmOperand;
 }
 def brtarget32 : BranchTargetOperand<OtherVT>;
 
diff --git a/llvm/test/MC/X86/validate-inst-intel.s b/llvm/test/MC/X86/validate-inst-intel.s
index 466b906fee731ea..1b134e9891860ad 100644
--- a/llvm/test/MC/X86/validate-inst-intel.s
+++ b/llvm/test/MC/X86/validate-inst-intel.s
@@ -13,3 +13,39 @@
 # CHECK:	int -129
 # CHECK:            ^
 
+	.text
+	loop BYTE PTR [SYM+4]
+# CHECK: error: invalid operand for instruction
+# CHECK:	loop BYTE PTR [SYM+4]
+# CHECK:        ^
+
+	.text
+	loope BYTE PTR [128]
+# CHECK: error: invalid operand for instruction
+# CHECK:	loope BYTE PTR [128]
+# CHECK:        ^
+
+	.text
+	loopne BYTE PTR [-129]
+# CHECK: error: invalid operand for instruction
+# CHECK:	loopne BYTE PTR [-129]
+# CHECK:        ^
+
+	.text
+	jrcxz XMMWORD PTR [0]
+# CHECK: error: invalid operand for instruction
+# CHECK:	jrcxz XMMWORD PTR [0]
+# CHECK:        ^
+
+	.text
+	jecxz BYTE PTR[-444]
+# CHECK: error: invalid operand for instruction
+# CHECK:	jecxz BYTE PTR[-444]
+# CHECK:        ^
+
+	.text
+	jcxz BYTE PTR[444]
+# CHECK: error: invalid operand for instruction
+# CHECK:	jcxz BYTE PTR[444]
+# CHECK:        ^
+
diff --git a/llvm/utils/TableGen/X86RecognizableInstr.cpp b/llvm/utils/TableGen/X86RecognizableInstr.cpp
index 607a6bd27c21f78..c296f0e0b16fd92 100644
--- a/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -1087,6 +1087,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
   TYPE("i512mem_GR32", TYPE_M)
   TYPE("i512mem_GR64", TYPE_M)
   TYPE("i64i32imm_brtarget", TYPE_REL)
+  TYPE("i8imm_brtarget", TYPE_REL)
   TYPE("i16imm_brtarget", TYPE_REL)
   TYPE("i32imm_brtarget", TYPE_REL)
   TYPE("ccode", TYPE_IMM)
@@ -1405,6 +1406,7 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s,
   ENCODING("i64i32imm_brtarget", ENCODING_ID)
   ENCODING("i16imm_brtarget", ENCODING_IW)
   ENCODING("i32imm_brtarget", ENCODING_ID)
+  ENCODING("i8imm_brtarget", ENCODING_IB)
   ENCODING("brtarget32", ENCODING_ID)
   ENCODING("brtarget16", ENCODING_IW)
   ENCODING("brtarget8", ENCODING_IB)

``````````

</details>


https://github.com/llvm/llvm-project/pull/126073


More information about the llvm-commits mailing list