Skip to content

Commit c537f56

Browse files
committed
Add pass to turn function into Unreachable and script to find UB.
This adds a pass to replace function bodies with 'unreachable' and a script that checks if the result still verifies. This can be used to find functions in llvm-lit tests that have unconditional UB using llvm-lit -j4 -sv -Dopt=~/find-ub-in-test.sh Examples of found & fixed UB: * b8d728a * 684a82f Differential Revision: https://reviews.llvm.org/D127607
1 parent 961c66c commit c537f56

File tree

6 files changed

+111
-0
lines changed

6 files changed

+111
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===- ToUnreachable.h - Turn function into unreachable. --------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef LLVM_TRANSFORMS_SCALAR_TOUNREACHABLE_H
12+
#define LLVM_TRANSFORMS_SCALAR_TOUNREACHABLE_H
13+
14+
#include "llvm/IR/PassManager.h"
15+
16+
namespace llvm {
17+
struct ToUnreachablePass : public PassInfoMixin<ToUnreachablePass> {
18+
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
19+
};
20+
} // namespace llvm
21+
22+
#endif

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@
299299
#include "llvm/Transforms/Scalar/StraightLineStrengthReduce.h"
300300
#include "llvm/Transforms/Scalar/StructurizeCFG.h"
301301
#include "llvm/Transforms/Scalar/TailRecursionElimination.h"
302+
#include "llvm/Transforms/Scalar/ToUnreachable.h"
302303
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
303304
#include "llvm/Transforms/Utils/AddDiscriminators.h"
304305
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ FUNCTION_PASS("view-dom-only", DomOnlyViewer())
495495
FUNCTION_PASS("view-post-dom", PostDomViewer())
496496
FUNCTION_PASS("view-post-dom-only", PostDomOnlyViewer())
497497
FUNCTION_PASS("wasm-eh-prepare", WasmEHPreparePass())
498+
FUNCTION_PASS("to-unreachable", ToUnreachablePass())
498499
#undef FUNCTION_PASS
499500

500501
#ifndef FUNCTION_PASS_WITH_PARAMS

llvm/lib/Transforms/Scalar/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ add_llvm_component_library(LLVMScalarOpts
7878
StraightLineStrengthReduce.cpp
7979
StructurizeCFG.cpp
8080
TailRecursionElimination.cpp
81+
ToUnreachable.cpp
8182
WarnMissedTransforms.cpp
8283

8384
ADDITIONAL_HEADER_DIRS
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===- ToUnreachable.cpp - Turn function into unreachable. ------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#include "llvm/Transforms/Scalar/ToUnreachable.h"
12+
#include "llvm/ADT/SmallVector.h"
13+
#include "llvm/IR/Function.h"
14+
#include "llvm/IR/Instructions.h"
15+
16+
using namespace llvm;
17+
18+
PreservedAnalyses ToUnreachablePass::run(Function &F,
19+
FunctionAnalysisManager &AM) {
20+
SmallVector<BasicBlock *> AllBlocks;
21+
for (BasicBlock &BB : F) {
22+
AllBlocks.push_back(&BB);
23+
BB.dropAllReferences();
24+
}
25+
26+
for (unsigned I = 1; I < AllBlocks.size(); ++I)
27+
AllBlocks[I]->eraseFromParent();
28+
29+
for (Instruction &I : make_early_inc_range(*AllBlocks[0]))
30+
I.eraseFromParent();
31+
32+
new UnreachableInst(F.getContext(), AllBlocks[0]);
33+
return PreservedAnalyses::none();
34+
}

llvm/utils/find-ub-in-test.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#!/bin/bash
2+
3+
FILE=""
4+
S_OPT=""
5+
ORIG_ARGS="$@"
6+
for arg in $@; do
7+
shift
8+
if [[ $arg == *".ll" ]]; then
9+
FILE="${arg}"
10+
fi
11+
done
12+
13+
if [[ "$OSTYPE" == "darwin"* ]]; then
14+
# Mac
15+
TV_SHAREDLIB=tv.dylib
16+
else
17+
# Linux, Cygwin/Msys, or Win32?
18+
TV_SHAREDLIB=tv.so
19+
fi
20+
21+
TV_REPORT_DIR=""
22+
TIMEOUT=""
23+
TV_SMT_TO=""
24+
TV_SMT_STATS=""
25+
TV_REPORT_DIR=-tv-report-dir=alive2/build/logs
26+
TIMEOUT=""
27+
TV_SMT_TO="-tv-smt-to=100000"
28+
TV_SMT_STATS=-tv-smt-stats
29+
30+
NPM_PLUGIN="-load-pass-plugin=alive2/build/tv/$TV_SHAREDLIB"
31+
32+
# Write input to temporary file so it can be passed to multiple opt calls, even
33+
# if read from stdin. Run opt with original args, save output.
34+
OUT=$(mktemp)
35+
if [[ $FILE == "" ]]; then
36+
FILE="$(mktemp)"
37+
bin/opt > $FILE
38+
bin/opt $ORIG_ARGS $FILE > $OUT
39+
else
40+
bin/opt $ORIG_ARGS > $OUT
41+
fi
42+
43+
# Check if replacing all input functions with unreachable still verifies. If it does, the input has likely unconditional UB.
44+
bin/opt -load=live2/build/tv/$TV_SHAREDLIB $NPM_PLUGIN -tv-exit-on-error -passes="tv,to-unreachable,tv" -disable-output $FILE $TV_SMT_TO $TV_REPORT_DIR $TV_SMT_STATS 2> /dev/null
45+
ret=$?
46+
47+
cat $OUT
48+
49+
if [ $ret -ne 0 ]; then
50+
exit 0
51+
fi
52+
exit 1

0 commit comments

Comments
 (0)