-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathFindLengthChecks.cc
More file actions
104 lines (91 loc) · 3.48 KB
/
FindLengthChecks.cc
File metadata and controls
104 lines (91 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#define DEBUG_TYPE "find-length"
#include "CallInstSet.hh"
#include "CheckGetElementPtrVisitor.hh"
#include "FindLengthChecks.hh"
#include "IIGlueReader.hh"
#include "SRA/SymbolicRangeAnalysis.h"
#include <boost/algorithm/cxx11/any_of.hpp>
#include <boost/foreach.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/combine.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/iterator_range.hpp>
#include <fstream>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <llvm/Analysis/LoopPass.h>
#include <llvm/IR/InstVisitor.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/raw_os_ostream.h>
using namespace boost;
using namespace boost::algorithm;
using namespace llvm;
using namespace std;
static const RegisterPass<FindLengthChecks> registration("find-length",
"Find arrays with a statically known constant or parameter-bounded length.",
true, true);
char FindLengthChecks::ID;
static llvm::cl::opt<std::string>
testOutputName("test-find-length",
llvm::cl::Optional,
llvm::cl::value_desc("filename"),
llvm::cl::desc("Filename to write results to for regression tests"));
inline FindLengthChecks::FindLengthChecks()
: ModulePass(ID) {
}
void FindLengthChecks::getAnalysisUsage(AnalysisUsage &usage) const {
// read-only pass never changes anything
usage.setPreservesAll();
usage.addRequired<IIGlueReader>();
usage.addRequired<SymbolicRangeAnalysis>();
}
bool FindLengthChecks::runOnModule(Module &module) {
DEBUG(dbgs() << "Top of runOnModule()\n");
for (const Function &func : module)
for (const Argument &arg : make_iterator_range(func.arg_begin(), func.arg_end()))
valueSets.insert(make_shared<const ValueSet>(ValueSet{&arg}));
for (Function &func : module) {
if (func.isDeclaration()) continue;
DEBUG(dbgs() << "Analyzing " << func.getName() << "\n");
const SymbolicRangeAnalysis &ra = getAnalysis<SymbolicRangeAnalysis>(func);
CheckGetElementPtrVisitor visitor{maxIndexes[&func], ra, module, lengths[&func], valueSets};
for(BasicBlock &visitee : func) {
DEBUG(dbgs() << "Visiting a new basic block...\n");
visitor.visit(visitee);
}
}
if (!testOutputName.empty()) {
ofstream out(testOutputName);
llvm::raw_os_ostream sink(out);
print(sink, &module);
sink.flush();
out.close();
}
// read-only pass never changes anything
return false;
}
void FindLengthChecks::print(raw_ostream &sink, const Module *module) const {
const IIGlueReader &iiglue = getAnalysis<IIGlueReader>();
for (const Function &func : *module) {
const auto &constantMap = maxIndexes.at(&func);
const auto ¶meterLengthMap = lengths.at(&func);
sink << "Analyzing " << func.getName() << "\n";
for (const Argument &arg : make_iterator_range(func.arg_begin(), func.arg_end())) {
const auto set = valueSets.getValueSetFromValue(&arg);
const auto foundConstant = constantMap.find(set);
if (foundConstant != constantMap.end())
sink << "\tArgument " << arg.getName() << " has max index " << foundConstant->second << '\n';
else {
const auto foundParam = parameterLengthMap.find(set);
if (foundParam != parameterLengthMap.end())
sink << "\tArgument " << arg.getName() << " has max index argument " << (*foundParam->second->begin())->getName() << '\n';
else if (iiglue.isArray(arg))
sink << "\tArgument " << arg.getName() << " has unknown max index.\n";
}
}
}
}