Skip to content

[ARM] FIX: change pkhtb custom parsing produce NoMatch rather than Error #85765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 19, 2024

Conversation

AlfieRichardsArm
Copy link
Contributor

@AlfieRichardsArm AlfieRichardsArm commented Mar 19, 2024

This was broken by #83436 as in optional operands meant when the CC operand is provided the parsePKHImm parser is applied to register operands, which previously erroneously produced an error.

This patch changes parsePKHImm to provide NoMatch instead. However this unfortunately means the default parsing happens which combines the shift and the base operator which causes the diagnostics to be nonsense.

To fix this I added a special case diagnostic to this default parsing which is little unfortunate. Ideally these two methods for handling operands should be unified and the TableGen matching mechanisms should be used for validaing parsed shifts rather than special cases in parsing.

This was broken by llvm#83436 as in
optional operands meant sometimes the parsePKHImm parser is applied to
operands in other positions, which previously produced an error.

Now this instead fails the parse. However this unfortunately means
the default parsing happens which combines the shift and the base operator
which causes the diagnostics to be non-sense.

To fix this I had to add a special case diagnostic which is unfortunate.
Ideally these two methods for handling operands should be unified and the
TableGen matching mechanisms should be used for validaing parsed shifts rather
than special cases in parsing.
@llvmbot llvmbot added backend:ARM mc Machine (object) code labels Mar 19, 2024
@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2024

@llvm/pr-subscribers-backend-arm

Author: Alfie Richards (AlfieRichardsArm)

Changes

This was broken by #83436 as in optional operands meant when the CC operand is provided the parsePKHImm parser is applied to register operands, which previously produced an error.

This patch changes parsePKHImm to provide NoMatch instead. However this unfortunately means the default parsing happens which combines the shift and the base operator which causes the diagnostics to be nonsense.

To fix this I added a special case diagnostic to this default parsing which is little unfortunate. Ideally these two methods for handling operands should be unified and the TableGen matching mechanisms should be used for validaing parsed shifts rather than special cases in parsing.


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

3 Files Affected:

  • (modified) llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (+19-2)
  • (modified) llvm/test/MC/ARM/basic-arm-instructions.s (+4)
  • (modified) llvm/test/MC/ARM/diagnostics.s (+2-2)
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 026d4ca06e87b9..e21310c53f45a0 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -4318,6 +4318,23 @@ int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) {
     }
   }
 
+  auto MnemonicOp = static_cast<ARMOperand &>(*Operands[0]);
+  // These instructions handle shift operands as seperate operators to the
+  // register. In these cases doing the default conversion makes nonsense
+  // diagnostics.
+  // FIXME: Unify the different methods for handling shift operators
+  // and use TableGen matching mechanisms to do the validation.
+  static const DenseSet<StringRef> NoDefaultConvertSet{"pkhbt", "pkhtb"};
+  bool ShouldDefaultConvert =
+      (MnemonicOp.isToken() &&
+       !NoDefaultConvertSet.contains(MnemonicOp.getToken()));
+  if (!ShouldDefaultConvert) {
+    // If we get to this point the parsing for the shift operator in
+    // parsePKHLSLImm has failed. So we can generate a diagnostic here.
+    Error(S, "shift operator is malformed for this instruction");
+    return -1;
+  }
+
   if (ShiftReg && ShiftTy != ARM_AM::rrx)
     Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
                                                          ShiftReg, Imm,
@@ -5289,12 +5306,12 @@ ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op,
   MCAsmParser &Parser = getParser();
   const AsmToken &Tok = Parser.getTok();
   if (Tok.isNot(AsmToken::Identifier))
-    return Error(Parser.getTok().getLoc(), Op + " operand expected.");
+    return ParseStatus::NoMatch;
   StringRef ShiftName = Tok.getString();
   std::string LowerOp = Op.lower();
   std::string UpperOp = Op.upper();
   if (ShiftName != LowerOp && ShiftName != UpperOp)
-    return Error(Parser.getTok().getLoc(), Op + " operand expected.");
+    return ParseStatus::NoMatch;
   Parser.Lex(); // Eat shift type token.
 
   // There must be a '#' and a shift amount.
diff --git a/llvm/test/MC/ARM/basic-arm-instructions.s b/llvm/test/MC/ARM/basic-arm-instructions.s
index 055f3ce316153d..84a7cf52fa30e0 100644
--- a/llvm/test/MC/ARM/basic-arm-instructions.s
+++ b/llvm/test/MC/ARM/basic-arm-instructions.s
@@ -1774,6 +1774,9 @@ Lforward:
         pkhtb r2, r2, r3, asr #31
         pkhtb r2, r2, r3, asr #15
 
+        it ne
+        pkhtbne r2, r2, r3, asr #15
+
 @ CHECK: pkhbt	r2, r2, r3              @ encoding: [0x13,0x20,0x82,0xe6]
 @ CHECK: pkhbt	r2, r2, r3, lsl #31     @ encoding: [0x93,0x2f,0x82,0xe6]
 @ CHECK: pkhbt	r2, r2, r3              @ encoding: [0x13,0x20,0x82,0xe6]
@@ -1782,6 +1785,7 @@ Lforward:
 @ CHECK: pkhbt	r2, r3, r2              @ encoding: [0x12,0x20,0x83,0xe6]
 @ CHECK: pkhtb	r2, r2, r3, asr #31     @ encoding: [0xd3,0x2f,0x82,0xe6]
 @ CHECK: pkhtb	r2, r2, r3, asr #15     @ encoding: [0xd3,0x27,0x82,0xe6]
+@ CHECK: pkhtbne r2, r2, r3, asr #15    @ encoding: [0xd3,0x27,0x82,0x16]
 
 @------------------------------------------------------------------------------
 @ FIXME: PLD
diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s
index fa23a7da1e4048..b6d011e5bdef8f 100644
--- a/llvm/test/MC/ARM/diagnostics.s
+++ b/llvm/test/MC/ARM/diagnostics.s
@@ -235,10 +235,10 @@
 @ CHECK-ERRORS: error: immediate value out of range
 @ CHECK-ERRORS:         pkhtb r2, r2, r3, asr #33
 @ CHECK-ERRORS:                                ^
-@ CHECK-ERRORS: error: lsl operand expected.
+@ CHECK-ERRORS: error: shift operator is malformed for this instruction
 @ CHECK-ERRORS:         pkhbt r2, r2, r3, asr #3
 @ CHECK-ERRORS:                           ^
-@ CHECK-ERRORS: error: asr operand expected.
+@ CHECK-ERRORS: error: shift operator is malformed for this instruction
 @ CHECK-ERRORS:         pkhtb r2, r2, r3, lsl #3
 @ CHECK-ERRORS:                           ^
 

@llvmbot
Copy link
Member

llvmbot commented Mar 19, 2024

@llvm/pr-subscribers-mc

Author: Alfie Richards (AlfieRichardsArm)

Changes

This was broken by #83436 as in optional operands meant when the CC operand is provided the parsePKHImm parser is applied to register operands, which previously produced an error.

This patch changes parsePKHImm to provide NoMatch instead. However this unfortunately means the default parsing happens which combines the shift and the base operator which causes the diagnostics to be nonsense.

To fix this I added a special case diagnostic to this default parsing which is little unfortunate. Ideally these two methods for handling operands should be unified and the TableGen matching mechanisms should be used for validaing parsed shifts rather than special cases in parsing.


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

3 Files Affected:

  • (modified) llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (+19-2)
  • (modified) llvm/test/MC/ARM/basic-arm-instructions.s (+4)
  • (modified) llvm/test/MC/ARM/diagnostics.s (+2-2)
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 026d4ca06e87b9..e21310c53f45a0 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -4318,6 +4318,23 @@ int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) {
     }
   }
 
+  auto MnemonicOp = static_cast<ARMOperand &>(*Operands[0]);
+  // These instructions handle shift operands as seperate operators to the
+  // register. In these cases doing the default conversion makes nonsense
+  // diagnostics.
+  // FIXME: Unify the different methods for handling shift operators
+  // and use TableGen matching mechanisms to do the validation.
+  static const DenseSet<StringRef> NoDefaultConvertSet{"pkhbt", "pkhtb"};
+  bool ShouldDefaultConvert =
+      (MnemonicOp.isToken() &&
+       !NoDefaultConvertSet.contains(MnemonicOp.getToken()));
+  if (!ShouldDefaultConvert) {
+    // If we get to this point the parsing for the shift operator in
+    // parsePKHLSLImm has failed. So we can generate a diagnostic here.
+    Error(S, "shift operator is malformed for this instruction");
+    return -1;
+  }
+
   if (ShiftReg && ShiftTy != ARM_AM::rrx)
     Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
                                                          ShiftReg, Imm,
@@ -5289,12 +5306,12 @@ ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op,
   MCAsmParser &Parser = getParser();
   const AsmToken &Tok = Parser.getTok();
   if (Tok.isNot(AsmToken::Identifier))
-    return Error(Parser.getTok().getLoc(), Op + " operand expected.");
+    return ParseStatus::NoMatch;
   StringRef ShiftName = Tok.getString();
   std::string LowerOp = Op.lower();
   std::string UpperOp = Op.upper();
   if (ShiftName != LowerOp && ShiftName != UpperOp)
-    return Error(Parser.getTok().getLoc(), Op + " operand expected.");
+    return ParseStatus::NoMatch;
   Parser.Lex(); // Eat shift type token.
 
   // There must be a '#' and a shift amount.
diff --git a/llvm/test/MC/ARM/basic-arm-instructions.s b/llvm/test/MC/ARM/basic-arm-instructions.s
index 055f3ce316153d..84a7cf52fa30e0 100644
--- a/llvm/test/MC/ARM/basic-arm-instructions.s
+++ b/llvm/test/MC/ARM/basic-arm-instructions.s
@@ -1774,6 +1774,9 @@ Lforward:
         pkhtb r2, r2, r3, asr #31
         pkhtb r2, r2, r3, asr #15
 
+        it ne
+        pkhtbne r2, r2, r3, asr #15
+
 @ CHECK: pkhbt	r2, r2, r3              @ encoding: [0x13,0x20,0x82,0xe6]
 @ CHECK: pkhbt	r2, r2, r3, lsl #31     @ encoding: [0x93,0x2f,0x82,0xe6]
 @ CHECK: pkhbt	r2, r2, r3              @ encoding: [0x13,0x20,0x82,0xe6]
@@ -1782,6 +1785,7 @@ Lforward:
 @ CHECK: pkhbt	r2, r3, r2              @ encoding: [0x12,0x20,0x83,0xe6]
 @ CHECK: pkhtb	r2, r2, r3, asr #31     @ encoding: [0xd3,0x2f,0x82,0xe6]
 @ CHECK: pkhtb	r2, r2, r3, asr #15     @ encoding: [0xd3,0x27,0x82,0xe6]
+@ CHECK: pkhtbne r2, r2, r3, asr #15    @ encoding: [0xd3,0x27,0x82,0x16]
 
 @------------------------------------------------------------------------------
 @ FIXME: PLD
diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s
index fa23a7da1e4048..b6d011e5bdef8f 100644
--- a/llvm/test/MC/ARM/diagnostics.s
+++ b/llvm/test/MC/ARM/diagnostics.s
@@ -235,10 +235,10 @@
 @ CHECK-ERRORS: error: immediate value out of range
 @ CHECK-ERRORS:         pkhtb r2, r2, r3, asr #33
 @ CHECK-ERRORS:                                ^
-@ CHECK-ERRORS: error: lsl operand expected.
+@ CHECK-ERRORS: error: shift operator is malformed for this instruction
 @ CHECK-ERRORS:         pkhbt r2, r2, r3, asr #3
 @ CHECK-ERRORS:                           ^
-@ CHECK-ERRORS: error: asr operand expected.
+@ CHECK-ERRORS: error: shift operator is malformed for this instruction
 @ CHECK-ERRORS:         pkhtb r2, r2, r3, lsl #3
 @ CHECK-ERRORS:                           ^
 

@AlfieRichardsArm
Copy link
Contributor Author

Note, this fixes a regression introduced in #83436 brought up here:
#83436 (comment)

@AlfieRichardsArm
Copy link
Contributor Author

AlfieRichardsArm commented Mar 19, 2024

There is seemingly unrelated build failures in CI regarding SystemZISelLowering.
Fixed now

Copy link
Member

@mstorsjo mstorsjo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, thanks, this does fix my build issue. I can't say I fully understand the code changes here (without spending another 15 minutes on reading up on what's going on here), but it does unbreak things.

I'm leaving it unapproved still, if someone else from Arm wants to have a look and give it a proper review, otherwise I guess this can go in later today.

@jthackray jthackray self-requested a review March 19, 2024 11:05
@@ -235,10 +235,10 @@
@ CHECK-ERRORS: error: immediate value out of range
@ CHECK-ERRORS: pkhtb r2, r2, r3, asr #33
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: lsl operand expected.
@ CHECK-ERRORS: error: shift operator is malformed for this instruction
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see you've added a new testcase in basic-arm-instructions.s for the specific failure mentioned in the bug report, but is this change because you've added the new error message? Presumably this is now reached instead, hence the change in this testcase?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the old mechanism for the diagnostic was throwing an error when parsing failed.
Unfortunately with the optional operand change the parsing gets applied to more operands and is expected to return NoMatch when there genuinely isn't a match.

Actually, I still handle this better. Let me fix this with a better diagnostic really quickly.

Copy link
Contributor

@jthackray jthackray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, new testcase added for the specific issue mentioned in the bug report.

@AlfieRichardsArm
Copy link
Contributor Author

@jthackray Just pushed a change that achieves the same thing a much cleaner way. I'm much happier with this change!

Copy link

github-actions bot commented Mar 19, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@jthackray
Copy link
Contributor

@jthackray Just pushed a change that achieves the same thing a much cleaner way. I'm much happier with this change!

Yes, good improvement, and removes the error string change to the other testcase.

Copy link
Contributor

@jthackray jthackray left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Approved.

@mstorsjo mstorsjo merged commit e3030f1 into llvm:main Mar 19, 2024
@mstorsjo
Copy link
Member

I went ahead and landed this now, to unbreak my builds. I tried to update the commit message according to the solution chosen in the end. (If unhappy with the way I phrased it, feel free to revert and recommit with a more correct message.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:ARM mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants