diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2487,6 +2487,17 @@ Assert(CBI.getOperand(i) != CBI.getOperand(j), "Duplicate callbr destination!", &CBI); } + for (auto *BB : CBI.getIndirectDests()) { + BlockAddress *BA = BlockAddress::get(BB); + bool Found = false; + for (unsigned i = 0, e = CBI.getNumOperands(); i != e; ++i) + if (CBI.getOperand(i) == BA) { + Found = true; + break; + } + Assert(Found, "Did not find indirect destination in callbr operand list", + &CBI); + } visitTerminator(CBI); } diff --git a/llvm/test/Verifier/callbr.ll b/llvm/test/Verifier/callbr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/callbr.ll @@ -0,0 +1,15 @@ +; RUN: not opt -verify -S < %s 2>&1 | FileCheck %s + +; CHECK: Did not find indirect destination in callbr operand list + +define i32 @test_asm_goto(i32 %x){ +entry: + callbr void asm "", "r,X"(i32 %x, i8* blockaddress(@test_asm_goto, %not_in_indirect_list)) to label %fallthrough [label %indirect] + +fallthrough: + ret i32 1 +indirect: + ret i32 0 +not_in_indirect_list: + ret i32 2 +}