|
1 | 1 | #include "klee/Core/MockBuilder.h" |
2 | 2 |
|
| 3 | +#include "klee/Module/Annotation.h" |
3 | 4 | #include "klee/Support/ErrorHandling.h" |
4 | 5 | #include "llvm/IR/IRBuilder.h" |
5 | 6 | #include "llvm/IR/Module.h" |
6 | 7 |
|
7 | 8 | #include <memory> |
| 9 | +#include <utility> |
8 | 10 |
|
9 | 11 | namespace klee { |
10 | 12 |
|
11 | 13 | MockBuilder::MockBuilder(const llvm::Module *initModule, |
12 | 14 | std::string mockEntrypoint, std::string userEntrypoint, |
13 | | - std::map<std::string, llvm::Type *> externals) |
| 15 | + std::map<std::string, llvm::Type *> externals, |
| 16 | + Annotations annotations) |
14 | 17 | : userModule(initModule), externals(std::move(externals)), |
| 18 | + annotations(std::move(annotations)), |
15 | 19 | mockEntrypoint(std::move(mockEntrypoint)), |
16 | 20 | userEntrypoint(std::move(userEntrypoint)) {} |
17 | 21 |
|
@@ -115,6 +119,11 @@ void MockBuilder::buildExternalFunctionsDefinitions() { |
115 | 119 | continue; |
116 | 120 | } |
117 | 121 |
|
| 122 | + const auto annotation = annotations.find(extName); |
| 123 | + if (annotation != annotations.end()) { |
| 124 | + buildAnnotationForExternalFunctionParams(func, annotation->second); |
| 125 | + } |
| 126 | + |
118 | 127 | auto *mockReturnValue = |
119 | 128 | builder->CreateAlloca(func->getReturnType(), nullptr); |
120 | 129 | buildCallKleeMakeSymbol("klee_make_mock", mockReturnValue, |
@@ -149,4 +158,67 @@ void MockBuilder::buildCallKleeMakeSymbol(const std::string &klee_function_name, |
149 | 158 | gep}); |
150 | 159 | } |
151 | 160 |
|
| 161 | +// TODO: add method for return value of external functions. |
| 162 | +void MockBuilder::buildAnnotationForExternalFunctionParams( |
| 163 | + llvm::Function *func, Annotation &annotation) { |
| 164 | + for (size_t i = 1; i < annotation.statements.size(); i++) { |
| 165 | + const auto arg = func->getArg(i - 1); |
| 166 | + for (const auto &statement : annotation.statements[i]) { |
| 167 | + llvm::Value *elem = goByOffset(arg, statement->offset); |
| 168 | + switch (statement->getStatementName()) { |
| 169 | + case Annotation::StatementKind::Deref: { |
| 170 | + if (!elem->getType()->isPointerTy()) { |
| 171 | + klee_error("Incorrect annotation offset."); |
| 172 | + } |
| 173 | + builder->CreateLoad(elem); |
| 174 | + break; |
| 175 | + } |
| 176 | + case Annotation::StatementKind::InitNull: { |
| 177 | + // TODO |
| 178 | + } |
| 179 | + case Annotation::StatementKind::Unknown: |
| 180 | + default: |
| 181 | + __builtin_unreachable(); |
| 182 | + } |
| 183 | + } |
| 184 | + } |
| 185 | + |
| 186 | + for (const auto &property : annotation.properties) { |
| 187 | + switch (property) { |
| 188 | + case Annotation::Property::Determ: { |
| 189 | + // TODO |
| 190 | + } |
| 191 | + case Annotation::Property::Noreturn: { |
| 192 | + // TODO |
| 193 | + } |
| 194 | + case Annotation::Property::Unknown: |
| 195 | + default: |
| 196 | + __builtin_unreachable(); |
| 197 | + } |
| 198 | + } |
| 199 | +} |
| 200 | + |
| 201 | +llvm::Value *MockBuilder::goByOffset(llvm::Value *value, |
| 202 | + const std::vector<std::string> &offset) { |
| 203 | + llvm::Value *current = value; |
| 204 | + for (const auto &inst : offset) { |
| 205 | + if (inst == "*") { |
| 206 | + if (!current->getType()->isPointerTy()) { |
| 207 | + klee_error("Incorrect annotation offset."); |
| 208 | + } |
| 209 | + current = builder->CreateLoad(current); |
| 210 | + } else if (inst == "&") { |
| 211 | + auto addr = builder->CreateAlloca(current->getType()); |
| 212 | + current = builder->CreateStore(current, addr); |
| 213 | + } else { |
| 214 | + const size_t index = std::stol(inst); |
| 215 | + if (!(current->getType()->isPointerTy() || current->getType()->isArrayTy())) { |
| 216 | + klee_error("Incorrect annotation offset."); |
| 217 | + } |
| 218 | + current = builder->CreateConstInBoundsGEP1_64(current, index); |
| 219 | + } |
| 220 | + } |
| 221 | + return current; |
| 222 | +} |
| 223 | + |
152 | 224 | } // namespace klee |
0 commit comments