about summary refs log tree commit diff homepage
path: root/lib/Module/InstrumentLegacy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Module/InstrumentLegacy.cpp')
-rw-r--r--lib/Module/InstrumentLegacy.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/lib/Module/InstrumentLegacy.cpp b/lib/Module/InstrumentLegacy.cpp
new file mode 100644
index 00000000..daae8043
--- /dev/null
+++ b/lib/Module/InstrumentLegacy.cpp
@@ -0,0 +1,125 @@
+//===-- InstrumentLegacy.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The KLEE Symbolic Virtual Machine
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "ModuleHelper.h"
+
+#include "Passes.h"
+#include "klee/Support/CompilerWarning.h"
+#include "klee/Support/ErrorHandling.h"
+
+DISABLE_WARNING_PUSH
+DISABLE_WARNING_DEPRECATED_DECLARATIONS
+#include "llvm/Bitcode/BitcodeWriter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueSymbolTable.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Scalar/Scalarizer.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+DISABLE_WARNING_POP
+
+using namespace llvm;
+using namespace klee;
+
+void klee::instrument(bool CheckDivZero, bool CheckOvershift,
+                      llvm::Module *module) {
+  // Inject checks prior to optimization... we also perform the
+  // invariant transformations that we will end up doing later so that
+  // optimize is seeing what is as close as possible to the final
+  // module.
+  legacy::PassManager pm;
+  pm.add(new RaiseAsmPass());
+
+  // This pass will scalarize as much code as possible so that the Executor
+  // does not need to handle operands of vector type for most instructions
+  // other than InsertElementInst and ExtractElementInst.
+  //
+  // NOTE: Must come before division/overshift checks because those passes
+  // don't know how to handle vector instructions.
+  pm.add(createScalarizerPass());
+
+  // This pass will replace atomic instructions with non-atomic operations
+  pm.add(createLowerAtomicPass());
+  if (CheckDivZero)
+    pm.add(new DivCheckPass());
+  if (CheckOvershift)
+    pm.add(new OvershiftCheckPass());
+
+  llvm::DataLayout targetData(module);
+  pm.add(new IntrinsicCleanerPass(targetData));
+  pm.run(*module);
+}
+
+void klee::checkModule(bool DontVerify, llvm::Module *module) {
+  InstructionOperandTypeCheckPass *operandTypeCheckPass =
+      new InstructionOperandTypeCheckPass();
+
+  legacy::PassManager pm;
+  if (!DontVerify)
+    pm.add(createVerifierPass());
+  pm.add(operandTypeCheckPass);
+  pm.run(*module);
+
+  // Enforce the operand type invariants that the Executor expects.  This
+  // implicitly depends on the "Scalarizer" pass to be run in order to succeed
+  // in the presence of vector instructions.
+  if (!operandTypeCheckPass->checkPassed()) {
+    klee_error("Unexpected instruction operand types detected");
+  }
+}
+
+void klee::optimiseAndPrepare(bool OptimiseKLEECall, bool Optimize,
+                              SwitchImplType SwitchType, std::string EntryPoint,
+                              llvm::ArrayRef<const char *> preservedFunctions,
+                              llvm::Module *module) {
+  // Preserve all functions containing klee-related function calls from being
+  // optimised around
+  if (!OptimiseKLEECall) {
+    legacy::PassManager pm;
+    pm.add(new OptNonePass());
+    pm.run(*module);
+  }
+
+  if (Optimize)
+    optimizeModule(module, preservedFunctions);
+
+  // Needs to happen after linking (since ctors/dtors can be modified)
+  // and optimization (since global optimization can rewrite lists).
+  injectStaticConstructorsAndDestructors(module, EntryPoint);
+
+  // Finally, run the passes that maintain invariants we expect during
+  // interpretation. We run the intrinsic cleaner just in case we
+  // linked in something with intrinsics but any external calls are
+  // going to be unresolved. We really need to handle the intrinsics
+  // directly I think?
+  legacy::PassManager pm3;
+  pm3.add(createCFGSimplificationPass());
+  switch (SwitchType) {
+  case SwitchImplType::eSwitchTypeInternal:
+    break;
+  case SwitchImplType::eSwitchTypeSimple:
+    pm3.add(new LowerSwitchPass());
+    break;
+  case SwitchImplType::eSwitchTypeLLVM:
+    pm3.add(createLowerSwitchPass());
+    break;
+  }
+
+  llvm::DataLayout targetData(module);
+  pm3.add(new IntrinsicCleanerPass(targetData));
+  pm3.add(createScalarizerPass());
+  pm3.add(new PhiCleanerPass());
+  pm3.add(new FunctionAliasPass());
+  pm3.run(*module);
+}
\ No newline at end of file