about summary refs log tree commit diff homepage
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
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.
-rw-r--r--lib/Core/Executor.cpp12
-rw-r--r--lib/Module/Passes.h5
-rw-r--r--lib/Module/RaiseAsm.cpp39
-rw-r--r--test/Feature/RaiseAsm.c2
4 files changed, 49 insertions, 9 deletions
diff --git a/lib/Core/Executor.cpp b/lib/Core/Executor.cpp
index d755403f..8b885527 100644
--- a/lib/Core/Executor.cpp
+++ b/lib/Core/Executor.cpp
@@ -2543,9 +2543,15 @@ void Executor::executeInstruction(ExecutionState &state, KInstruction *ki) {
     bindLocal(ki, state, result);
     break;
   }
- 
-    // Other instructions...
-    // Unhandled
+#if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
+  case Instruction::Fence: {
+    // Ignore for now
+    break;
+  }
+#endif
+
+  // Other instructions...
+  // Unhandled
   case Instruction::ExtractElement:
   case Instruction::InsertElement:
   case Instruction::ShuffleVector:
diff --git a/lib/Module/Passes.h b/lib/Module/Passes.h
index accb64d0..4f1a1453 100644
--- a/lib/Module/Passes.h
+++ b/lib/Module/Passes.h
@@ -21,8 +21,9 @@
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
 #endif
-#include "llvm/Pass.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/Pass.h"
 
 namespace llvm {
   class Function;
@@ -46,6 +47,8 @@ class RaiseAsmPass : public llvm::ModulePass {
 
   const llvm::TargetLowering *TLI;
 
+  llvm::Triple triple;
+
   llvm::Function *getIntrinsic(llvm::Module &M,
                                unsigned IID,
                                LLVM_TYPE_Q llvm::Type **Tys,
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) {
diff --git a/test/Feature/RaiseAsm.c b/test/Feature/RaiseAsm.c
index 6a4b7b3c..f8ba173a 100644
--- a/test/Feature/RaiseAsm.c
+++ b/test/Feature/RaiseAsm.c
@@ -36,5 +36,7 @@ int main() {
   assert(ui16 == byteswap_uint16(byteswap_uint16_asm(ui16)));
   assert(ui32 == byteswap_uint32(byteswap_uint32_asm(ui32)));
 
+  __asm__ __volatile__("" : : : "memory");
+
   return 0;
 }