]> granicus.if.org Git - llvm/commitdiff
[mips] Partially fix PR34391
authorSimon Dardis <simon.dardis@imgtec.com>
Tue, 10 Oct 2017 13:34:45 +0000 (13:34 +0000)
committerSimon Dardis <simon.dardis@imgtec.com>
Tue, 10 Oct 2017 13:34:45 +0000 (13:34 +0000)
Previously, the parsing of the 'subu $reg, ($reg,) imm' relied on a parser
which also rendered the operand to the instruction. In some cases the
general parser could construct an MCExpr which was not a MCConstantExpr
which MipsAsmParser was expecting.

Address this by altering the special handling to cope with unexpected inputs
and fine-tune the handling of cases where an register name that is not
available in the current ABI is regarded as not a match for the custom parser
but also not as an outright error.

Also enforces the binutils restriction that only constants are accepted.

This partially resolves PR34391.

Thanks to Ed Maste for reporting the issue!

Reviewers: nitesh.jain, arichardson

Differential Revision: https://reviews.llvm.org/D37476

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315310 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/Mips/AsmParser/MipsAsmParser.cpp
test/MC/Mips/macro-aliases-invalid-wrong-error.s [new file with mode: 0644]
test/MC/Mips/macro-aliases.s [new file with mode: 0644]

index 6a411e0856bd4fd426f0ebb587d1adeb13e4bb7c..4d6fb7f1cdf96e39b1a449110bd0c2508456e33e 100644 (file)
@@ -5859,14 +5859,21 @@ OperandMatchResultTy
 MipsAsmParser::parseInvNum(OperandVector &Operands) {
   MCAsmParser &Parser = getParser();
   const MCExpr *IdVal;
-  // If the first token is '$' we may have register operand.
-  if (Parser.getTok().is(AsmToken::Dollar))
-    return MatchOperand_NoMatch;
+  // If the first token is '$' we may have register operand. We have to reject
+  // cases where it is not a register. Complicating the matter is that
+  // register names are not reserved across all ABIs.
+  // Peek past the dollar to see if it's a register name for this ABI.
   SMLoc S = Parser.getTok().getLoc();
+  if (Parser.getTok().is(AsmToken::Dollar)) {
+    return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1
+               ? MatchOperand_ParseFail
+               : MatchOperand_NoMatch;
+  }
   if (getParser().parseExpression(IdVal))
     return MatchOperand_ParseFail;
   const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal);
-  assert(MCE && "Unexpected MCExpr type.");
+  if (!MCE)
+    return MatchOperand_NoMatch;
   int64_t Val = MCE->getValue();
   SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
   Operands.push_back(MipsOperand::CreateImm(
diff --git a/test/MC/Mips/macro-aliases-invalid-wrong-error.s b/test/MC/Mips/macro-aliases-invalid-wrong-error.s
new file mode 100644 (file)
index 0000000..b87646d
--- /dev/null
@@ -0,0 +1,38 @@
+# RUN: not llvm-mc -arch=mips %s 2>%t1
+# RUN: FileCheck --check-prefix=O32 %s < %t1
+
+# RUN: not llvm-mc -arch=mips64 %s 2>%t1
+# RUN: FileCheck --check-prefix=N64 %s < %t1
+
+# Check that subu only rejects any non-constant values.
+
+.globl end
+  subu  $4, $4, %lo($start)   # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $4, $start        # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $a4, $a4          # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $4, %hi(end)      # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $4, end + 4       # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $4, end           # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $4, sp            # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+
+  subu  $4, %lo($start)       # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $start            # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, $a4               # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, %hi(end)          # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, end + 4           # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, end               # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+  subu  $4, sp                # O32: [[@LINE]]:{{[0-9]+}}: error: unexpected token in argument list
+                              # N64: [[@LINE-1]]:{{[0-9]+}}: error: unexpected token in argument list
+
+$start:
diff --git a/test/MC/Mips/macro-aliases.s b/test/MC/Mips/macro-aliases.s
new file mode 100644 (file)
index 0000000..daa1d8b
--- /dev/null
@@ -0,0 +1,35 @@
+# RUN: llvm-mc -arch=mips -mcpu=mips32r2 %s -show-inst | FileCheck %s
+
+# Test that subu accepts constant operands and inverts them when
+# rendering the operand.
+
+  subu  $4, $4, 4          # CHECK: ADDiu
+                           # CHECK; Imm:-4
+  subu  $gp, $gp, 4        # CHECK: ADDiu
+                           # CHECK; Imm:-4
+  subu  $sp, $sp, 4        # CHECK: ADDiu
+                           # CHECK; Imm:-4
+  subu  $4, $4, -4         # CHECK: ADDiu
+                           # CHECK; Imm:4
+  subu  $gp, $gp, -4       # CHECK: ADDiu
+                           # CHECK; Imm:4
+  subu  $sp, $sp, -4       # CHECK: ADDiu
+                           # CHECK; Imm:4
+  subu  $sp, $sp, -(4 + 4) # CHECK: ADDiu
+                           # CHECK: Imm:8
+
+  subu  $4, 8              # CHECK: ADDiu
+                           # CHECK; Imm:-8
+  subu  $gp, 8             # CHECK: ADDiu
+                           # CHECK; Imm:-8
+  subu  $sp, 8             # CHECK: ADDiu
+                           # CHECK; Imm:-8
+  subu  $4, -8             # CHECK: ADDiu
+                           # CHECK; Imm:8
+  subu  $gp, -8            # CHECK: ADDiu
+                           # CHECK; Imm:8
+  subu  $sp, -8            # CHECK: ADDiu
+                           # CHECK; Imm:8
+  subu  $sp, -(4 + 4)      # CHECK: ADDiu
+                           # CHECK: Imm:8
+