about summary refs log tree commit diff homepage
path: root/lib/Module/RaiseAsm.cpp
diff options
context:
space:
mode:
authorMartin Nowack <martin.nowack@gmail.com>2016-08-04 15:43:11 +0200
committerMartin Nowack <martin@se.inf.tu-dresden.de>2016-08-10 21:22:06 +0200
commit95a39e0fe58c7b95588da97b3478eafba9920281 (patch)
treee473ca52e739805533b11b11820c251d0672bbb8 /lib/Module/RaiseAsm.cpp
parent66b3470f4d01df50bc77d9f96e3c526e8e4cbf91 (diff)
downloadklee-95a39e0fe58c7b95588da97b3478eafba9920281.tar.gz
Extended support for assembler raising
Improved support for assembler handling.
Providing additional triple information
to raise assembler for supported architectures
only.

Implemented support for raising full assembly
memory fence.

Added initial support for memory fences in Executor.
Diffstat (limited to 'lib/Module/RaiseAsm.cpp')
-rw-r--r--lib/Module/RaiseAsm.cpp39
1 files changed, 34 insertions, 5 deletions
diff --git a/lib/Module/RaiseAsm.cpp b/lib/Module/RaiseAsm.cpp
index 12e5479b..7c0e6ccf 100644
--- a/lib/Module/RaiseAsm.cpp
+++ b/lib/Module/RaiseAsm.cpp
@@ -9,12 +9,16 @@
 
 #include "Passes.h"
 #include "klee/Config/Version.h"
+#include "klee/Internal/Support/ErrorHandling.h"
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Instructions.h"
 #else
 #include "llvm/InlineAsm.h"
 #include "llvm/LLVMContext.h"
+#include "llvm/Support/IRBuilder.h"
 #endif
 
 #include "llvm/Support/raw_ostream.h"
@@ -46,10 +50,32 @@ Function *RaiseAsmPass::getIntrinsic(llvm::Module &M,
 // FIXME: This should just be implemented as a patch to
 // X86TargetAsmInfo.cpp, then everyone will benefit.
 bool RaiseAsmPass::runOnInstruction(Module &M, Instruction *I) {
-  if (CallInst *ci = dyn_cast<CallInst>(I)) {
-    if (InlineAsm *ia = dyn_cast<InlineAsm>(ci->getCalledValue())) {
-      (void) ia;
-      return TLI && TLI->ExpandInlineAsm(ci);
+  // We can just raise inline assembler using calls
+  CallInst *ci = dyn_cast<CallInst>(I);
+  if (!ci)
+    return false;
+
+  InlineAsm *ia = dyn_cast<InlineAsm>(ci->getCalledValue());
+  if (!ia)
+    return false;
+
+  // Try to use existing infrastructure
+  if (!TLI)
+    return false;
+
+  if (TLI->ExpandInlineAsm(ci))
+    return true;
+
+  if (triple.getArch() == llvm::Triple::x86_64 &&
+      triple.getOS() == llvm::Triple::Linux) {
+
+    if (ia->getAsmString() == "" && ia->hasSideEffects()) {
+#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
+      IRBuilder<> Builder(I);
+      Builder.CreateFence(llvm::SequentiallyConsistent);
+#endif
+      I->eraseFromParent();
+      return true;
     }
   }
 
@@ -66,9 +92,10 @@ bool RaiseAsmPass::runOnModule(Module &M) {
   std::string HostTriple = llvm::sys::getHostTriple();
 #endif
   const Target *NativeTarget = TargetRegistry::lookupTarget(HostTriple, Err);
+
   TargetMachine * TM = 0;
   if (NativeTarget == 0) {
-    llvm::errs() << "Warning: unable to select native target: " << Err << "\n";
+    klee_warning("Warning: unable to select native target: %s", Err.c_str());
     TLI = 0;
   } else {
 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 1)
@@ -80,6 +107,8 @@ bool RaiseAsmPass::runOnModule(Module &M) {
     TM = NativeTarget->createTargetMachine(HostTriple, "");
 #endif
     TLI = TM->getTargetLowering();
+
+    triple = llvm::Triple(HostTriple);
   }
   
   for (Module::iterator fi = M.begin(), fe = M.end(); fi != fe; ++fi) {