[llvm] r241537 - MIR Parser: Verify the implicit machine register operands.

Alex Lorenz arphaman at gmail.com
Mon Jul 6 19:08:46 PDT 2015


Author: arphaman
Date: Mon Jul  6 21:08:46 2015
New Revision: 241537

URL: http://llvm.org/viewvc/llvm-project?rev=241537&view=rev
Log:
MIR Parser: Verify the implicit machine register operands.

This commit verifies that the parsed machine instructions contain the implicit
register operands as specified by the MCInstrDesc. Variadic and call
instructions aren't verified.

Reviewers: Duncan P. N. Exon Smith

Differential Revision: http://reviews.llvm.org/D10781

Added:
    llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir
    llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir
    llvm/trunk/test/CodeGen/MIR/X86/missing-implicit-operand.mir
Modified:
    llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
    llvm/trunk/test/CodeGen/MIR/X86/expected-number-after-bb.mir
    llvm/trunk/test/CodeGen/MIR/X86/global-value-operands.mir
    llvm/trunk/test/CodeGen/MIR/X86/large-index-number-error.mir
    llvm/trunk/test/CodeGen/MIR/X86/machine-basic-block-operands.mir
    llvm/trunk/test/CodeGen/MIR/X86/machine-instructions.mir
    llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir
    llvm/trunk/test/CodeGen/MIR/X86/register-mask-operands.mir
    llvm/trunk/test/CodeGen/MIR/X86/unknown-machine-basic-block.mir
    llvm/trunk/test/CodeGen/MIR/X86/unknown-named-machine-basic-block.mir

Modified: llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRParser/MIParser.cpp Mon Jul  6 21:08:46 2015
@@ -29,6 +29,18 @@ using namespace llvm;
 
 namespace {
 
+/// A wrapper struct around the 'MachineOperand' struct that includes a source
+/// range.
+struct MachineOperandWithLocation {
+  MachineOperand Operand;
+  StringRef::iterator Begin;
+  StringRef::iterator End;
+
+  MachineOperandWithLocation(const MachineOperand &Operand,
+                             StringRef::iterator Begin, StringRef::iterator End)
+      : Operand(Operand), Begin(Begin), End(End) {}
+};
+
 class MIParser {
   SourceMgr &SM;
   MachineFunction &MF;
@@ -90,6 +102,9 @@ private:
 
   bool parseInstruction(unsigned &OpCode);
 
+  bool verifyImplicitOperands(ArrayRef<MachineOperandWithLocation> Operands,
+                              const MCInstrDesc &MCID);
+
   void initNames2Regs();
 
   /// Try to convert a register name to a register number. Return true if the
@@ -139,11 +154,12 @@ bool MIParser::parse(MachineInstr *&MI)
   // Parse any register operands before '='
   // TODO: Allow parsing of multiple operands before '='
   MachineOperand MO = MachineOperand::CreateImm(0);
-  SmallVector<MachineOperand, 8> Operands;
+  SmallVector<MachineOperandWithLocation, 8> Operands;
   if (Token.isRegister() || Token.isRegisterFlag()) {
+    auto Loc = Token.location();
     if (parseRegisterOperand(MO, /*IsDef=*/true))
       return true;
-    Operands.push_back(MO);
+    Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
     if (Token.isNot(MIToken::equal))
       return error("expected '='");
     lex();
@@ -157,9 +173,10 @@ bool MIParser::parse(MachineInstr *&MI)
 
   // Parse the remaining machine operands.
   while (Token.isNot(MIToken::Eof)) {
+    auto Loc = Token.location();
     if (parseMachineOperand(MO))
       return true;
-    Operands.push_back(MO);
+    Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location()));
     if (Token.is(MIToken::Eof))
       break;
     if (Token.isNot(MIToken::comma))
@@ -168,12 +185,16 @@ bool MIParser::parse(MachineInstr *&MI)
   }
 
   const auto &MCID = MF.getSubtarget().getInstrInfo()->get(OpCode);
+  if (!MCID.isVariadic()) {
+    // FIXME: Move the implicit operand verification to the machine verifier.
+    if (verifyImplicitOperands(Operands, MCID))
+      return true;
+  }
 
   // TODO: Check for extraneous machine operands.
-  // TODO: Check that this instruction has the implicit register operands.
   MI = MF.CreateMachineInstr(MCID, DebugLoc(), /*NoImplicit=*/true);
   for (const auto &Operand : Operands)
-    MI->addOperand(MF, Operand);
+    MI->addOperand(MF, Operand.Operand);
   return false;
 }
 
@@ -190,6 +211,68 @@ bool MIParser::parseMBB(MachineBasicBloc
   return false;
 }
 
+static const char *printImplicitRegisterFlag(const MachineOperand &MO) {
+  assert(MO.isImplicit());
+  return MO.isDef() ? "implicit-def" : "implicit";
+}
+
+static std::string getRegisterName(const TargetRegisterInfo *TRI,
+                                   unsigned Reg) {
+  assert(TargetRegisterInfo::isPhysicalRegister(Reg) && "expected phys reg");
+  return StringRef(TRI->getName(Reg)).lower();
+}
+
+bool MIParser::verifyImplicitOperands(
+    ArrayRef<MachineOperandWithLocation> Operands, const MCInstrDesc &MCID) {
+  if (MCID.isCall())
+    // We can't verify call instructions as they can contain arbitrary implicit
+    // register and register mask operands.
+    return false;
+
+  // Gather all the expected implicit operands.
+  SmallVector<MachineOperand, 4> ImplicitOperands;
+  if (MCID.ImplicitDefs)
+    for (const uint16_t *ImpDefs = MCID.getImplicitDefs(); *ImpDefs; ++ImpDefs)
+      ImplicitOperands.push_back(
+          MachineOperand::CreateReg(*ImpDefs, true, true));
+  if (MCID.ImplicitUses)
+    for (const uint16_t *ImpUses = MCID.getImplicitUses(); *ImpUses; ++ImpUses)
+      ImplicitOperands.push_back(
+          MachineOperand::CreateReg(*ImpUses, false, true));
+
+  const auto *TRI = MF.getSubtarget().getRegisterInfo();
+  assert(TRI && "Expected target register info");
+  size_t I = ImplicitOperands.size(), J = Operands.size();
+  while (I) {
+    --I;
+    if (J) {
+      --J;
+      const auto &ImplicitOperand = ImplicitOperands[I];
+      const auto &Operand = Operands[J].Operand;
+      if (ImplicitOperand.isIdenticalTo(Operand))
+        continue;
+      if (Operand.isReg() && Operand.isImplicit()) {
+        return error(Operands[J].Begin,
+                     Twine("expected an implicit register operand '") +
+                         printImplicitRegisterFlag(ImplicitOperand) + " %" +
+                         getRegisterName(TRI, ImplicitOperand.getReg()) + "'");
+      }
+    }
+    // TODO: Fix source location when Operands[J].end is right before '=', i.e:
+    // insead of reporting an error at this location:
+    //            %eax = MOV32r0
+    //                 ^
+    // report the error at the following location:
+    //            %eax = MOV32r0
+    //                          ^
+    return error(J < Operands.size() ? Operands[J].End : Token.location(),
+                 Twine("missing implicit register operand '") +
+                     printImplicitRegisterFlag(ImplicitOperands[I]) + " %" +
+                     getRegisterName(TRI, ImplicitOperands[I].getReg()) + "'");
+  }
+  return false;
+}
+
 bool MIParser::parseInstruction(unsigned &OpCode) {
   if (Token.isNot(MIToken::Identifier))
     return error("expected a machine instruction");

Added: llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir?rev=241537&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir Mon Jul  6 21:08:46 2015
@@ -0,0 +1,38 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+  define i32 @foo(i32* %p) {
+  entry:
+    %a = load i32, i32* %p
+    %0 = icmp sle i32 %a, 10
+    br i1 %0, label %less, label %exit
+
+  less:
+    ret i32 0
+
+  exit:
+    ret i32 %a
+  }
+
+
+...
+---
+name:            foo
+body:
+ - id:              0
+   name:            entry
+   instructions:
+     - '%eax = MOV32rm %rdi, 1, _, 0, _'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
+# CHECK: [[@LINE+1]]:26: expected an implicit register operand 'implicit %eflags'
+     - 'JG_1 %bb.2.exit, implicit %eax'
+ - id:              1
+   name:            less
+   instructions:
+     - '%eax = MOV32r0 implicit-def %eflags'
+ - id:              2
+   name:            exit
+   instructions:
+     - 'RETQ %eax'
+...

Added: llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir?rev=241537&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir Mon Jul  6 21:08:46 2015
@@ -0,0 +1,38 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+  define i32 @foo(i32* %p) {
+  entry:
+    %a = load i32, i32* %p
+    %0 = icmp sle i32 %a, 10
+    br i1 %0, label %less, label %exit
+
+  less:
+    ret i32 0
+
+  exit:
+    ret i32 %a
+  }
+
+
+...
+---
+name:            foo
+body:
+ - id:              0
+   name:            entry
+   instructions:
+     - '%eax = MOV32rm %rdi, 1, _, 0, _'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
+# CHECK: [[@LINE+1]]:26: expected an implicit register operand 'implicit %eflags'
+     - 'JG_1 %bb.2.exit, implicit-def %eflags'
+ - id:              1
+   name:            less
+   instructions:
+     - '%eax = MOV32r0 implicit-def %eflags'
+ - id:              2
+   name:            exit
+   instructions:
+     - 'RETQ %eax'
+...

Modified: llvm/trunk/test/CodeGen/MIR/X86/expected-number-after-bb.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/expected-number-after-bb.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/expected-number-after-bb.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/expected-number-after-bb.mir Mon Jul  6 21:08:46 2015
@@ -23,13 +23,13 @@ body:
    name:   entry
    instructions:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
-     - 'CMP32ri8 %eax, 10'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
      # CHECK: [[@LINE+1]]:18: expected a number after '%bb.'
-     - 'JG_1 %bb.nah'
+     - 'JG_1 %bb.nah, implicit %eflags'
  - id: 1
    name: yes
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id: 2
    name: nah
    instructions:

Modified: llvm/trunk/test/CodeGen/MIR/X86/global-value-operands.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/global-value-operands.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/global-value-operands.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/global-value-operands.mir Mon Jul  6 21:08:46 2015
@@ -31,7 +31,7 @@ body:
       # CHECK: - '%rax = MOV64rm %rip, 1, _, @G, _'
       - '%rax = MOV64rm %rip, 1, _, @G, _'
       - '%eax = MOV32rm %rax, 1, _, 0, _'
-      - '%eax = INC32r %eax'
+      - '%eax = INC32r %eax, implicit-def %eflags'
       - 'RETQ %eax'
 ...
 ---
@@ -44,6 +44,6 @@ body:
       # CHECK: - '%rax = MOV64rm %rip, 1, _, @0, _'
       - '%rax = MOV64rm %rip, 1, _, @0, _'
       - '%eax = MOV32rm %rax, 1, _, 0, _'
-      - '%eax = INC32r %eax'
+      - '%eax = INC32r %eax, implicit-def %eflags'
       - 'RETQ %eax'
 ...

Modified: llvm/trunk/test/CodeGen/MIR/X86/large-index-number-error.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/large-index-number-error.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/large-index-number-error.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/large-index-number-error.mir Mon Jul  6 21:08:46 2015
@@ -23,12 +23,12 @@ body:
    name: entry
    instructions:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
-     - 'CMP32ri8 %eax, 10'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
      # CHECK: [[@LINE+1]]:14: expected 32-bit integer (too large)
-     - 'JG_1 %bb.123456789123456'
+     - 'JG_1 %bb.123456789123456, implicit %eflags'
  - id: 1
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id: 2
    instructions:
      - 'RETQ %eax'

Modified: llvm/trunk/test/CodeGen/MIR/X86/machine-basic-block-operands.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/machine-basic-block-operands.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/machine-basic-block-operands.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/machine-basic-block-operands.mir Mon Jul  6 21:08:46 2015
@@ -41,13 +41,13 @@ body:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
      # CHECK:      - 'CMP32ri8 %eax, 10
      # CHECK-NEXT: - 'JG_1 %bb.2.exit
-     - 'CMP32ri8 %eax, 10'
-     - 'JG_1 %bb.2.exit'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
+     - 'JG_1 %bb.2.exit, implicit %eflags'
  # CHECK: name: less
  - id:              1
    name:            less
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id:              2
    name:            exit
    instructions:
@@ -64,11 +64,11 @@ body:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
      # CHECK:      - 'CMP32ri8 %eax, 10
      # CHECK-NEXT: - 'JG_1 %bb.2
-     - 'CMP32ri8 %eax, 10'
-     - 'JG_1 %bb.3'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
+     - 'JG_1 %bb.3, implicit %eflags'
  - id: 1
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id: 3
    instructions:
      - 'RETQ %eax'

Modified: llvm/trunk/test/CodeGen/MIR/X86/machine-instructions.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/machine-instructions.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/machine-instructions.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/machine-instructions.mir Mon Jul  6 21:08:46 2015
@@ -18,8 +18,8 @@ body:
  - id:           0
    name:         entry
    instructions:
-     # CHECK:      - IMUL32rri8
+     # CHECK:      - MOV32rr
      # CHECK-NEXT: - RETQ
-     - IMUL32rri8
+     - MOV32rr
      - ' RETQ '
 ...

Added: llvm/trunk/test/CodeGen/MIR/X86/missing-implicit-operand.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/missing-implicit-operand.mir?rev=241537&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/missing-implicit-operand.mir (added)
+++ llvm/trunk/test/CodeGen/MIR/X86/missing-implicit-operand.mir Mon Jul  6 21:08:46 2015
@@ -0,0 +1,40 @@
+# RUN: not llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+# This test ensures that the MIR parser reports an error when an instruction
+# is missing one of its implicit register operands.
+
+--- |
+
+  define i32 @foo(i32* %p) {
+  entry:
+    %a = load i32, i32* %p
+    %0 = icmp sle i32 %a, 10
+    br i1 %0, label %less, label %exit
+
+  less:
+    ret i32 0
+
+  exit:
+    ret i32 %a
+  }
+
+
+...
+---
+name:            foo
+body:
+ - id:              0
+   name:            entry
+   instructions:
+     - '%eax = MOV32rm %rdi, 1, _, 0, _'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
+# CHECK: [[@LINE+1]]:24: missing implicit register operand 'implicit %eflags'
+     - 'JG_1 %bb.2.exit'
+ - id:              1
+   name:            less
+   instructions:
+     - '%eax = MOV32r0 implicit-def %eflags'
+ - id:              2
+   name:            exit
+   instructions:
+     - 'RETQ %eax'
+...

Modified: llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/named-registers.mir Mon Jul  6 21:08:46 2015
@@ -18,6 +18,6 @@ body:
    instructions:
      # CHECK:      - '%eax = MOV32r0
      # CHECK-NEXT: - 'RETQ %eax
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
      - 'RETQ %eax'
 ...

Modified: llvm/trunk/test/CodeGen/MIR/X86/register-mask-operands.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/register-mask-operands.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/register-mask-operands.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/register-mask-operands.mir Mon Jul  6 21:08:46 2015
@@ -24,7 +24,7 @@ body:
   - id:          0
     name:        body
     instructions:
-      - '%eax = IMUL32rri8 %edi, 11'
+      - '%eax = IMUL32rri8 %edi, 11, implicit-def %eflags'
       - 'RETQ %eax'
 ...
 ---
@@ -36,8 +36,8 @@ body:
     instructions:
       # CHECK:      - 'PUSH64r %rax
       # CHECK-NEXT: - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
-      - 'PUSH64r %rax'
+      - 'PUSH64r %rax, implicit-def %rsp, implicit %rsp'
       - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax'
-      - '%rdx = POP64r'
+      - '%rdx = POP64r implicit-def %rsp, implicit %rsp'
       - 'RETQ %eax'
 ...

Modified: llvm/trunk/test/CodeGen/MIR/X86/unknown-machine-basic-block.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/unknown-machine-basic-block.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/unknown-machine-basic-block.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/unknown-machine-basic-block.mir Mon Jul  6 21:08:46 2015
@@ -26,12 +26,12 @@ body:
    name:         entry
    instructions:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
-     - 'CMP32ri8 %eax, 10'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
      # CHECK: [[@LINE+1]]:14: use of undefined machine basic block #4
-     - 'JG_1 %bb.4'
+     - 'JG_1 %bb.4, implicit %eflags'
  - id: 1
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id: 2
    instructions:
      - 'RETQ %eax'

Modified: llvm/trunk/test/CodeGen/MIR/X86/unknown-named-machine-basic-block.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MIR/X86/unknown-named-machine-basic-block.mir?rev=241537&r1=241536&r2=241537&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/MIR/X86/unknown-named-machine-basic-block.mir (original)
+++ llvm/trunk/test/CodeGen/MIR/X86/unknown-named-machine-basic-block.mir Mon Jul  6 21:08:46 2015
@@ -25,13 +25,13 @@ body:
    name:            entry
    instructions:
      - '%eax = MOV32rm %rdi, 1, _, 0, _'
-     - 'CMP32ri8 %eax, 10'
+     - 'CMP32ri8 %eax, 10, implicit-def %eflags'
      # CHECK: [[@LINE+1]]:14: the name of machine basic block #2 isn't 'hit'
-     - 'JG_1 %bb.2.hit'
+     - 'JG_1 %bb.2.hit, implicit %eflags'
  - id:              1
    name:            less
    instructions:
-     - '%eax = MOV32r0'
+     - '%eax = MOV32r0 implicit-def %eflags'
  - id:              2
    name:            exit
    instructions:





More information about the llvm-commits mailing list