diff options
Diffstat (limited to 'lib/Module/OptNone.cpp')
-rw-r--r-- | lib/Module/OptNone.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/lib/Module/OptNone.cpp b/lib/Module/OptNone.cpp new file mode 100644 index 00000000..08837488 --- /dev/null +++ b/lib/Module/OptNone.cpp @@ -0,0 +1,59 @@ +//===-- OptNone.cpp -------------------------------------------------------===// +// +// The KLEE Symbolic Virtual Machine +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Passes.h" + +#include "klee/Config/Version.h" + +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Module.h" + +namespace klee { + +char OptNonePass::ID; + +bool OptNonePass::runOnModule(llvm::Module &M) { + // Find list of functions that start with `klee_` + // and mark all functions that contain such call or invoke as optnone + llvm::SmallPtrSet<llvm::Function *,16> CallingFunctions; + for (auto &F : M) { + if (!F.hasName() || !F.getName().startswith("klee_")) + continue; +#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5) + for (auto *U : F.users()) { + // skip non-calls and non-invokes + if (!llvm::isa<llvm::CallInst>(U) && !llvm::isa<llvm::InvokeInst>(U)) + continue; + auto *Inst = llvm::cast<llvm::Instruction>(U); + CallingFunctions.insert(Inst->getParent()->getParent()); + } +#else + for (auto i = F.use_begin(), e = F.use_end(); i != e; ++i) { + if (auto Inst = llvm::dyn_cast<llvm::Instruction>(*i)) { + CallingFunctions.insert(Inst->getParent()->getParent()); + } + } +#endif + } + + bool changed = false; + for (auto F : CallingFunctions) { + // Skip if already annotated + if (F->hasFnAttribute(llvm::Attribute::OptimizeNone)) + continue; + F->addFnAttr(llvm::Attribute::OptimizeNone); + F->addFnAttr(llvm::Attribute::NoInline); + changed = true; + } + + return changed; +} +} // namespace klee |