[llvm] r372923 - [Verifier] add invariant check for callbr

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 25 15:28:27 PDT 2019


Author: nickdesaulniers
Date: Wed Sep 25 15:28:27 2019
New Revision: 372923

URL: http://llvm.org/viewvc/llvm-project?rev=372923&view=rev
Log:
[Verifier] add invariant check for callbr

Summary:
The list of indirect labels should ALWAYS have their blockaddresses as
argument operands to the callbr (but not necessarily the other way
around).  Add an invariant that checks this.

The verifier catches a bad test case that was added recently in r368478.
I think that was a simple mistake, and the test was made less strict in
regards to the precise addresses (as those weren't specifically the
point of the test).

This invariant will be used to find a reported bug.

Link: https://www.spinics.net/lists/arm-kernel/msg753473.html
Link: https://github.com/ClangBuiltLinux/linux/issues/649

Reviewers: craig.topper, void, chandlerc

Reviewed By: void

Subscribers: ychen, lebedev.ri, javed.absar, kristof.beyls, hiraditya, llvm-commits, srhines

Tags: #llvm

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

Added:
    llvm/trunk/test/Verifier/callbr.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/lib/IR/Verifier.cpp
    llvm/trunk/test/CodeGen/AArch64/callbr-asm-obj-file.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=372923&r1=372922&r2=372923&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Wed Sep 25 15:28:27 2019
@@ -7070,7 +7070,7 @@ Syntax:
 ::
 
       <result> = callbr [cconv] [ret attrs] [addrspace(<num>)] <ty>|<fnty> <fnptrval>(<function args>) [fn attrs]
-                    [operand bundles] to label <normal label> or jump [other labels]
+                    [operand bundles] to label <normal label> [other labels]
 
 Overview:
 """""""""
@@ -7114,7 +7114,8 @@ This instruction requires several argume
 #. '``normal label``': the label reached when the called function
    executes a '``ret``' instruction.
 #. '``other labels``': the labels reached when a callee transfers control
-   to a location other than the normal '``normal label``'
+   to a location other than the normal '``normal label``'. The blockaddress
+   constant for these should also be in the list of '``function args``'.
 #. The optional :ref:`function attributes <fnattrs>` list.
 #. The optional :ref:`operand bundles <opbundles>` list.
 
@@ -7136,7 +7137,7 @@ Example:
 .. code-block:: text
 
       callbr void asm "", "r,x"(i32 %x, i8 *blockaddress(@foo, %fail))
-                  to label %normal or jump [label %fail]
+                  to label %normal [label %fail]
 
 .. _i_resume:
 

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=372923&r1=372922&r2=372923&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Wed Sep 25 15:28:27 2019
@@ -2504,6 +2504,15 @@ void Verifier::visitCallBrInst(CallBrIns
         Assert(CBI.getOperand(i) != CBI.getOperand(j),
                "Duplicate callbr destination!", &CBI);
   }
+  {
+    SmallPtrSet<BasicBlock *, 4> ArgBBs;
+    for (Value *V : CBI.args())
+      if (auto *BA = dyn_cast<BlockAddress>(V))
+        ArgBBs.insert(BA->getBasicBlock());
+    for (BasicBlock *BB : CBI.getIndirectDests())
+      Assert(ArgBBs.find(BB) != ArgBBs.end(),
+             "Indirect label missing from arglist.", &CBI);
+  }
 
   visitTerminator(CBI);
 }

Modified: llvm/trunk/test/CodeGen/AArch64/callbr-asm-obj-file.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/callbr-asm-obj-file.ll?rev=372923&r1=372922&r2=372923&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/callbr-asm-obj-file.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/callbr-asm-obj-file.ll Wed Sep 25 15:28:27 2019
@@ -6,11 +6,11 @@
 
 @l = common hidden local_unnamed_addr global i32 0, align 4
 
-; CHECK-LABEL: 0000000000000000 test1:
-; CHECK-LABEL: 0000000000000018 $d.1:
-; CHECK-LABEL: 0000000000000020 $x.2:
+; CHECK-LABEL: test1:
+; CHECK-LABEL: $d.1:
+; CHECK-LABEL: $x.2:
 ; CHECK-NEXT:    b #16 <$x.4+0x4>
-; CHECK-LABEL: 000000000000002c $x.4:
+; CHECK-LABEL: $x.4:
 ; CHECK-NEXT:    b #4 <$x.4+0x4>
 ; CHECK-NEXT:    mov w0, wzr
 ; CHECK-NEXT:    ldr x30, [sp], #16
@@ -40,11 +40,11 @@ declare dso_local i32 @g(...) local_unna
 
 declare dso_local i32 @i(...) local_unnamed_addr
 
-; CHECK-LABEL: 000000000000003c test2:
-; CHECK:         bl #0 <test2+0x18>
-; CHECK-LABEL: 0000000000000064 $d.5:
-; CHECK-LABEL: 000000000000006c $x.6:
-; CHECK-NEXT:    b #-24 <test2+0x18>
+; CHECK-LABEL: test2:
+; CHECK:         bl #0 <test2+0x10>
+; CHECK-LABEL: $d.5:
+; CHECK-LABEL: $x.6:
+; CHECK-NEXT:    b #16 <$x.8+0x4>
 define hidden i32 @test2() local_unnamed_addr {
   %1 = load i32, i32* @l, align 4
   %2 = icmp eq i32 %1, 0
@@ -57,7 +57,7 @@ define hidden i32 @test2() local_unnamed
 
 6:                                                ; preds = %3
   callbr void asm sideeffect "1: nop\0A\09.quad b\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test2, %7))
-          to label %10 [label %9]
+          to label %10 [label %7]
 
 7:                                                ; preds = %3
   %8 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)()
@@ -70,11 +70,11 @@ define hidden i32 @test2() local_unnamed
   ret i32 undef
 }
 
-; CHECK-LABEL: 0000000000000084 test3:
-; CHECK-LABEL: 00000000000000a8 $d.9:
-; CHECK-LABEL: 00000000000000b0 $x.10:
+; CHECK-LABEL: test3:
+; CHECK-LABEL: $d.9:
+; CHECK-LABEL: $x.10:
 ; CHECK-NEXT:    b #20 <$x.12+0x8>
-; CHECK-LABEL: 00000000000000bc $x.12:
+; CHECK-LABEL: $x.12:
 ; CHECK-NEXT:    b #4 <$x.12+0x4>
 ; CHECK-NEXT:    mov w0, wzr
 ; CHECK-NEXT:    ldr x30, [sp], #16

Added: llvm/trunk/test/Verifier/callbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/callbr.ll?rev=372923&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/callbr.ll (added)
+++ llvm/trunk/test/Verifier/callbr.ll Wed Sep 25 15:28:27 2019
@@ -0,0 +1,50 @@
+; RUN: not opt -S %s -verify 2>&1 | FileCheck %s
+
+; CHECK: Indirect label missing from arglist.
+define void @foo() {
+  ; The %4 in the indirect label list is not found in the blockaddresses in the
+  ; arg list (bad).
+  callbr void asm sideeffect "${0:l} {1:l}", "X,X"(i8* blockaddress(@foo, %3), i8* blockaddress(@foo, %2))
+  to label %1 [label %4, label %2]
+1:
+  ret void
+2:
+  ret void
+3:
+  ret void
+4:
+  ret void
+}
+
+; CHECK-NOT: Indirect label missing from arglist.
+define void @bar() {
+  ; %4 and %2 are both in the indirect label list and the arg list (good).
+  callbr void asm sideeffect "${0:l} ${1:l}", "X,X"(i8* blockaddress(@bar, %4), i8* blockaddress(@bar, %2))
+  to label %1 [label %4, label %2]
+1:
+  ret void
+2:
+  ret void
+3:
+  ret void
+4:
+  ret void
+}
+
+; CHECK-NOT: Indirect label missing from arglist.
+define void @baz() {
+  ; note %2 blockaddress. Such a case is possible when passing the address of
+  ; a label as an input to the inline asm (both address of label and asm goto
+  ; use blockaddress constants; we're testing that the indirect label list from
+  ; the asm goto is in the arg list to the asm).
+  callbr void asm sideeffect "${0:l} ${1:l} ${2:l}", "X,X,X"(i8* blockaddress(@baz, %4), i8* blockaddress(@baz, %2), i8* blockaddress(@baz, %3))
+  to label %1 [label %3, label %4]
+1:
+  ret void
+2:
+  ret void
+3:
+  ret void
+4:
+  ret void
+}




More information about the llvm-commits mailing list