klee
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IntrinsicCleaner.cpp
Go to the documentation of this file.
1 //===-- IntrinsicCleaner.cpp ----------------------------------------------===//
2 //
3 // The KLEE Symbolic Virtual Machine
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Passes.h"
11 
12 #include "klee/Config/Version.h"
13 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 3)
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/DerivedTypes.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/InstrTypes.h"
18 #include "llvm/IR/Instruction.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/IR/IntrinsicInst.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/Type.h"
23 #include "llvm/IR/IRBuilder.h"
24 
25 #else
26 #include "llvm/Constants.h"
27 #include "llvm/DerivedTypes.h"
28 #include "llvm/Function.h"
29 #include "llvm/InstrTypes.h"
30 #include "llvm/Instruction.h"
31 #include "llvm/Instructions.h"
32 #include "llvm/IntrinsicInst.h"
33 #include "llvm/LLVMContext.h"
34 #include "llvm/Module.h"
35 #include "llvm/Type.h"
36 #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 2)
37 #include "llvm/IRBuilder.h"
38 #else
39 #include "llvm/Support/IRBuilder.h"
40 #endif
41 #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
42 #include "llvm/Target/TargetData.h"
43 #else
44 #include "llvm/DataLayout.h"
45 #endif
46 #endif
47 #include "llvm/Pass.h"
48 #include "llvm/Transforms/Scalar.h"
49 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
50 
51 using namespace llvm;
52 
53 namespace klee {
54 
55 char IntrinsicCleanerPass::ID;
56 
57 bool IntrinsicCleanerPass::runOnModule(Module &M) {
58  bool dirty = false;
59  for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f)
60  for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b)
61  dirty |= runOnBasicBlock(*b, M);
62  if (Function *Declare = M.getFunction("llvm.trap"))
63  Declare->eraseFromParent();
64  return dirty;
65 }
66 
67 bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b, Module &M) {
68  bool dirty = false;
69 
70 #if LLVM_VERSION_CODE <= LLVM_VERSION(3, 1)
71  unsigned WordSize = TargetData.getPointerSizeInBits() / 8;
72 #else
73  unsigned WordSize = DataLayout.getPointerSizeInBits() / 8;
74 #endif
75  for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie;) {
76  IntrinsicInst *ii = dyn_cast<IntrinsicInst>(&*i);
77  // increment now since LowerIntrinsic deletion makes iterator invalid.
78  ++i;
79  if(ii) {
80  switch (ii->getIntrinsicID()) {
81  case Intrinsic::vastart:
82  case Intrinsic::vaend:
83  break;
84 
85  // Lower vacopy so that object resolution etc is handled by
86  // normal instructions.
87  //
88  // FIXME: This is much more target dependent than just the word size,
89  // however this works for x86-32 and x86-64.
90  case Intrinsic::vacopy: { // (dst, src) -> *((i8**) dst) = *((i8**) src)
91  Value *dst = ii->getArgOperand(0);
92  Value *src = ii->getArgOperand(1);
93 
94  if (WordSize == 4) {
95  Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::getInt8Ty(getGlobalContext())));
96  Value *castedDst = CastInst::CreatePointerCast(dst, i8pp, "vacopy.cast.dst", ii);
97  Value *castedSrc = CastInst::CreatePointerCast(src, i8pp, "vacopy.cast.src", ii);
98  Value *load = new LoadInst(castedSrc, "vacopy.read", ii);
99  new StoreInst(load, castedDst, false, ii);
100  } else {
101  assert(WordSize == 8 && "Invalid word size!");
102  Type *i64p = PointerType::getUnqual(Type::getInt64Ty(getGlobalContext()));
103  Value *pDst = CastInst::CreatePointerCast(dst, i64p, "vacopy.cast.dst", ii);
104  Value *pSrc = CastInst::CreatePointerCast(src, i64p, "vacopy.cast.src", ii);
105  Value *val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii);
106  Value *off = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 1);
107  pDst = GetElementPtrInst::Create(pDst, off, std::string(), ii);
108  pSrc = GetElementPtrInst::Create(pSrc, off, std::string(), ii);
109  val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii);
110  pDst = GetElementPtrInst::Create(pDst, off, std::string(), ii);
111  pSrc = GetElementPtrInst::Create(pSrc, off, std::string(), ii);
112  val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii);
113  }
114  ii->removeFromParent();
115  delete ii;
116  break;
117  }
118 
119  case Intrinsic::uadd_with_overflow:
120  case Intrinsic::umul_with_overflow: {
121  IRBuilder<> builder(ii->getParent(), ii);
122 
123  Value *op1 = ii->getArgOperand(0);
124  Value *op2 = ii->getArgOperand(1);
125 
126  Value *result = 0;
127  if (ii->getIntrinsicID() == Intrinsic::uadd_with_overflow)
128  result = builder.CreateAdd(op1, op2);
129  else
130  result = builder.CreateMul(op1, op2);
131 
132  Value *overflow = builder.CreateICmpULT(result, op1);
133 
134  Value *resultStruct =
135  builder.CreateInsertValue(UndefValue::get(ii->getType()), result, 0);
136  resultStruct = builder.CreateInsertValue(resultStruct, overflow, 1);
137 
138  ii->replaceAllUsesWith(resultStruct);
139  ii->removeFromParent();
140  delete ii;
141  dirty = true;
142  break;
143  }
144 
145  case Intrinsic::dbg_value:
146  case Intrinsic::dbg_declare:
147  // Remove these regardless of lower intrinsics flag. This can
148  // be removed once IntrinsicLowering is fixed to not have bad
149  // caches.
150  ii->eraseFromParent();
151  dirty = true;
152  break;
153 
154  case Intrinsic::trap: {
155  // Intrisic instruction "llvm.trap" found. Directly lower it to
156  // a call of the abort() function.
157  Function *F = cast<Function>(
158  M.getOrInsertFunction(
159  "abort", Type::getVoidTy(getGlobalContext()), NULL));
160  F->setDoesNotReturn();
161  F->setDoesNotThrow();
162 
163  CallInst::Create(F, Twine(), ii);
164  new UnreachableInst(getGlobalContext(), ii);
165 
166  ii->eraseFromParent();
167 
168  dirty = true;
169  break;
170  }
171 
172  default:
173  if (LowerIntrinsics)
174  IL->LowerIntrinsicCall(ii);
175  dirty = true;
176  break;
177  }
178  }
179  }
180 
181  return dirty;
182 }
183 }