14#include "llvm/Analysis/MemoryBuiltins.h"
15#include "llvm/Analysis/ConstantFolding.h"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/DerivedTypes.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/InstrTypes.h"
21#include "llvm/IR/Instruction.h"
22#include "llvm/IR/Instructions.h"
23#include "llvm/IR/IntrinsicInst.h"
24#if LLVM_VERSION_CODE >= LLVM_VERSION(10, 0)
25#include "llvm/IR/IntrinsicsX86.h"
27#include "llvm/IR/Module.h"
28#include "llvm/IR/Type.h"
30#include "llvm/Transforms/Scalar.h"
31#include "llvm/Transforms/Utils/BasicBlockUtils.h"
41 for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f)
42 for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b)
45 if (Function *Declare = M.getFunction(
"llvm.trap")) {
46 Declare->eraseFromParent();
54 LLVMContext &ctx = M.getContext();
56 unsigned WordSize =
DataLayout.getPointerSizeInBits() / 8;
57 for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie;) {
58 IntrinsicInst *ii = dyn_cast<IntrinsicInst>(&*i);
62 if (isa<DbgInfoIntrinsic>(ii))
65 switch (ii->getIntrinsicID()) {
66 case Intrinsic::vastart:
67 case Intrinsic::vaend:
69#if LLVM_VERSION_CODE >= LLVM_VERSION(7, 0)
73#if LLVM_VERSION_CODE >= LLVM_VERSION(12, 0)
87 case Intrinsic::vacopy: {
88 llvm::IRBuilder<> Builder(ii);
89 Value *dst = ii->getArgOperand(0);
90 Value *src = ii->getArgOperand(1);
93 Type *i8pp = PointerType::getUnqual(
94 PointerType::getUnqual(Type::getInt8Ty(ctx)));
96 Builder.CreatePointerCast(dst, i8pp,
"vacopy.cast.dst");
98 Builder.CreatePointerCast(src, i8pp,
"vacopy.cast.src");
100 Builder.CreateLoad(castedSrc->getType()->getPointerElementType(),
101 castedSrc,
"vacopy.read");
102 Builder.CreateStore(load, castedDst,
false );
104 assert(WordSize == 8 &&
"Invalid word size!");
105 Type *i64p = PointerType::getUnqual(Type::getInt64Ty(ctx));
106 auto pDst = Builder.CreatePointerCast(dst, i64p,
"vacopy.cast.dst");
107 auto pSrc = Builder.CreatePointerCast(src, i64p,
"vacopy.cast.src");
109 auto pSrcType = pSrc->getType()->getPointerElementType();
110 auto pDstType = pDst->getType()->getPointerElementType();
112 auto val = Builder.CreateLoad(pSrcType, pSrc);
113 Builder.CreateStore(val, pDst, ii);
115 auto off = ConstantInt::get(Type::getInt64Ty(ctx), 1);
116 pDst = Builder.CreateGEP(pDstType, pDst, off);
117 pSrc = Builder.CreateGEP(pSrcType, pSrc, off);
118 val = Builder.CreateLoad(pSrcType, pSrc);
119 Builder.CreateStore(val, pDst);
120 pDst = Builder.CreateGEP(pDstType, pDst, off);
121 pSrc = Builder.CreateGEP(pSrcType, pSrc, off);
122 val = Builder.CreateLoad(pSrcType, pSrc);
123 Builder.CreateStore(val, pDst);
125 ii->eraseFromParent();
130 case Intrinsic::sadd_with_overflow:
131 case Intrinsic::ssub_with_overflow:
132 case Intrinsic::smul_with_overflow:
133 case Intrinsic::uadd_with_overflow:
134 case Intrinsic::usub_with_overflow:
135 case Intrinsic::umul_with_overflow: {
136 IRBuilder<> builder(ii->getParent(), ii->getIterator());
138 Value *op1 = ii->getArgOperand(0);
139 Value *op2 = ii->getArgOperand(1);
142 Value *result_ext = 0;
145 unsigned int bw = op1->getType()->getPrimitiveSizeInBits();
146 unsigned int bw2 = op1->getType()->getPrimitiveSizeInBits() * 2;
148 if ((ii->getIntrinsicID() == Intrinsic::uadd_with_overflow) ||
149 (ii->getIntrinsicID() == Intrinsic::usub_with_overflow) ||
150 (ii->getIntrinsicID() == Intrinsic::umul_with_overflow)) {
153 builder.CreateZExt(op1, IntegerType::get(M.getContext(), bw2));
155 builder.CreateZExt(op2, IntegerType::get(M.getContext(), bw2));
157 ConstantInt::get(op1->getType(), APInt::getMaxValue(bw));
158 Value *int_max = builder.CreateZExt(
159 int_max_s, IntegerType::get(M.getContext(), bw2));
161 if (ii->getIntrinsicID() == Intrinsic::uadd_with_overflow) {
162 result_ext = builder.CreateAdd(op1ext, op2ext);
163 }
else if (ii->getIntrinsicID() == Intrinsic::usub_with_overflow) {
164 result_ext = builder.CreateSub(op1ext, op2ext);
165 }
else if (ii->getIntrinsicID() == Intrinsic::umul_with_overflow) {
166 result_ext = builder.CreateMul(op1ext, op2ext);
168 overflow = builder.CreateICmpUGT(result_ext, int_max);
170 }
else if ((ii->getIntrinsicID() == Intrinsic::sadd_with_overflow) ||
171 (ii->getIntrinsicID() == Intrinsic::ssub_with_overflow) ||
172 (ii->getIntrinsicID() == Intrinsic::smul_with_overflow)) {
175 builder.CreateSExt(op1, IntegerType::get(M.getContext(), bw2));
177 builder.CreateSExt(op2, IntegerType::get(M.getContext(), bw2));
179 ConstantInt::get(op1->getType(), APInt::getSignedMaxValue(bw));
181 ConstantInt::get(op1->getType(), APInt::getSignedMinValue(bw));
182 Value *int_max = builder.CreateSExt(
183 int_max_s, IntegerType::get(M.getContext(), bw2));
184 Value *int_min = builder.CreateSExt(
185 int_min_s, IntegerType::get(M.getContext(), bw2));
187 if (ii->getIntrinsicID() == Intrinsic::sadd_with_overflow) {
188 result_ext = builder.CreateAdd(op1ext, op2ext);
189 }
else if (ii->getIntrinsicID() == Intrinsic::ssub_with_overflow) {
190 result_ext = builder.CreateSub(op1ext, op2ext);
191 }
else if (ii->getIntrinsicID() == Intrinsic::smul_with_overflow) {
192 result_ext = builder.CreateMul(op1ext, op2ext);
195 builder.CreateOr(builder.CreateICmpSGT(result_ext, int_max),
196 builder.CreateICmpSLT(result_ext, int_min));
207 result = builder.CreateTrunc(result_ext, op1->getType());
208 Value *resultStruct = builder.CreateInsertValue(
209 UndefValue::get(ii->getType()), result, 0);
210 resultStruct = builder.CreateInsertValue(resultStruct, overflow, 1);
212 ii->replaceAllUsesWith(resultStruct);
213 ii->eraseFromParent();
217#if LLVM_VERSION_CODE >= LLVM_VERSION(8, 0)
218 case Intrinsic::sadd_sat:
219 case Intrinsic::ssub_sat:
220 case Intrinsic::uadd_sat:
221 case Intrinsic::usub_sat: {
222 IRBuilder<> builder(ii);
224 Value *op1 = ii->getArgOperand(0);
225 Value *op2 = ii->getArgOperand(1);
227 unsigned int bw = op1->getType()->getPrimitiveSizeInBits();
228 assert(bw == op2->getType()->getPrimitiveSizeInBits());
230 Value *overflow =
nullptr;
231 Value *result =
nullptr;
232 Value *saturated =
nullptr;
233 switch(ii->getIntrinsicID()) {
234 case Intrinsic::usub_sat:
235 result = builder.CreateSub(op1, op2);
236 overflow = builder.CreateICmpULT(op1, op2);
237 saturated = ConstantInt::get(ctx, APInt(bw, 0));
239 case Intrinsic::uadd_sat:
240 result = builder.CreateAdd(op1, op2);
241 overflow = builder.CreateICmpULT(result, op1);
242 saturated = ConstantInt::get(ctx, APInt::getMaxValue(bw));
244 case Intrinsic::ssub_sat:
245 case Intrinsic::sadd_sat: {
246 if (ii->getIntrinsicID() == Intrinsic::ssub_sat) {
247 result = builder.CreateSub(op1, op2);
249 result = builder.CreateAdd(op1, op2);
251 ConstantInt *zero = ConstantInt::get(ctx, APInt(bw, 0));
252 ConstantInt *smin = ConstantInt::get(ctx, APInt::getSignedMinValue(bw));
253 ConstantInt *smax = ConstantInt::get(ctx, APInt::getSignedMaxValue(bw));
255 Value *sign1 = builder.CreateICmpSLT(op1, zero);
256 Value *sign2 = builder.CreateICmpSLT(op2, zero);
257 Value *signR = builder.CreateICmpSLT(result, zero);
259 if (ii->getIntrinsicID() == Intrinsic::ssub_sat) {
260 saturated = builder.CreateSelect(sign2, smax, smin);
262 saturated = builder.CreateSelect(sign2, smin, smax);
266 overflow = builder.CreateXor(sign1, signR);
267 if (ii->getIntrinsicID() == Intrinsic::ssub_sat) {
269 overflow = builder.CreateAnd(overflow, builder.CreateXor(sign1, sign2));
272 overflow = builder.CreateAnd(overflow, builder.CreateNot(builder.CreateXor(sign1, sign2)));
279 result = builder.CreateSelect(overflow, saturated, result);
280 ii->replaceAllUsesWith(result);
281 ii->eraseFromParent();
287 case Intrinsic::trap: {
290 auto C = M.getOrInsertFunction(
"abort", Type::getVoidTy(ctx));
291#if LLVM_VERSION_CODE >= LLVM_VERSION(9, 0)
292 if (
auto *F = dyn_cast<Function>(C.getCallee())) {
294 if (
auto *F = dyn_cast<Function>(C)) {
296 F->setDoesNotReturn();
297 F->setDoesNotThrow();
300 llvm::IRBuilder<> Builder(ii);
301 Builder.CreateCall(C);
302 Builder.CreateUnreachable();
304 i = ii->eraseFromParent();
312 i = i->eraseFromParent();
318 case Intrinsic::objectsize: {
320 auto replacement = llvm::lowerObjectSizeCall(ii,
DataLayout,
nullptr,
322 ii->replaceAllUsesWith(replacement);
323 ii->eraseFromParent();
327#if LLVM_VERSION_CODE >= LLVM_VERSION(8, 0)
328 case Intrinsic::is_constant: {
329 if(
auto* constant = llvm::ConstantFoldInstruction(ii, ii->getModule()->getDataLayout()))
330 ii->replaceAllUsesWith(constant);
332 ii->replaceAllUsesWith(ConstantInt::getFalse(ii->getType()));
333 ii->eraseFromParent();
342 case Intrinsic::addressofreturnaddress:
343 case Intrinsic::annotation:
344 case Intrinsic::assume:
345 case Intrinsic::bswap:
346 case Intrinsic::ceil:
347 case Intrinsic::copysign:
349 case Intrinsic::ctlz:
350 case Intrinsic::ctpop:
351 case Intrinsic::cttz:
352 case Intrinsic::dbg_declare:
353#if LLVM_VERSION_CODE >= LLVM_VERSION(7, 0)
354 case Intrinsic::dbg_label:
356#ifndef SUPPORT_KLEE_EH_CXX
357 case Intrinsic::eh_typeid_for:
359 case Intrinsic::exp2:
361 case Intrinsic::expect:
362 case Intrinsic::floor:
363 case Intrinsic::flt_rounds:
364 case Intrinsic::frameaddress:
365 case Intrinsic::get_dynamic_area_offset:
366 case Intrinsic::invariant_end:
367 case Intrinsic::invariant_start:
368 case Intrinsic::lifetime_end:
369 case Intrinsic::lifetime_start:
370 case Intrinsic::log10:
371 case Intrinsic::log2:
373 case Intrinsic::memcpy:
374 case Intrinsic::memmove:
375 case Intrinsic::memset:
376 case Intrinsic::not_intrinsic:
377 case Intrinsic::pcmarker:
379 case Intrinsic::prefetch:
380 case Intrinsic::ptr_annotation:
381 case Intrinsic::readcyclecounter:
382 case Intrinsic::returnaddress:
383 case Intrinsic::round:
384#if LLVM_VERSION_CODE >= LLVM_VERSION(11, 0)
385 case Intrinsic::roundeven:
388 case Intrinsic::sqrt:
389 case Intrinsic::stackrestore:
390 case Intrinsic::stacksave:
392 case Intrinsic::var_annotation:
393 IL->LowerIntrinsicCall(ii);
397#ifdef SUPPORT_KLEE_EH_CXX
398 case Intrinsic::eh_typeid_for: {
406 const Function *Callee = ii->getCalledFunction();
407 llvm::StringRef name = Callee->getName();
408 klee_warning_once((
void*)Callee,
"unsupported intrinsic %.*s", (
int)name.size(), name.data());
bool runOnModule(llvm::Module &M) override
const llvm::DataLayout & DataLayout
bool runOnBasicBlock(llvm::BasicBlock &b, llvm::Module &M)
llvm::IntrinsicLowering * IL
uint64_t trunc(uint64_t l, unsigned outWidth, unsigned inWidth)
void void void void klee_warning_once(const void *id, const char *msg,...) __attribute__((format(printf