[llvm] [ARM] Validate STREX instruction in the assembler (PR #85074)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 13 06:31:20 PDT 2024
https://github.com/adamszilagyi created https://github.com/llvm/llvm-project/pull/85074
Based on the ARM Architecture Reference Manual:
```
**Use of R15** Specifying R15 for register <Rd>, <Rn>, or <Rm> has UNPREDICTABLE results.
**Operand restrictions** <Rd> must be distinct from both <Rm> and <Rn>, otherwise the results are UNPREDICTABLE.
```
>From 9191717aaa76c762ab48b51c3160138a098511f1 Mon Sep 17 00:00:00 2001
From: Adam Szilagyi <szilagyi.adam97 at gmail.com>
Date: Wed, 13 Mar 2024 14:23:36 +0100
Subject: [PATCH] [ARM] Validate STREX instruction in the assembler
---
.../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 33 ++++++++++++
llvm/test/MC/ARM/diagnostics.s | 52 +++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index c320bf723c88bb..8c96cce7a5cf55 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -7629,6 +7629,39 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
}
return false;
}
+ case ARM::t2STREXB:
+ case ARM::t2STREXH:
+ case ARM::t2STREX:
+ case ARM::STREXB:
+ case ARM::STREXH:
+ case ARM::STREX:
+ case ARM::STREXD: {
+ unsigned Rd = MRI->getEncodingValue(Inst.getOperand(0).getReg());
+ unsigned Rm = MRI->getEncodingValue(Inst.getOperand(1).getReg());
+ unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
+
+ if (Rd == 15 || Rm == 15 || Rn == 15)
+ return Error(Operands[3]->getStartLoc(), "operand can't be R15");
+
+ if (Rd == Rm || Rd == Rn || (Opcode == ARM::STREXD && Rd == Rm + 1))
+ return Error(Operands[3]->getStartLoc(),
+ "destination operand can't be identical to source operand");
+ return false;
+ }
+ case ARM::t2STREXD: {
+ unsigned Rd = MRI->getEncodingValue(Inst.getOperand(0).getReg());
+ unsigned Rm1 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
+ unsigned Rm2 = MRI->getEncodingValue(Inst.getOperand(2).getReg());
+ unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg());
+
+ if (Rd == 15 || Rn == 15)
+ return Error(Operands[4]->getStartLoc(), "operand can't be R15");
+
+ if (Rd == Rm1 || Rd == Rm2 || Rd == Rn)
+ return Error(Operands[4]->getStartLoc(),
+ "destination operand can't be identical to source operand");
+ return false;
+ }
case ARM::t2IT: {
// Encoding is unpredictable if it ever results in a notional 'NV'
// predicate. Since we don't parse 'NV' directly this means an 'AL'
diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s
index e6d80ea7a6280c..f29be4e3bafcc8 100644
--- a/llvm/test/MC/ARM/diagnostics.s
+++ b/llvm/test/MC/ARM/diagnostics.s
@@ -336,6 +336,58 @@
@ CHECK-ERRORS: strexd r6, r5, r3, [r8]
@ CHECK-ERRORS: ^
+ @ Invalid Rm/Rn operands for strex
+ strex r1, r2, [r1]
+ strex r1, r1, [r2]
+
+@ CHECK-ERRORS: error: destination operand can't be identical to source operand
+@ CHECK-ERRORS: strex r1, r2, [r1]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: destination operand can't be identical to source operand
+@ CHECK-ERRORS: strex r1, r1, [r2]
+@ CHECK-ERRORS: ^
+
+ @ Can not use R15 as operand for strex
+ strex r15, r2, [r1]
+ strex r1, r15, [r2]
+ strex r1, r2, [r15]
+
+@ CHECK-ERRORS: error: operand can't be R15
+@ CHECK-ERRORS: strex r15, r2, [r1]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: operand can't be R15
+@ CHECK-ERRORS: strex r1, r15, [r2]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: operand can't be R15
+@ CHECK-ERRORS: strex r1, r2, [r15]
+@ CHECK-ERRORS: ^
+
+ @ Can not use R15 as operand for strexd
+ strexd r15, r0, r1, [r6]
+ strexd r2, r0, r1, [r15]
+
+@ CHECK-ERRORS: error: operand can't be R15
+@ CHECK-ERRORS: strexd r15, r0, r1, [r6]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: operand can't be R15
+@ CHECK-ERRORS: strexd r2, r0, r1, [r15]
+@ CHECK-ERRORS: ^
+
+ @ Invalid Rm/Rn operands for strexd
+ strexd r1, r0, r1, [r6]
+ strexd r2, r2, r3, [r6]
+ strexd r4, r0, r1, [r4]
+
+@ CHECK-ERRORS: error: destination operand can't be identical to source operand
+@ CHECK-ERRORS: strexd r1, r0, r1, [r6]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: destination operand can't be identical to source operand
+@ CHECK-ERRORS: strexd r2, r2, r3, [r6]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: destination operand can't be identical to source operand
+@ CHECK-ERRORS: strexd r4, r0, r1, [r4]
+@ CHECK-ERRORS: ^
+
@ Illegal rotate operators for extend instructions
sxtb r8, r3, #8
sxtb r8, r3, ror 24
More information about the llvm-commits
mailing list