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

Evgenii Kudriashov via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 26 11:15:10 PST 2025


https://github.com/e-kud updated https://github.com/llvm/llvm-project/pull/126073

>From 24d86a429164c782049cc3917149df4fa07e93f2 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Thu, 6 Feb 2025 05:08:09 -0800
Subject: [PATCH 1/3] [X86][AsmParser] Improve rel8 validation

* 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.
---
 llvm/lib/Target/X86/AsmParser/X86Operand.h   | 13 +++++--
 llvm/lib/Target/X86/X86InstrControl.td       | 15 ++++----
 llvm/lib/Target/X86/X86InstrOperands.td      | 15 ++++++--
 llvm/test/MC/X86/validate-inst-intel.s       | 36 ++++++++++++++++++++
 llvm/utils/TableGen/X86RecognizableInstr.cpp |  2 ++
 5 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h
index d715fd1903802..953ae76b2a63a 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 62cc758cc594b..4907105e6b8cc 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 4f427d6d9d72e..266d1dbe60624 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 466b906fee731..1b134e9891860 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 607a6bd27c21f..c296f0e0b16fd 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)

>From d60fbb3c51195dda637cffbcbbed69069d7de3db Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Wed, 26 Feb 2025 08:35:50 -0800
Subject: [PATCH 2/3] Allow label+offset combination for relocation

---
 llvm/lib/Target/X86/AsmParser/X86Operand.h | 5 ++---
 llvm/test/MC/X86/intel-syntax.s            | 6 ++++++
 llvm/test/MC/X86/validate-inst-intel.s     | 4 ++--
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h
index 953ae76b2a63a..9e1a7e020c5c2 100644
--- a/llvm/lib/Target/X86/AsmParser/X86Operand.h
+++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h
@@ -421,12 +421,11 @@ struct X86Operand final : public MCParsedAsmOperand {
   bool isDispImm8() const {
     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
       return isImmSExti64i8Value(CE->getValue());
-    return false;
+    return true;
   }
 
   bool isAbsMem8() const {
-    return isAbsMem() && isMem8() &&
-           (isa<MCSymbolRefExpr>(getMemDisp()) || isDispImm8());
+    return isAbsMem() && isMem8() && isDispImm8();
   }
 
   bool isMemUseUpRegs() const override { return UseUpRegs; }
diff --git a/llvm/test/MC/X86/intel-syntax.s b/llvm/test/MC/X86/intel-syntax.s
index c622832d24bea..386f42fa53d3b 100644
--- a/llvm/test/MC/X86/intel-syntax.s
+++ b/llvm/test/MC/X86/intel-syntax.s
@@ -2,6 +2,9 @@
 // RUN: FileCheck < %t %s
 // RUN: FileCheck --check-prefix=CHECK-STDERR < %t.err %s
 
+_nop_label:
+	nop
+
 _test:
 	xor	EAX, EAX
 	ret
@@ -825,6 +828,9 @@ fucomip st, st(2)
 // CHECK: fcompi  %st(2)
 // CHECK: fucompi  %st(2)
 
+jrcxz _nop_label
+jecxz _nop_label + 1
+
 loopz _foo
 loopnz _foo
 // CHECK: loope _foo
diff --git a/llvm/test/MC/X86/validate-inst-intel.s b/llvm/test/MC/X86/validate-inst-intel.s
index 1b134e9891860..abf84ca96ef45 100644
--- a/llvm/test/MC/X86/validate-inst-intel.s
+++ b/llvm/test/MC/X86/validate-inst-intel.s
@@ -14,9 +14,9 @@
 # CHECK:            ^
 
 	.text
-	loop BYTE PTR [SYM+4]
+	loop WORD PTR [SYM+4]
 # CHECK: error: invalid operand for instruction
-# CHECK:	loop BYTE PTR [SYM+4]
+# CHECK:	loop WORD PTR [SYM+4]
 # CHECK:        ^
 
 	.text

>From 886f28ada77f4eecb026776c61c2916a61834883 Mon Sep 17 00:00:00 2001
From: Evgenii Kudriashov <evgenii.kudriashov at intel.com>
Date: Wed, 26 Feb 2025 11:11:41 -0800
Subject: [PATCH 3/3] Formatting

---
 llvm/lib/Target/X86/AsmParser/X86Operand.h | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86Operand.h b/llvm/lib/Target/X86/AsmParser/X86Operand.h
index 9e1a7e020c5c2..1fa82a16860c8 100644
--- a/llvm/lib/Target/X86/AsmParser/X86Operand.h
+++ b/llvm/lib/Target/X86/AsmParser/X86Operand.h
@@ -419,14 +419,12 @@ struct X86Operand final : public MCParsedAsmOperand {
   bool isAbsMemMode16() const { return isAbsMem() && Mem.ModeSize == 16; }
 
   bool isDispImm8() const {
-    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
+    if (auto *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
       return isImmSExti64i8Value(CE->getValue());
     return true;
   }
 
-  bool isAbsMem8() const {
-    return isAbsMem() && isMem8() && isDispImm8();
-  }
+  bool isAbsMem8() const { return isAbsMem() && isMem8() && isDispImm8(); }
 
   bool isMemUseUpRegs() const override { return UseUpRegs; }
 



More information about the llvm-commits mailing list