[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