about summary refs log tree commit diff homepage
path: root/include
diff options
context:
space:
mode:
authorMartin Nowack <martin.nowack@gmail.com>2018-05-15 15:12:12 +0100
committerCristian Cadar <c.cadar@imperial.ac.uk>2018-07-04 15:13:02 +0100
commitef90f1e219fec27a3d594158ae5f380a9e9a2f37 (patch)
tree0a02b5da762b4bc59f7f6bd2453a2a6591f00062 /include
parent6803c37be83f0c97c95870a18cb230e135a131c9 (diff)
downloadklee-ef90f1e219fec27a3d594158ae5f380a9e9a2f37.tar.gz
Reorder linking and optimizations
Link intrinsic library before executing optimizations.
This makes sure that any optimization run by KLEE on the module
is executed for the intrinsic library as well.

Support .ll files as input for KLEE as well.
Diffstat (limited to 'include')
-rw-r--r--include/klee/Internal/Module/KModule.h55
-rw-r--r--include/klee/Internal/Support/ModuleUtil.h73
-rw-r--r--include/klee/Interpreter.h14
3 files changed, 96 insertions, 46 deletions
diff --git a/include/klee/Internal/Module/KModule.h b/include/klee/Internal/Module/KModule.h
index e8ded725..478e24d7 100644
--- a/include/klee/Internal/Module/KModule.h
+++ b/include/klee/Internal/Module/KModule.h
@@ -13,7 +13,10 @@
 #include "klee/Config/Version.h"
 #include "klee/Interpreter.h"
 
+#include "llvm/ADT/ArrayRef.h"
+
 #include <map>
+#include <memory>
 #include <set>
 #include <vector>
 
@@ -50,12 +53,11 @@ namespace klee {
     /// "coverable" for statistics and search heuristics.
     bool trackCoverage;
 
-  private:
-    KFunction(const KFunction&);
-    KFunction &operator=(const KFunction&);
-
   public:
     explicit KFunction(llvm::Function*, KModule *);
+    KFunction(const KFunction &) = delete;
+    KFunction &operator=(const KFunction &) = delete;
+
     ~KFunction();
 
     unsigned getArgRegister(unsigned index) { return index; }
@@ -80,24 +82,24 @@ namespace klee {
 
   class KModule {
   public:
-    llvm::Module *module;
-    llvm::DataLayout *targetData;
+    std::unique_ptr<llvm::Module> module;
+    std::unique_ptr<llvm::DataLayout> targetData;
 
     // Our shadow versions of LLVM structures.
-    std::vector<KFunction*> functions;
+    std::vector<std::unique_ptr<KFunction>> functions;
     std::map<llvm::Function*, KFunction*> functionMap;
 
     // Functions which escape (may be called indirectly)
     // XXX change to KFunction
     std::set<llvm::Function*> escapingFunctions;
 
-    InstructionInfoTable *infos;
+    std::unique_ptr<InstructionInfoTable> infos;
 
     std::vector<llvm::Constant*> constants;
-    std::map<const llvm::Constant*, KConstant*> constantMap;
+    std::map<const llvm::Constant *, std::unique_ptr<KConstant>> constantMap;
     KConstant* getKConstant(const llvm::Constant *c);
 
-    Cell *constantTable;
+    std::unique_ptr<Cell[]> constantTable;
 
     // Functions which are part of KLEE runtime
     std::set<const llvm::Function*> internalFunctions;
@@ -107,14 +109,37 @@ namespace klee {
     void addInternalFunction(const char* functionName);
 
   public:
-    KModule(llvm::Module *_module);
-    ~KModule();
+    KModule() = default;
 
-    /// Initialize local data structures.
+    /// Optimise and prepare module such that KLEE can execute it
     //
+    void optimiseAndPrepare(const Interpreter::ModuleOptions &opts,
+                            llvm::ArrayRef<const char *>);
+
+    /// Manifest the generated module (e.g. assembly.ll, output.bc) and
+    /// prepares KModule
+    ///
+    /// @param ih
+    /// @param forceSourceOutput true if assembly.ll should be created
+    ///
     // FIXME: ihandler should not be here
-    void prepare(const Interpreter::ModuleOptions &opts, 
-                 InterpreterHandler *ihandler);
+    void manifest(InterpreterHandler *ih, bool forceSourceOutput);
+
+    /// Link the provided modules together as one KLEE module.
+    ///
+    /// If the entry point is empty, all modules are linked together.
+    /// If the entry point is not empty, all modules are linked which resolve
+    /// the dependencies of the module containing entryPoint
+    ///
+    /// @param modules list of modules to be linked together
+    /// @param entryPoint name of the function which acts as the program's entry
+    /// point
+    /// @return true if at least one module has been linked in, false if nothing
+    /// changed
+    bool link(std::vector<std::unique_ptr<llvm::Module>> &modules,
+              const std::string &entryPoint);
+
+    void instrument(const Interpreter::ModuleOptions &opts);
 
     /// Return an id for the given constant, creating a new one if necessary.
     unsigned getConstantID(llvm::Constant *c, KInstruction* ki);
diff --git a/include/klee/Internal/Support/ModuleUtil.h b/include/klee/Internal/Support/ModuleUtil.h
index 4c3243ce..8c819f40 100644
--- a/include/klee/Internal/Support/ModuleUtil.h
+++ b/include/klee/Internal/Support/ModuleUtil.h
@@ -13,8 +13,6 @@
 #include "klee/Config/Version.h"
 
 #include "llvm/IR/Module.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/LLVMContext.h"
 
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 5)
 #include "llvm/IR/CallSite.h"
@@ -22,33 +20,58 @@
 #include "llvm/Support/CallSite.h"
 #endif
 
+#include <memory>
 #include <string>
+#include <vector>
 
 namespace klee {
-  /// Load llvm module from a bitcode archive file.
-  llvm::Module *loadModule(llvm::LLVMContext &ctx,
-                           const std::string &path,
-                           std::string &errorMsg);
-
-  /// Link a module with a specified bitcode archive.
-  llvm::Module *linkWithLibrary(llvm::Module *module,
-                                const std::string &libraryName);
-
-  /// Return the Function* target of a Call or Invoke instruction, or
-  /// null if it cannot be determined (should be only for indirect
-  /// calls, although complicated constant expressions might be
-  /// another possibility).
-  ///
-  /// If `moduleIsFullyLinked` is set to true it will be assumed that the
-  //  module containing the `llvm::CallSite` is fully linked. This assumption
-  //  allows resolution of functions that are marked as overridable.
-  llvm::Function *getDirectCallTarget(llvm::CallSite, bool moduleIsFullyLinked);
-
-  /// Return true iff the given Function value is used in something
-  /// other than a direct call (or a constant expression that
-  /// terminates in a direct call).
-  bool functionEscapes(const llvm::Function *f);
 
+/// Links all the modules together into one and returns it.
+///
+/// All the modules which are used for resolving entities are freed,
+/// all the remaining ones are preserved.
+///
+/// @param modules List of modules to link together: if resolveOnly true,
+/// everything is linked against the first entry.
+/// @param entryFunction if set, missing functions of the module containing the
+/// entry function will be solved.
+/// @return final module or null in this case errorMsg is set
+std::unique_ptr<llvm::Module>
+linkModules(std::vector<std::unique_ptr<llvm::Module>> &modules,
+            llvm::StringRef entryFunction, std::string &errorMsg);
+
+/// Return the Function* target of a Call or Invoke instruction, or
+/// null if it cannot be determined (should be only for indirect
+/// calls, although complicated constant expressions might be
+/// another possibility).
+///
+/// If `moduleIsFullyLinked` is set to true it will be assumed that the
+///  module containing the `llvm::CallSite` is fully linked. This assumption
+///  allows resolution of functions that are marked as overridable.
+llvm::Function *getDirectCallTarget(llvm::CallSite, bool moduleIsFullyLinked);
+
+/// Return true iff the given Function value is used in something
+/// other than a direct call (or a constant expression that
+/// terminates in a direct call).
+bool functionEscapes(const llvm::Function *f);
+
+/// Loads the file libraryName and reads all possible modules out of it.
+///
+/// Different file types are possible:
+/// * .bc binary file
+/// * .ll IR file
+/// * .a archive containing .bc and .ll files
+///
+/// @param libraryName library to read
+/// @param modules contains extracted modules
+/// @param errorMsg contains the error description in case the file could not be
+/// loaded
+/// @return true if successful otherwise false
+bool loadFile(const std::string &libraryName, llvm::LLVMContext &context,
+              std::vector<std::unique_ptr<llvm::Module>> &modules,
+              std::string &errorMsg);
+
+void checkModule(llvm::Module *m);
 }
 
 #endif
diff --git a/include/klee/Interpreter.h b/include/klee/Interpreter.h
index 40f59ff1..4d8a580c 100644
--- a/include/klee/Interpreter.h
+++ b/include/klee/Interpreter.h
@@ -9,10 +9,11 @@
 #ifndef KLEE_INTERPRETER_H
 #define KLEE_INTERPRETER_H
 
-#include <vector>
-#include <string>
 #include <map>
+#include <memory>
 #include <set>
+#include <string>
+#include <vector>
 
 struct KTest;
 
@@ -98,12 +99,13 @@ public:
                              const InterpreterOptions &_interpreterOpts,
                              InterpreterHandler *ih);
 
-  /// Register the module to be executed.  
-  ///
+  /// Register the module to be executed.
+  /// \param modules A list of modules that should form the final
+  ///                module
   /// \return The final module after it has been optimized, checks
   /// inserted, and modified for interpretation.
-  virtual const llvm::Module * 
-  setModule(llvm::Module *module, 
+  virtual llvm::Module *
+  setModule(std::vector<std::unique_ptr<llvm::Module>> &modules,
             const ModuleOptions &opts) = 0;
 
   // supply a tree stream writer which the interpreter will use