klee
InstructionOperandTypeCheckPass.cpp
Go to the documentation of this file.
1//===-- InstructionOperandTypeCheckPass.cpp ---------------------*- C++ -*-===//
2//
3// The KLEE Symbolic Virtual Machine
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "Passes.h"
10#include "klee/Config/Version.h"
12#include "llvm/Support/raw_ostream.h"
13
14using namespace llvm;
15
16namespace {
17
18void printOperandWarning(const char *expected, const Instruction *i, Type *ty,
19 unsigned opNum) {
20 std::string msg;
21 llvm::raw_string_ostream ss(msg);
22 ss << "Found unexpected type (" << *ty << ") at operand " << opNum
23 << ". Expected " << expected << " in " << *i;
24 i->print(ss);
25 ss.flush();
26 klee::klee_warning("%s", msg.c_str());
27}
28
29bool checkOperandTypeIsScalarInt(const Instruction *i, unsigned opNum) {
30 assert(opNum < i->getNumOperands());
31 llvm::Type *ty = i->getOperand(opNum)->getType();
32 if (!(ty->isIntegerTy())) {
33 printOperandWarning("scalar integer", i, ty, opNum);
34 return false;
35 }
36 return true;
37}
38
39bool checkOperandTypeIsScalarIntOrPointer(const Instruction *i,
40 unsigned opNum) {
41 assert(opNum < i->getNumOperands());
42 llvm::Type *ty = i->getOperand(opNum)->getType();
43 if (!(ty->isIntegerTy() || ty->isPointerTy())) {
44 printOperandWarning("scalar integer or pointer", i, ty, opNum);
45 return false;
46 }
47 return true;
48}
49
50bool checkOperandTypeIsScalarPointer(const Instruction *i, unsigned opNum) {
51 assert(opNum < i->getNumOperands());
52 llvm::Type *ty = i->getOperand(opNum)->getType();
53 if (!(ty->isPointerTy())) {
54 printOperandWarning("scalar pointer", i, ty, opNum);
55 return false;
56 }
57 return true;
58}
59
60bool checkOperandTypeIsScalarFloat(const Instruction *i, unsigned opNum) {
61 assert(opNum < i->getNumOperands());
62 llvm::Type *ty = i->getOperand(opNum)->getType();
63 if (!(ty->isFloatingPointTy())) {
64 printOperandWarning("scalar float", i, ty, opNum);
65 return false;
66 }
67 return true;
68}
69
70bool checkOperandsHaveSameType(const Instruction *i, unsigned opNum0,
71 unsigned opNum1) {
72 assert(opNum0 < i->getNumOperands());
73 assert(opNum1 < i->getNumOperands());
74 llvm::Type *ty0 = i->getOperand(opNum0)->getType();
75 llvm::Type *ty1 = i->getOperand(opNum1)->getType();
76 if (!(ty0 == ty1)) {
77 std::string msg;
78 llvm::raw_string_ostream ss(msg);
79 ss << "Found mismatched type (" << *ty0 << " != " << *ty1
80 << ") for operands" << opNum0 << " and " << opNum1
81 << ". Expected operand types to match in " << *i;
82 i->print(ss);
83 ss.flush();
84 klee::klee_warning("%s", msg.c_str());
85 return false;
86 }
87 return true;
88}
89
90bool checkInstruction(const Instruction *i) {
91 switch (i->getOpcode()) {
92 case Instruction::Select: {
93 // Note we do not enforce that operand 1 and 2 are scalar because the
94 // scalarizer pass might not remove these. This could be selecting which
95 // vector operand to feed to another instruction. The Executor can handle
96 // this so case so this is not a problem
97 return checkOperandTypeIsScalarInt(i, 0) &
98 checkOperandsHaveSameType(i, 1, 2);
99 }
100 // Integer arithmetic, logical and shifting
101 case Instruction::Add:
102 case Instruction::Sub:
103 case Instruction::Mul:
104 case Instruction::UDiv:
105 case Instruction::SDiv:
106 case Instruction::URem:
107 case Instruction::SRem:
108 case Instruction::And:
109 case Instruction::Or:
110 case Instruction::Xor:
111 case Instruction::Shl:
112 case Instruction::LShr:
113 case Instruction::AShr: {
114 return checkOperandTypeIsScalarInt(i, 0) &
115 checkOperandTypeIsScalarInt(i, 1);
116 }
117 // Integer comparison
118 case Instruction::ICmp: {
119 return checkOperandTypeIsScalarIntOrPointer(i, 0) &
120 checkOperandTypeIsScalarIntOrPointer(i, 1);
121 }
122 // Integer Conversion
123 case Instruction::Trunc:
124 case Instruction::ZExt:
125 case Instruction::SExt:
126 case Instruction::IntToPtr: {
127 return checkOperandTypeIsScalarInt(i, 0);
128 }
129 case Instruction::PtrToInt: {
130 return checkOperandTypeIsScalarPointer(i, 0);
131 }
132 // TODO: Figure out if Instruction::BitCast needs checking
133 // Floating point arithmetic
134 case Instruction::FAdd:
135 case Instruction::FSub:
136 case Instruction::FMul:
137 case Instruction::FDiv:
138 case Instruction::FRem: {
139 return checkOperandTypeIsScalarFloat(i, 0) &
140 checkOperandTypeIsScalarFloat(i, 1);
141 }
142 // Floating point conversion
143 case Instruction::FPTrunc:
144 case Instruction::FPExt:
145 case Instruction::FPToUI:
146 case Instruction::FPToSI: {
147 return checkOperandTypeIsScalarFloat(i, 0);
148 }
149 case Instruction::UIToFP:
150 case Instruction::SIToFP: {
151 return checkOperandTypeIsScalarInt(i, 0);
152 }
153 // Floating point comparison
154 case Instruction::FCmp: {
155 return checkOperandTypeIsScalarFloat(i, 0) &
156 checkOperandTypeIsScalarFloat(i, 1);
157 }
158 default:
159 // Treat all other instructions as conforming
160 return true;
161 }
162}
163}
164
165namespace klee {
166
168
171 for (Module::iterator fi = M.begin(), fe = M.end(); fi != fe; ++fi) {
172 for (Function::iterator bi = fi->begin(), be = fi->end(); bi != be; ++bi) {
173 for (BasicBlock::iterator ii = bi->begin(), ie = bi->end(); ii != ie;
174 ++ii) {
175 Instruction *i = &*ii;
176 instructionOperandsConform &= checkInstruction(i);
177 }
178 }
179 }
180
181 return false;
182}
183}
Definition: main.cpp:291
void void void klee_warning(const char *msg,...) __attribute__((format(printf