[llvm] [X86][AsmParser] Support parentheses around scale and index register in Intel syntax (PR #211003)

Wiktor Ludwichowski via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 06:08:20 PDT 2026


https://github.com/AlnandoFeronso updated https://github.com/llvm/llvm-project/pull/211003

>From 52eee91f5497c1038f04edce2da15d553d440844 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Tue, 21 Jul 2026 12:59:05 +0200
Subject: [PATCH 1/8] [X86][AsmParser] Support parentheses around scale and
 index register in Intel syntax

---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 156 ++++++++++--------
 ...-syntax-scale-register-parentheses-error.s |  23 +++
 .../intel-syntax-scale-register-parentheses.s |  75 +++++++++
 3 files changed, 188 insertions(+), 66 deletions(-)
 create mode 100644 llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
 create mode 100644 llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 54edcba34a7e9..cbd66c6808749 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -45,6 +45,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <memory>
+#include <optional>
 
 using namespace llvm;
 
@@ -445,6 +446,7 @@ class X86AsmParser : public MCTargetAsmParser {
     IntelExprState State = IES_INIT, PrevState = IES_ERROR;
     MCRegister BaseReg, IndexReg, TmpReg;
     unsigned Scale = 0;
+    std::optional<unsigned> TmpScale = {};
     int64_t Imm = 0;
     const MCExpr *Sym = nullptr;
     StringRef SymName;
@@ -700,20 +702,27 @@ class X86AsmParser : public MCTargetAsmParser {
         IC.pushOperator(IC_PLUS);
         NegativeAdditiveTerm = false;
         NegativeAdditiveTermLoc = SMLoc();
-        if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
-          // If we already have a BaseReg, then assume this is the IndexReg with
-          // no explicit scale.
-          if (!BaseReg) {
+        if (TmpReg) {
+          // A pending scale forces this to be the IndexReg; otherwise a free
+          // BaseReg takes it as an unscaled base.
+          if (!BaseReg && !TmpScale.has_value()) {
             BaseReg = TmpReg;
+            TmpReg = MCRegister::NoRegister;
           } else {
             if (IndexReg)
               return regsUseUpError(ErrMsg);
             IndexReg = TmpReg;
-            Scale = 0;
+            TmpReg = MCRegister::NoRegister;
+            if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
+              return true;
+            }
+            Scale = TmpScale.value_or(0);
           }
         }
         break;
       }
+      // A '+' ends the current additive term, so clear the pending scale.
+      TmpScale.reset();
       PrevState = CurrState;
       return false;
     }
@@ -761,20 +770,27 @@ class X86AsmParser : public MCTargetAsmParser {
           return true;
         } else
           IC.pushOperator(IC_NEG);
-        if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
-          // If we already have a BaseReg, then assume this is the IndexReg with
-          // no explicit scale.
-          if (!BaseReg) {
+        if (TmpReg) {
+          // A pending scale forces this to be the IndexReg; otherwise a free
+          // BaseReg takes it as an unscaled base.
+          if (!BaseReg && !TmpScale.has_value()) {
             BaseReg = TmpReg;
+            TmpReg = MCRegister::NoRegister;
           } else {
             if (IndexReg)
               return regsUseUpError(ErrMsg);
             IndexReg = TmpReg;
-            Scale = 0;
+            TmpReg = MCRegister::NoRegister;
+            if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
+              return true;
+            }
+            Scale = TmpScale.value_or(0);
           }
         }
         break;
       }
+      // A '-' ends the current additive term, so clear the pending scale.
+      TmpScale.reset();
       PrevState = CurrState;
       return false;
     }
@@ -816,33 +832,42 @@ class X86AsmParser : public MCTargetAsmParser {
       default:
         State = IES_ERROR;
         break;
-      case IES_PLUS:
       case IES_MINUS:
-      case IES_LPAREN:
+      case IES_PLUS:
       case IES_LBRAC:
         State = IES_REGISTER;
         TmpReg = Reg;
         IC.pushOperand(IC_REGISTER);
+        if (NegativeAdditiveTerm) {
+          ErrMsg = "Scale can't be negative";
+          return true;
+        }
         break;
+      case IES_LPAREN:
       case IES_MULTIPLY:
-        // Index Register - Scale * Register
-        if (PrevState == IES_INTEGER) {
+        // A register already held in TmpReg means we are multiplying two reg
+        if (TmpReg) {
+          ErrMsg = "Register can't be multiplied with register!";
+          return true;
+        }
+        State = IES_REGISTER;
+        TmpReg = Reg;
+        // Recognize this register as a scaled index register. This covers
+        // 'scale * reg' and 'scale * (reg)', including parenthesized or
+        // multi-factor scales where the accumulated value is held in TmpScale.
+        if (TmpScale.has_value() || PrevState == IES_MULTIPLY ||
+            (PrevState == IES_INTEGER && CurrState == IES_MULTIPLY)) {
           if (IndexReg)
             return regsUseUpError(ErrMsg);
           if (NegativeAdditiveTerm) {
             ErrMsg = "Scale can't be negative";
             return true;
           }
-          State = IES_REGISTER;
-          IndexReg = Reg;
-          // Get the scale and replace the 'Scale * Register' with '0'.
-          Scale = IC.popOperand();
-          if (checkScale(Scale, ErrMsg))
-            return true;
+          // Push an immediate, not the register, so the infix calculator
+          // won't evaluate reg * int; this is a scaled index reg.
           IC.pushOperand(IC_IMM);
-          IC.popOperator();
         } else {
-          State = IES_ERROR;
+          IC.pushOperand(IC_REGISTER);
         }
         break;
       }
@@ -911,23 +936,16 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_INIT:
       case IES_LBRAC:
         State = IES_INTEGER;
-        if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
-          // Index Register - Register * Scale
-          if (IndexReg)
-            return regsUseUpError(ErrMsg);
-          if (NegativeAdditiveTerm) {
-            ErrMsg = "Scale can't be negative";
-            return true;
-          }
-          IndexReg = TmpReg;
-          Scale = TmpInt;
-          if (checkScale(Scale, ErrMsg))
-            return true;
-          // Get the scale and replace the 'Register * Scale' with '0'.
-          IC.popOperator();
+        // Accumulate the scale: multiply into a pending scale or seed it.
+        if (TmpScale.has_value()) {
+          TmpScale.value() *= TmpInt;
         } else {
-          IC.pushOperand(IC_IMM, TmpInt);
+          TmpScale = TmpInt;
         }
+        // Once an index register is pending, check if TmpScale is valid.
+        if (TmpReg && checkScale(TmpScale.value(), ErrMsg))
+          return true;
+        IC.pushOperand(IC_IMM, TmpInt);
         break;
       }
       PrevState = CurrState;
@@ -940,10 +958,26 @@ class X86AsmParser : public MCTargetAsmParser {
         State = IES_ERROR;
         break;
       case IES_INTEGER:
+        // Seed the scale accumulator with the integer just parsed (the left
+        // operand of this '*'), reading it back from the operand stack.
+        if (!TmpScale.has_value()) {
+          TmpScale = IC.popOperand();
+          IC.pushOperand(IC_IMM, TmpScale.value());
+        }
+        State = IES_MULTIPLY;
+        IC.pushOperator(IC_MULTIPLY);
+        break;
       case IES_REGISTER:
       case IES_RPAREN:
-        State = IES_MULTIPLY;
+        // A register before '*' is a scaled index register. If no scale is
+        // pending yet, replace its operand-stack entry with an immediate so
+        // the infix calculator does not evaluate a reg * int product.
+        if (TmpReg && (!TmpScale.has_value())) {
+          IC.popOperand();
+          IC.pushOperand(IC_IMM);
+        }
         IC.pushOperator(IC_MULTIPLY);
+        State = IES_MULTIPLY;
         break;
       }
     }
@@ -993,6 +1027,8 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_CAST:
         assert(!BracCount && "BracCount should be zero on parsing's start");
         State = IES_LBRAC;
+        // Entering a new memory expression; clear the pending scale.
+        TmpScale.reset();
         break;
       }
       MemExpr = true;
@@ -1015,26 +1051,34 @@ class X86AsmParser : public MCTargetAsmParser {
           return true;
         }
         State = IES_RBRAC;
-        if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
-          // If we already have a BaseReg, then assume this is the IndexReg with
-          // no explicit scale.
-          if (!BaseReg) {
+
+        if (TmpReg) {
+          // A pending scale forces this to be the IndexReg; otherwise a free
+          // BaseReg takes it as an unscaled base.
+          if (!BaseReg && !TmpScale.has_value()) {
             BaseReg = TmpReg;
-          } else {
-            if (IndexReg)
-              return regsUseUpError(ErrMsg);
+            TmpReg = MCRegister::NoRegister;
+          } else if (!IndexReg) {
             if (NegativeAdditiveTerm) {
               ErrMsg = "Scale can't be negative";
               return true;
             }
             IndexReg = TmpReg;
-            Scale = 0;
+            TmpReg = MCRegister::NoRegister;
+            if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
+                return true;
+            }
+            Scale = TmpScale.value_or(0);
+          } else {
+            return regsUseUpError(ErrMsg);
           }
         }
         NegativeAdditiveTerm = false;
         NegativeAdditiveTermLoc = SMLoc();
         break;
       }
+      // Leaving the memory expression; clear the pending scale.
+      TmpScale.reset();
       PrevState = CurrState;
       return false;
     }
@@ -1082,26 +1126,6 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_RBRAC:
       case IES_RPAREN:
         State = IES_RPAREN;
-        // In the case of a multiply, onRegister has already set IndexReg
-        // directly, with appropriate scale.
-        // Otherwise if we just saw a register it has only been stored in
-        // TmpReg, so we need to store it into the state machine.
-        if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
-          // If we already have a BaseReg, then assume this is the IndexReg with
-          // no explicit scale.
-          if (!BaseReg) {
-            BaseReg = TmpReg;
-          } else {
-            if (IndexReg)
-              return regsUseUpError(ErrMsg);
-            if (NegativeAdditiveTerm) {
-              ErrMsg = "Scale can't be negative";
-              return true;
-            }
-            IndexReg = TmpReg;
-            Scale = 0;
-          }
-        }
         IC.pushOperator(IC_RPAREN);
         break;
       }
diff --git a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
new file mode 100644
index 0000000000000..b0adcfd170c17
--- /dev/null
+++ b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
@@ -0,0 +1,23 @@
+// RUN: not llvm-mc -triple x86_64-unknown-unknown -x86-asm-syntax=intel %s 2>&1 | FileCheck %s
+
+// CHECK: error: Scale can't be negative
+  xor [rsi - rdx + 40], eax
+// CHECK: error: Scale can't be negative
+  xor [rsi - 8 * rdx], eax
+// CHECK: error: BaseReg/IndexReg already set!
+  xor [rsi + rbx + rbx], eax
+// CHECK: error: BaseReg/IndexReg already set!
+  xor [rsi + 4*rbx + rbx], eax
+// CHECK: error: BaseReg/IndexReg already set!
+  xor [rsi + (4*rbx) + rbx], eax
+// CHECK: error: Register can't be multiplied with register!
+  xor [rsi + (rax*rbx)], eax
+// CHECK: error: Register can't be multiplied with register!
+  xor [rsi + rax*(rbx)], eax
+// CHECK: error: Register can't be multiplied with register!
+  xor [rsi + rax*rbx], eax
+// CHECK: error: scale factor in address must be 1, 2, 4 or 8
+  xor [rsi + 0*(rbx)], eax
+// CHECK: error: scale factor in address must be 1, 2, 4 or 8
+  xor [rsi + (rbx)*0], eax
+
diff --git a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s
new file mode 100644
index 0000000000000..5c410e4a02e86
--- /dev/null
+++ b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s
@@ -0,0 +1,75 @@
+// RUN: llvm-mc -triple x86_64-unknown-unknown -x86-asm-syntax=intel --output-asm-variant=1 %s | FileCheck %s
+
+// Test that parentheses around scale register are interpreted correctly
+// Tests parentheses around registers and scale values in register addressing
+// CHECK: xor dword ptr [rsi + rbx + 16], eax
+  xor [rsi + 2 * 8 + (((rbx)))], eax
+// CHECK: xor dword ptr [rsi + rbx + 16], eax
+  xor [rsi + 2 * 8 + (rbx)], eax
+// CHECK: xor dword ptr [rsi + 16], eax
+  xor [rsi + 2 * 8], eax
+// CHECK: xor dword ptr [rsi + 16], eax
+  xor [rsi + (2) * 8], eax
+// CHECK: xor dword ptr [rsi + 16], eax
+  xor [rsi + 2 * (8)], eax
+// CHECK: xor dword ptr [rsi + 2*rbx + 16], eax
+  xor [rsi + (2) * 8 + rbx * 2], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
+  xor [rsi + 2 * (8) + rbx * 4], eax
+// CHECK: xor dword ptr [rsi + 2*rbx + 16], eax
+  xor [rsi + 2 * 8 + (((rbx))) * 2], eax
+// CHECK: xor dword ptr [rsi + 8*rbx + 16], eax
+  xor [(rsi) + 2 * 8 + (rbx) * 8], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
+  xor [rsi + 2 * 8 + (rbx * 4)], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 40], eax
+  xor [rsi + 2 * 8 + (rbx * 4) + 24], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
+  xor [(rsi) + 2 * 8 + (rbx * 4)], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
+  xor [(((rsi))) + 2 * 8 + (rbx * 4)], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
+  xor [(((rsi))) + 2 * 8 + (rbx) * 4], eax
+// CHECK: xor dword ptr [rsi + 2*rbx], eax
+  xor [rsi + 2*(rbx)], eax
+// CHECK: xor dword ptr [rsi], eax
+  xor [rsi + 0], eax
+// CHECK: xor dword ptr [rsi], eax
+  xor [0 + rsi], eax
+// CHECK: xor dword ptr [rsi + 2*rbx], eax
+  xor [rsi + (2*rbx)], eax
+// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
+  xor [rsi + (2*rbx) - 40], eax
+// CHECK: xor dword ptr [rsi - 40], eax
+  xor [rsi - 40], eax
+// CHECK: xor dword ptr [rsi + rbx - 40], eax
+  xor [rsi + rbx - 40], eax
+// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
+  xor [rsi -40 +(2*rbx)], eax
+// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
+  xor [rsi -40 +2*(rbx)], eax
+// CHECK: xor dword ptr [rsi + 4*rbx], eax
+  xor [rsi + (4*(rbx))], eax
+// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
+  xor [rsi + 2*(((2*((rbx))))) - 40], eax
+// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
+  xor [rsi -40 + 2*(((2*((rbx)))))], eax
+// CHECK: xor dword ptr [rsi + 8*rbx], eax
+  xor [rsi + 2*(2*2*(rbx))], eax
+// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
+  xor [rsi -40 +2*(rbx)], eax
+// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
+  xor [rsi -40 +2*((((((rbx))))))], eax
+// CHECK: xor dword ptr [rsi + 4*rbx], eax
+  xor [rsi + (4*(rbx))], eax
+// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
+  xor [rsi -40 +((((((rbx)))*2))*2)], eax
+// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
+  xor [rsi -40 +((((((rbx*2))*2)))*2)], eax
+// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
+  xor [rsi -40 +(((2*(((rbx)))*2))*2)], eax
+// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
+  xor [rsi -40 +((2*((2*((rbx*2)))))*(1))], eax
+// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
+  xor [rsi -40 +((2*((1*((rbx*2)))))*(2))], eax
+

>From 9dd6ab4ff3309a69d8910de81b725e022ca54505 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Tue, 21 Jul 2026 18:35:17 +0200
Subject: [PATCH 2/8] fixed formatting

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index cbd66c6808749..fbb7baba558f5 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1066,7 +1066,7 @@ class X86AsmParser : public MCTargetAsmParser {
             IndexReg = TmpReg;
             TmpReg = MCRegister::NoRegister;
             if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
-                return true;
+              return true;
             }
             Scale = TmpScale.value_or(0);
           } else {

>From 058394797dae46ec656e4b6e97ee1bbef6006ed4 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Tue, 21 Jul 2026 18:40:21 +0200
Subject: [PATCH 3/8] case order restored

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index fbb7baba558f5..2ad8b8e384626 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -832,8 +832,8 @@ class X86AsmParser : public MCTargetAsmParser {
       default:
         State = IES_ERROR;
         break;
-      case IES_MINUS:
       case IES_PLUS:
+      case IES_MINUS:
       case IES_LBRAC:
         State = IES_REGISTER;
         TmpReg = Reg;

>From e336e58a4ce41a7ab19b6ee8f14e58b1c228268d Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Thu, 23 Jul 2026 16:22:39 +0200
Subject: [PATCH 4/8] [X86][AsmParser] Fix negative scale detection in
 Intel-syntax memory operands

---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 55 +++++++++++--------
 llvm/test/MC/X86/intel-syntax-invalid-scale.s |  4 +-
 2 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 2ad8b8e384626..5232395a11f9f 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -700,8 +700,6 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_OFFSET:
         State = IES_PLUS;
         IC.pushOperator(IC_PLUS);
-        NegativeAdditiveTerm = false;
-        NegativeAdditiveTermLoc = SMLoc();
         if (TmpReg) {
           // A pending scale forces this to be the IndexReg; otherwise a free
           // BaseReg takes it as an unscaled base.
@@ -713,6 +711,10 @@ class X86AsmParser : public MCTargetAsmParser {
               return regsUseUpError(ErrMsg);
             IndexReg = TmpReg;
             TmpReg = MCRegister::NoRegister;
+            if (NegativeAdditiveTerm) {
+              ErrMsg = "Scale can't be negative";
+              return true;
+            }
             if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
               return true;
             }
@@ -721,6 +723,8 @@ class X86AsmParser : public MCTargetAsmParser {
         }
         break;
       }
+      NegativeAdditiveTerm = false;
+      NegativeAdditiveTermLoc = SMLoc();
       // A '+' ends the current additive term, so clear the pending scale.
       TmpScale.reset();
       PrevState = CurrState;
@@ -757,36 +761,37 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_INIT:
       case IES_OFFSET:
         State = IES_MINUS;
+        NegativeAdditiveTerm = true;
+        NegativeAdditiveTermLoc = MinusLoc;
         // push minus operator if it is not a negate operator
         if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
             CurrState == IES_INTEGER || CurrState == IES_RBRAC ||
             CurrState == IES_OFFSET) {
           IC.pushOperator(IC_MINUS);
-          NegativeAdditiveTerm = true;
-          NegativeAdditiveTermLoc = MinusLoc;
+          if (TmpReg) {
+            // A pending scale forces this to be the IndexReg; otherwise a free
+            // BaseReg takes it as an unscaled base.
+            if (!BaseReg && !TmpScale.has_value()) {
+              BaseReg = TmpReg;
+              TmpReg = MCRegister::NoRegister;
+            } else {
+              if (IndexReg)
+                return regsUseUpError(ErrMsg);
+              IndexReg = TmpReg;
+              TmpReg = MCRegister::NoRegister;
+              if (TmpScale.has_value() &&
+                  checkScale(TmpScale.value(), ErrMsg)) {
+                return true;
+              }
+              Scale = TmpScale.value_or(0);
+            }
+          }
         } else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
           // We have negate operator for Scale: it's illegal
           ErrMsg = "Scale can't be negative";
           return true;
         } else
           IC.pushOperator(IC_NEG);
-        if (TmpReg) {
-          // A pending scale forces this to be the IndexReg; otherwise a free
-          // BaseReg takes it as an unscaled base.
-          if (!BaseReg && !TmpScale.has_value()) {
-            BaseReg = TmpReg;
-            TmpReg = MCRegister::NoRegister;
-          } else {
-            if (IndexReg)
-              return regsUseUpError(ErrMsg);
-            IndexReg = TmpReg;
-            TmpReg = MCRegister::NoRegister;
-            if (TmpScale.has_value() && checkScale(TmpScale.value(), ErrMsg)) {
-              return true;
-            }
-            Scale = TmpScale.value_or(0);
-          }
-        }
         break;
       }
       // A '-' ends the current additive term, so clear the pending scale.
@@ -943,6 +948,10 @@ class X86AsmParser : public MCTargetAsmParser {
           TmpScale = TmpInt;
         }
         // Once an index register is pending, check if TmpScale is valid.
+        if (TmpReg && NegativeAdditiveTerm) {
+          ErrMsg = "Scale can't be negative";
+          return true;
+        }
         if (TmpReg && checkScale(TmpScale.value(), ErrMsg))
           return true;
         IC.pushOperand(IC_IMM, TmpInt);
@@ -1028,9 +1037,11 @@ class X86AsmParser : public MCTargetAsmParser {
         assert(!BracCount && "BracCount should be zero on parsing's start");
         State = IES_LBRAC;
         // Entering a new memory expression; clear the pending scale.
-        TmpScale.reset();
         break;
       }
+      NegativeAdditiveTerm = false;
+      NegativeAdditiveTermLoc = SMLoc();
+      TmpScale.reset();
       MemExpr = true;
       BracketUsed = true;
       BracCount++;
diff --git a/llvm/test/MC/X86/intel-syntax-invalid-scale.s b/llvm/test/MC/X86/intel-syntax-invalid-scale.s
index 8c9e85693ca63..bd0c035cd5fab 100644
--- a/llvm/test/MC/X86/intel-syntax-invalid-scale.s
+++ b/llvm/test/MC/X86/intel-syntax-invalid-scale.s
@@ -11,7 +11,9 @@
     lea rax, [rdi + rdx*16]
 // CHECK: error: Scale can't be negative
     lea rax, [rdi + rdx*-8]
-// CHECK: error: scale factor in address must be 1, 2, 4 or 8
+// CHECK: [[#@LINE+3]]:21: error: Scale can't be negative
+// CHECK-NEXT:     lea rax, [rdi + -1*rdx]
+// CHECK-NEXT:                     ^
     lea rax, [rdi + -1*rdx]
 // CHECK: [[#@LINE+3]]:19: error: Scale can't be negative
 // CHECK-NEXT:     lea rax, [rax - 8 * rdx]

>From 412a14840c69ae4f8af6647f7785ca38a34d46b1 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Fri, 24 Jul 2026 15:48:00 +0200
Subject: [PATCH 5/8] delete unnecessary conditions

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 5232395a11f9f..1140d379dcdf4 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -860,8 +860,7 @@ class X86AsmParser : public MCTargetAsmParser {
         // Recognize this register as a scaled index register. This covers
         // 'scale * reg' and 'scale * (reg)', including parenthesized or
         // multi-factor scales where the accumulated value is held in TmpScale.
-        if (TmpScale.has_value() || PrevState == IES_MULTIPLY ||
-            (PrevState == IES_INTEGER && CurrState == IES_MULTIPLY)) {
+        if (TmpScale.has_value()){
           if (IndexReg)
             return regsUseUpError(ErrMsg);
           if (NegativeAdditiveTerm) {
@@ -904,6 +903,8 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_LPAREN:
         if (setSymRef(SymRef, SymRefName, ErrMsg))
           return true;
+        // Mark TmpScale as invalid, in case of multiplying by register
+        TmpScale = 0;
         MemExpr = true;
         State = IES_INTEGER;
         IC.pushOperand(IC_IMM);
@@ -967,12 +968,6 @@ class X86AsmParser : public MCTargetAsmParser {
         State = IES_ERROR;
         break;
       case IES_INTEGER:
-        // Seed the scale accumulator with the integer just parsed (the left
-        // operand of this '*'), reading it back from the operand stack.
-        if (!TmpScale.has_value()) {
-          TmpScale = IC.popOperand();
-          IC.pushOperand(IC_IMM, TmpScale.value());
-        }
         State = IES_MULTIPLY;
         IC.pushOperator(IC_MULTIPLY);
         break;
@@ -1036,11 +1031,11 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_CAST:
         assert(!BracCount && "BracCount should be zero on parsing's start");
         State = IES_LBRAC;
-        // Entering a new memory expression; clear the pending scale.
         break;
       }
       NegativeAdditiveTerm = false;
       NegativeAdditiveTermLoc = SMLoc();
+      // Entering a new memory expression; clear the pending scale.
       TmpScale.reset();
       MemExpr = true;
       BracketUsed = true;

>From 673960d3944855f184a5785ed01dec51dc7cc575 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Mon, 27 Jul 2026 09:51:18 +0200
Subject: [PATCH 6/8] formatting fix

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 1140d379dcdf4..19566c64969ce 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -860,7 +860,7 @@ class X86AsmParser : public MCTargetAsmParser {
         // Recognize this register as a scaled index register. This covers
         // 'scale * reg' and 'scale * (reg)', including parenthesized or
         // multi-factor scales where the accumulated value is held in TmpScale.
-        if (TmpScale.has_value()){
+        if (TmpScale.has_value()) {
           if (IndexReg)
             return regsUseUpError(ErrMsg);
           if (NegativeAdditiveTerm) {

>From f5dda8cc29a7fe351de0b6799d4e40c945378ebb Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Wed, 29 Jul 2026 15:11:57 +0200
Subject: [PATCH 7/8] reordering

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 19566c64969ce..28b8e09dadfb1 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -980,8 +980,8 @@ class X86AsmParser : public MCTargetAsmParser {
           IC.popOperand();
           IC.pushOperand(IC_IMM);
         }
-        IC.pushOperator(IC_MULTIPLY);
         State = IES_MULTIPLY;
+        IC.pushOperator(IC_MULTIPLY);
         break;
       }
     }

>From e3cc3656f2cae375abfaf3c004da14047eaf1cf6 Mon Sep 17 00:00:00 2001
From: "Ludwichowski, Wiktor" <wiktor.ludwichowski at intel.com>
Date: Fri, 31 Jul 2026 15:07:57 +0200
Subject: [PATCH 8/8] deleted repeated test cases, added invalid parenthesis
 error

---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 12 ++++
 ...-syntax-scale-register-parentheses-error.s | 17 ++---
 .../intel-syntax-scale-register-parentheses.s | 67 ++-----------------
 3 files changed, 24 insertions(+), 72 deletions(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 28b8e09dadfb1..ec6a03ead4835 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -453,6 +453,7 @@ class X86AsmParser : public MCTargetAsmParser {
     InfixCalculator IC;
     InlineAsmIdentifierInfo Info;
     short BracCount = 0;
+    short ParenCount = 0;
     bool MemExpr = false;
     bool BracketUsed = false;
     bool NegativeAdditiveTerm = false;
@@ -1039,6 +1040,7 @@ class X86AsmParser : public MCTargetAsmParser {
       TmpScale.reset();
       MemExpr = true;
       BracketUsed = true;
+      ParenCount = 0;
       BracCount++;
       return false;
     }
@@ -1056,6 +1058,10 @@ class X86AsmParser : public MCTargetAsmParser {
           ErrMsg = "unexpected bracket encountered";
           return true;
         }
+        if (ParenCount != 0) {
+          ErrMsg = "unmatched parenthesis";
+          return true;
+        }
         State = IES_RBRAC;
 
         if (TmpReg) {
@@ -1114,6 +1120,7 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_LPAREN:
       case IES_INIT:
       case IES_LBRAC:
+        ParenCount++;
         State = IES_LPAREN;
         IC.pushOperator(IC_LPAREN);
         break;
@@ -1131,6 +1138,11 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_REGISTER:
       case IES_RBRAC:
       case IES_RPAREN:
+        if (ParenCount == 0) {
+          ErrMsg = "unmatched parenthesis";
+          return true;
+        }
+        ParenCount--;
         State = IES_RPAREN;
         IC.pushOperator(IC_RPAREN);
         break;
diff --git a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
index b0adcfd170c17..33ec87753014a 100644
--- a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
+++ b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses-error.s
@@ -1,23 +1,18 @@
 // RUN: not llvm-mc -triple x86_64-unknown-unknown -x86-asm-syntax=intel %s 2>&1 | FileCheck %s
 
 // CHECK: error: Scale can't be negative
-  xor [rsi - rdx + 40], eax
+  xor [rsi - (rdx) + 40], eax
 // CHECK: error: Scale can't be negative
-  xor [rsi - 8 * rdx], eax
-// CHECK: error: BaseReg/IndexReg already set!
-  xor [rsi + rbx + rbx], eax
-// CHECK: error: BaseReg/IndexReg already set!
-  xor [rsi + 4*rbx + rbx], eax
+  xor [rsi - 8*(rdx)], eax
 // CHECK: error: BaseReg/IndexReg already set!
   xor [rsi + (4*rbx) + rbx], eax
 // CHECK: error: Register can't be multiplied with register!
   xor [rsi + (rax*rbx)], eax
 // CHECK: error: Register can't be multiplied with register!
   xor [rsi + rax*(rbx)], eax
-// CHECK: error: Register can't be multiplied with register!
-  xor [rsi + rax*rbx], eax
 // CHECK: error: scale factor in address must be 1, 2, 4 or 8
   xor [rsi + 0*(rbx)], eax
-// CHECK: error: scale factor in address must be 1, 2, 4 or 8
-  xor [rsi + (rbx)*0], eax
-
+// CHECK:  error: unmatched parenthesis
+  xor [rsi + 2*(rbx + 23], eax
+// CHECK:  error: unmatched parenthesis
+  xor [rsi + 2*(rbx)) + 23], eax
diff --git a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s
index 5c410e4a02e86..c2e719df511f5 100644
--- a/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s
+++ b/llvm/test/MC/X86/intel-syntax-scale-register-parentheses.s
@@ -2,74 +2,19 @@
 
 // Test that parentheses around scale register are interpreted correctly
 // Tests parentheses around registers and scale values in register addressing
-// CHECK: xor dword ptr [rsi + rbx + 16], eax
-  xor [rsi + 2 * 8 + (((rbx)))], eax
-// CHECK: xor dword ptr [rsi + rbx + 16], eax
-  xor [rsi + 2 * 8 + (rbx)], eax
-// CHECK: xor dword ptr [rsi + 16], eax
-  xor [rsi + 2 * 8], eax
 // CHECK: xor dword ptr [rsi + 16], eax
   xor [rsi + (2) * 8], eax
-// CHECK: xor dword ptr [rsi + 16], eax
-  xor [rsi + 2 * (8)], eax
-// CHECK: xor dword ptr [rsi + 2*rbx + 16], eax
-  xor [rsi + (2) * 8 + rbx * 2], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
-  xor [rsi + 2 * (8) + rbx * 4], eax
-// CHECK: xor dword ptr [rsi + 2*rbx + 16], eax
-  xor [rsi + 2 * 8 + (((rbx))) * 2], eax
+// CHECK: xor dword ptr [rsi + rbx + 16], eax
+  xor [rsi + 2 * 8 + (rbx)], eax
 // CHECK: xor dword ptr [rsi + 8*rbx + 16], eax
   xor [(rsi) + 2 * 8 + (rbx) * 8], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
-  xor [rsi + 2 * 8 + (rbx * 4)], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 40], eax
-  xor [rsi + 2 * 8 + (rbx * 4) + 24], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
-  xor [(rsi) + 2 * 8 + (rbx * 4)], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
-  xor [(((rsi))) + 2 * 8 + (rbx * 4)], eax
-// CHECK: xor dword ptr [rsi + 4*rbx + 16], eax
-  xor [(((rsi))) + 2 * 8 + (rbx) * 4], eax
 // CHECK: xor dword ptr [rsi + 2*rbx], eax
   xor [rsi + 2*(rbx)], eax
-// CHECK: xor dword ptr [rsi], eax
-  xor [rsi + 0], eax
-// CHECK: xor dword ptr [rsi], eax
-  xor [0 + rsi], eax
-// CHECK: xor dword ptr [rsi + 2*rbx], eax
-  xor [rsi + (2*rbx)], eax
 // CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
-  xor [rsi + (2*rbx) - 40], eax
-// CHECK: xor dword ptr [rsi - 40], eax
-  xor [rsi - 40], eax
-// CHECK: xor dword ptr [rsi + rbx - 40], eax
-  xor [rsi + rbx - 40], eax
-// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
-  xor [rsi -40 +(2*rbx)], eax
-// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
-  xor [rsi -40 +2*(rbx)], eax
-// CHECK: xor dword ptr [rsi + 4*rbx], eax
-  xor [rsi + (4*(rbx))], eax
-// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
-  xor [rsi + 2*(((2*((rbx))))) - 40], eax
-// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
-  xor [rsi -40 + 2*(((2*((rbx)))))], eax
+  xor [rsi - 40 + (2*rbx)], eax
+// CHECK: xor dword ptr [rsi + 4*rbx + 24], eax
+  xor [rsi + (rbx*2)*2 + 24], eax
 // CHECK: xor dword ptr [rsi + 8*rbx], eax
   xor [rsi + 2*(2*2*(rbx))], eax
-// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
-  xor [rsi -40 +2*(rbx)], eax
-// CHECK: xor dword ptr [rsi + 2*rbx - 40], eax
-  xor [rsi -40 +2*((((((rbx))))))], eax
-// CHECK: xor dword ptr [rsi + 4*rbx], eax
-  xor [rsi + (4*(rbx))], eax
-// CHECK: xor dword ptr [rsi + 4*rbx - 40], eax
-  xor [rsi -40 +((((((rbx)))*2))*2)], eax
 // CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
-  xor [rsi -40 +((((((rbx*2))*2)))*2)], eax
-// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
-  xor [rsi -40 +(((2*(((rbx)))*2))*2)], eax
-// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
-  xor [rsi -40 +((2*((2*((rbx*2)))))*(1))], eax
-// CHECK: xor dword ptr [rsi + 8*rbx - 40], eax
-  xor [rsi -40 +((2*((1*((rbx*2)))))*(2))], eax
-
+  xor [rsi -40 +(2*(1*(rbx*2))*(2))], eax



More information about the llvm-commits mailing list