//===-- MallocHelper.cpp - Functions to identify malloc calls -------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This family of functions identifies calls to malloc, bitcasts of malloc // calls, and the types and array sizes associated with them. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/MallocHelper.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Module.h" using namespace llvm; //===----------------------------------------------------------------------===// // malloc Call Utility Functions. // /// isMalloc - Returns true if the the value is either a malloc call or a /// bitcast of the result of a malloc call. bool llvm::isMalloc(Value* I) { return extractMallocCall(I) || extractMallocCallFromBitCast(I); } bool llvm::isMalloc(const Value* I) { return extractMallocCall(I) || extractMallocCallFromBitCast(I); } static bool isMallocCall(const CallInst *CI) { if (!CI) return false; const Module* M = CI->getParent()->getParent()->getParent(); Constant *MallocFunc = M->getFunction("malloc"); if (CI->getOperand(0) != MallocFunc) return false; return true; } /// extractMallocCall - Returns the corresponding CallInst if the instruction /// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we /// ignore InvokeInst here. const CallInst* llvm::extractMallocCall(const Value* I) { const CallInst *CI = dyn_cast(I); return (isMallocCall(CI)) ? CI : NULL; } CallInst* llvm::extractMallocCall(Value* I) { CallInst *CI = dyn_cast(I); return (isMallocCall(CI)) ? CI : NULL; } static bool isBitCastOfMallocCall(const BitCastInst* BCI) { if (!BCI) return false; return isMallocCall(dyn_cast(BCI->getOperand(0))); } /// extractMallocCallFromBitCast - Returns the corresponding CallInst if the /// instruction is a bitcast of the result of a malloc call. CallInst* llvm::extractMallocCallFromBitCast(Value* I) { BitCastInst *BCI = dyn_cast(I); return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) : NULL; } const CallInst* llvm::extractMallocCallFromBitCast(const Value* I) { const BitCastInst *BCI = dyn_cast(I); return (isBitCastOfMallocCall(BCI)) ? cast(BCI->getOperand(0)) : NULL; } static bool isArrayMallocHelper(const CallInst *CI) { if (!CI) return false; // Only identify array mallocs for mallocs with 1 bitcast use. The unique // bitcast is needed to determine the type/size of the array allocation. if (!CI->hasOneUse()) return false; for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end(); UI != E; ) if (!isa(cast(*UI++))) return false; // malloc arg Value* MallocArg = CI->getOperand(1); // element size const Type* T = getMallocAllocatedType(CI); if (!T) return false; Constant *ElementSize = ConstantExpr::getSizeOf(T); if (isa(MallocArg)) return (MallocArg == ElementSize) ? false : true; BinaryOperator *BI = dyn_cast(MallocArg); if (!BI) return false; if (BI->getOpcode() != Instruction::Mul) return false; if (BI->getOperand(1) != ElementSize) return false; return true; } /// isArrayMalloc - Returns the corresponding CallInst if the instruction /// matches the malloc call IR generated by CallInst::CreateMalloc(). This /// means that it is a malloc call with one bitcast use AND the malloc call's /// size argument is: /// 1. a constant not equal to the malloc's allocated type /// or /// 2. the result of a multiplication by the malloc's allocated type /// Otherwise it returns NULL. /// The unique bitcast is needed to determine the type/size of the array /// allocation. CallInst* llvm::isArrayMalloc(Value* I) { CallInst *CI = extractMallocCall(I); return (isArrayMallocHelper(CI)) ? CI : NULL; } const CallInst* llvm::isArrayMalloc(const Value* I) { const CallInst *CI = extractMallocCall(I); return (isArrayMallocHelper(CI)) ? CI : NULL; } /// getMallocType - Returns the PointerType resulting from the malloc call. /// This PointerType is the result type of the call's only bitcast use. /// If there is no unique bitcast use, then return NULL. const PointerType* llvm::getMallocType(const CallInst* CI) { assert(isMalloc(CI) && "GetMallocType and not malloc call"); const BitCastInst* BCI = NULL; // Determine type only if there is only 1 bitcast use of CI. if (CI->hasOneUse()) for (Value::use_const_iterator UI = CI->use_begin(), E = CI->use_end(); UI != E; ) BCI = dyn_cast(cast(*UI++)); return BCI ? reinterpret_cast(BCI->getDestTy()) : NULL; } /// getMallocAllocatedType - Returns the Type allocated by malloc call. This /// Type is the result type of the call's only bitcast use. If there is no /// unique bitcast use, then return NULL. const Type* llvm::getMallocAllocatedType(const CallInst* CI) { const PointerType* PT = getMallocType(CI); return PT ? PT->getElementType() : NULL; } /// isConstantOne - Return true only if val is constant int 1. static bool isConstantOne(Value *val) { return isa(val) && cast(val)->isOne(); } /// getMallocArraySize - Returns the array size of a malloc call. The array /// size is computated in 1 of 3 ways: /// 1. If the element type if of size 1, then array size is the argument to /// malloc. /// 2. Else if the malloc's argument is a constant, the array size is that /// argument divided by the element type's size. /// 3. Else the malloc argument must be a multiplication and the array size is /// the first operand of the multiplication. /// This function returns constant 1 if: /// 1. The malloc call's allocated type cannot be determined. /// 2. IR wasn't created by a call to CallInst::CreateMalloc() with a non-NULL /// ArraySize. Value* llvm::getMallocArraySize(CallInst* CI) { // Match CreateMalloc's use of constant 1 array-size for non-array mallocs. if (!isArrayMalloc(CI)) return ConstantInt::get(CI->getOperand(1)->getType(), 1); Value* MallocArg = CI->getOperand(1); assert(getMallocAllocatedType(CI) && "getMallocArraySize and no type"); Constant *ElementSize = ConstantExpr::getSizeOf(getMallocAllocatedType(CI)); ElementSize = ConstantExpr::getTruncOrBitCast(cast(ElementSize), MallocArg->getType()); Constant* CO = dyn_cast(MallocArg); BinaryOperator* BO = dyn_cast(MallocArg); assert((isConstantOne(ElementSize) || CO || BO) && "getMallocArraySize and malformed malloc IR"); if (isConstantOne(ElementSize)) return MallocArg; if (CO) return ConstantExpr::getUDiv(CO, ElementSize); assert(BO && "getMallocArraySize not constant but not multiplication either"); return BO->getOperand(0); }