aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2011-07-26 18:25:39 +0000
committerJim Grosbach <grosbach@apple.com>2011-07-26 18:25:39 +0000
commit189610f9466686a91fb7d847b572e1645c785323 (patch)
tree7343f5878068a667c2a7302e4e66f6bda324b536
parentcf128eab908e071eec58a666891f81ca3584724b (diff)
ARM diagnostics for ldrexd/stredx out of order paired register operands.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136110 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp40
-rw-r--r--test/MC/ARM/diagnostics.s12
2 files changed, 51 insertions, 1 deletions
diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 4587ed200d..a074bc5a74 100644
--- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -135,6 +135,10 @@ class ARMAsmParser : public MCTargetAsmParser {
bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
const SmallVectorImpl<MCParsedAsmOperand*> &);
+
+ bool validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
+
public:
ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
: MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
@@ -147,7 +151,7 @@ public:
// Implementation of the MCTargetAsmParser interface:
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
bool ParseInstruction(StringRef Name, SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands);
bool ParseDirective(AsmToken DirectiveID);
bool MatchAndEmitInstruction(SMLoc IDLoc,
@@ -2499,6 +2503,35 @@ bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
return false;
}
+// Validate context-sensitive operand constraints.
+// FIXME: We would really like to be able to tablegen'erate this.
+bool ARMAsmParser::
+validateInstruction(MCInst &Inst,
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+ switch (Inst.getOpcode()) {
+ case ARM::LDREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[3]->getStartLoc(),
+ "destination operands must be sequential");
+ return false;
+ }
+ case ARM::STREXD: {
+ // Rt2 must be Rt + 1.
+ unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
+ unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
+ if (Rt2 != Rt + 1)
+ return Error(Operands[4]->getStartLoc(),
+ "source operands must be sequential");
+ return false;
+ }
+ }
+
+ return false;
+}
+
bool ARMAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
@@ -2509,6 +2542,11 @@ MatchAndEmitInstruction(SMLoc IDLoc,
MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
switch (MatchResult) {
case Match_Success:
+ // Context sensitive operand constraints aren't handled by the matcher,
+ // so check them here.
+ if (validateInstruction(Inst, Operands))
+ return true;
+
Out.EmitInstruction(Inst);
return false;
case Match_MissingFeature:
diff --git a/test/MC/ARM/diagnostics.s b/test/MC/ARM/diagnostics.s
index 0c51887c7a..c8ca0593e7 100644
--- a/test/MC/ARM/diagnostics.s
+++ b/test/MC/ARM/diagnostics.s
@@ -226,3 +226,15 @@
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: svc #0x1000000
@ CHECK-ERRORS: ^
+
+
+ @ Out of order Rt/Rt2 operands for ldrexd/strexd
+ ldrexd r4, r3, [r8]
+ strexd r6, r5, r3, [r8]
+
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS: ldrexd r4, r3, [r8]
+@ CHECK-ERRORS: ^
+@ CHECK-ERRORS: error: source operands must be sequential
+@ CHECK-ERRORS: strexd r6, r5, r3, [r8]
+@ CHECK-ERRORS: ^