forked from OSchip/llvm-project
Add malloc call utility functions. Patch by Victor Hernandez.
llvm-svn: 81426
This commit is contained in:
parent
2ffe029a61
commit
1d9d4bdc99
|
@ -0,0 +1,86 @@
|
||||||
|
//===- llvm/Analysis/MallocHelper.h ---- Identify malloc calls --*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef LLVM_ANALYSIS_MALLOCHELPER_H
|
||||||
|
#define LLVM_ANALYSIS_MALLOCHELPER_H
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class BitCastInst;
|
||||||
|
class CallInst;
|
||||||
|
class Instruction;
|
||||||
|
class PointerType;
|
||||||
|
class Twine;
|
||||||
|
class Type;
|
||||||
|
class Value;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// 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 isMalloc(const Value* I);
|
||||||
|
bool isMalloc(Value* I);
|
||||||
|
|
||||||
|
/// extractMallocCall - Returns the corresponding CallInst if the instruction
|
||||||
|
/// is a malloc call. Since CallInst::CreateMalloc() only creates calls, we
|
||||||
|
/// ignore InvokeInst here.
|
||||||
|
const CallInst* extractMallocCall(const Value* I);
|
||||||
|
CallInst* extractMallocCall(Value* I);
|
||||||
|
|
||||||
|
/// extractMallocCallFromBitCast - Returns the corresponding CallInst if the
|
||||||
|
/// instruction is a bitcast of the result of a malloc call.
|
||||||
|
const CallInst* extractMallocCallFromBitCast(const Value* I);
|
||||||
|
CallInst* extractMallocCallFromBitCast(Value* I);
|
||||||
|
|
||||||
|
/// 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* isArrayMalloc(Value* I);
|
||||||
|
const CallInst* isArrayMalloc(const Value* I);
|
||||||
|
|
||||||
|
/// 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* getMallocType(const CallInst* CI);
|
||||||
|
|
||||||
|
/// 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* getMallocAllocatedType(const CallInst* CI);
|
||||||
|
|
||||||
|
/// 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* getMallocArraySize(CallInst* CI);
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
|
@ -1033,6 +1033,18 @@ public:
|
||||||
BasicBlock *InsertAtEnd) {
|
BasicBlock *InsertAtEnd) {
|
||||||
return new(1) CallInst(F, NameStr, InsertAtEnd);
|
return new(1) CallInst(F, NameStr, InsertAtEnd);
|
||||||
}
|
}
|
||||||
|
/// CreateMalloc - Generate the IR for a call to malloc:
|
||||||
|
/// 1. Compute the malloc call's argument as the specified type's size,
|
||||||
|
/// possibly multiplied by the array size if the array size is not
|
||||||
|
/// constant 1.
|
||||||
|
/// 2. Call malloc with that argument.
|
||||||
|
/// 3. Bitcast the result of the malloc call to the specified type.
|
||||||
|
static Value *CreateMalloc(Instruction *I,
|
||||||
|
const Type *AllocTy, const Type *IntPtrTy,
|
||||||
|
Value *ArraySize = 0, const Twine &NameStr = "");
|
||||||
|
static Value *CreateMalloc(BasicBlock *InsertAtEnd,
|
||||||
|
const Type *AllocTy, const Type *IntPtrTy,
|
||||||
|
Value *ArraySize = 0, const Twine &NameStr = "");
|
||||||
|
|
||||||
~CallInst();
|
~CallInst();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
//===-- 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<CallInst>(I);
|
||||||
|
return (isMallocCall(CI)) ? CI : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallInst* llvm::extractMallocCall(Value* I) {
|
||||||
|
CallInst *CI = dyn_cast<CallInst>(I);
|
||||||
|
return (isMallocCall(CI)) ? CI : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isBitCastOfMallocCall(const BitCastInst* BCI) {
|
||||||
|
if (!BCI)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return isMallocCall(dyn_cast<CallInst>(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<BitCastInst>(I);
|
||||||
|
return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(BCI->getOperand(0)) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CallInst* llvm::extractMallocCallFromBitCast(const Value* I) {
|
||||||
|
const BitCastInst *BCI = dyn_cast<BitCastInst>(I);
|
||||||
|
return (isBitCastOfMallocCall(BCI)) ? cast<CallInst>(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<BitCastInst>(cast<Instruction>(*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<ConstantExpr>(MallocArg))
|
||||||
|
return (MallocArg == ElementSize) ? false : true;
|
||||||
|
|
||||||
|
BinaryOperator *BI = dyn_cast<BinaryOperator>(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<BitCastInst>(cast<Instruction>(*UI++));
|
||||||
|
|
||||||
|
return BCI ? reinterpret_cast<const PointerType*>(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<ConstantInt>(val) && cast<ConstantInt>(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<Constant>(ElementSize),
|
||||||
|
MallocArg->getType());
|
||||||
|
|
||||||
|
Constant* CO = dyn_cast<Constant>(MallocArg);
|
||||||
|
BinaryOperator* BO = dyn_cast<BinaryOperator>(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);
|
||||||
|
}
|
|
@ -33,13 +33,13 @@ namespace {
|
||||||
/// @free calls.
|
/// @free calls.
|
||||||
///
|
///
|
||||||
class VISIBILITY_HIDDEN LowerAllocations : public BasicBlockPass {
|
class VISIBILITY_HIDDEN LowerAllocations : public BasicBlockPass {
|
||||||
Constant *MallocFunc; // Functions in the module we are processing
|
Constant *FreeFunc; // Functions in the module we are processing
|
||||||
Constant *FreeFunc; // Initialized by doInitialization
|
// Initialized by doInitialization
|
||||||
bool LowerMallocArgToInteger;
|
bool LowerMallocArgToInteger;
|
||||||
public:
|
public:
|
||||||
static char ID; // Pass ID, replacement for typeid
|
static char ID; // Pass ID, replacement for typeid
|
||||||
explicit LowerAllocations(bool LowerToInt = false)
|
explicit LowerAllocations(bool LowerToInt = false)
|
||||||
: BasicBlockPass(&ID), MallocFunc(0), FreeFunc(0),
|
: BasicBlockPass(&ID), FreeFunc(0),
|
||||||
LowerMallocArgToInteger(LowerToInt) {}
|
LowerMallocArgToInteger(LowerToInt) {}
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
|
@ -88,10 +88,6 @@ Pass *llvm::createLowerAllocationsPass(bool LowerMallocArgToInteger) {
|
||||||
//
|
//
|
||||||
bool LowerAllocations::doInitialization(Module &M) {
|
bool LowerAllocations::doInitialization(Module &M) {
|
||||||
const Type *BPTy = PointerType::getUnqual(Type::getInt8Ty(M.getContext()));
|
const Type *BPTy = PointerType::getUnqual(Type::getInt8Ty(M.getContext()));
|
||||||
// Prototype malloc as "char* malloc(...)", because we don't know in
|
|
||||||
// doInitialization whether size_t is int or long.
|
|
||||||
FunctionType *FT = FunctionType::get(BPTy, true);
|
|
||||||
MallocFunc = M.getOrInsertFunction("malloc", FT);
|
|
||||||
FreeFunc = M.getOrInsertFunction("free" , Type::getVoidTy(M.getContext()),
|
FreeFunc = M.getOrInsertFunction("free" , Type::getVoidTy(M.getContext()),
|
||||||
BPTy, (Type *)0);
|
BPTy, (Type *)0);
|
||||||
return true;
|
return true;
|
||||||
|
@ -102,7 +98,7 @@ bool LowerAllocations::doInitialization(Module &M) {
|
||||||
//
|
//
|
||||||
bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
assert(MallocFunc && FreeFunc && "Pass not initialized!");
|
assert(FreeFunc && "Pass not initialized!");
|
||||||
|
|
||||||
BasicBlock::InstListType &BBIL = BB.getInstList();
|
BasicBlock::InstListType &BBIL = BB.getInstList();
|
||||||
|
|
||||||
|
@ -112,50 +108,8 @@ bool LowerAllocations::runOnBasicBlock(BasicBlock &BB) {
|
||||||
// Loop over all of the instructions, looking for malloc or free instructions
|
// Loop over all of the instructions, looking for malloc or free instructions
|
||||||
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
|
for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) {
|
||||||
if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
|
if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
|
||||||
const Type *AllocTy = MI->getType()->getElementType();
|
Value *MCast = CallInst::CreateMalloc(I, MI->getType(), IntPtrTy,
|
||||||
|
MI->getOperand(0));
|
||||||
// malloc(type) becomes i8 *malloc(size)
|
|
||||||
Value *MallocArg;
|
|
||||||
if (LowerMallocArgToInteger)
|
|
||||||
MallocArg = ConstantInt::get(Type::getInt64Ty(BB.getContext()),
|
|
||||||
TD.getTypeAllocSize(AllocTy));
|
|
||||||
else
|
|
||||||
MallocArg = ConstantExpr::getSizeOf(AllocTy);
|
|
||||||
MallocArg =
|
|
||||||
ConstantExpr::getTruncOrBitCast(cast<Constant>(MallocArg),
|
|
||||||
IntPtrTy);
|
|
||||||
|
|
||||||
if (MI->isArrayAllocation()) {
|
|
||||||
if (isa<ConstantInt>(MallocArg) &&
|
|
||||||
cast<ConstantInt>(MallocArg)->isOne()) {
|
|
||||||
MallocArg = MI->getOperand(0); // Operand * 1 = Operand
|
|
||||||
} else if (Constant *CO = dyn_cast<Constant>(MI->getOperand(0))) {
|
|
||||||
CO =
|
|
||||||
ConstantExpr::getIntegerCast(CO, IntPtrTy, false /*ZExt*/);
|
|
||||||
MallocArg = ConstantExpr::getMul(CO,
|
|
||||||
cast<Constant>(MallocArg));
|
|
||||||
} else {
|
|
||||||
Value *Scale = MI->getOperand(0);
|
|
||||||
if (Scale->getType() != IntPtrTy)
|
|
||||||
Scale = CastInst::CreateIntegerCast(Scale, IntPtrTy, false /*ZExt*/,
|
|
||||||
"", I);
|
|
||||||
|
|
||||||
// Multiply it by the array size if necessary...
|
|
||||||
MallocArg = BinaryOperator::Create(Instruction::Mul, Scale,
|
|
||||||
MallocArg, "", I);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the call to Malloc.
|
|
||||||
CallInst *MCall = CallInst::Create(MallocFunc, MallocArg, "", I);
|
|
||||||
MCall->setTailCall();
|
|
||||||
|
|
||||||
// Create a cast instruction to convert to the right type...
|
|
||||||
Value *MCast;
|
|
||||||
if (MCall->getType() != Type::getVoidTy(BB.getContext()))
|
|
||||||
MCast = new BitCastInst(MCall, MI->getType(), "", I);
|
|
||||||
else
|
|
||||||
MCast = Constant::getNullValue(MI->getType());
|
|
||||||
|
|
||||||
// Replace all uses of the old malloc inst with the cast inst
|
// Replace all uses of the old malloc inst with the cast inst
|
||||||
MI->replaceAllUsesWith(MCast);
|
MI->replaceAllUsesWith(MCast);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Instructions.h"
|
#include "llvm/Instructions.h"
|
||||||
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Operator.h"
|
#include "llvm/Operator.h"
|
||||||
#include "llvm/Analysis/Dominators.h"
|
#include "llvm/Analysis/Dominators.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
|
@ -440,6 +441,116 @@ bool CallInst::paramHasAttr(unsigned i, Attributes attr) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// IsConstantOne - Return true only if val is constant int 1
|
||||||
|
static bool IsConstantOne(Value *val) {
|
||||||
|
assert(val && "IsConstantOne does not work with NULL val");
|
||||||
|
return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Value *checkArraySize(Value *Amt, const Type *IntPtrTy) {
|
||||||
|
if (!Amt)
|
||||||
|
Amt = ConstantInt::get(IntPtrTy, 1);
|
||||||
|
else {
|
||||||
|
assert(!isa<BasicBlock>(Amt) &&
|
||||||
|
"Passed basic block into malloc size parameter! Use other ctor");
|
||||||
|
assert(Amt->getType() == IntPtrTy &&
|
||||||
|
"Malloc array size is not an intptr!");
|
||||||
|
}
|
||||||
|
return Amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Value *createMalloc(Instruction *InsertBefore, BasicBlock *InsertAtEnd,
|
||||||
|
const Type *AllocTy, const Type *IntPtrTy,
|
||||||
|
Value *ArraySize, const Twine &NameStr) {
|
||||||
|
assert((!InsertBefore && InsertAtEnd || InsertBefore && !InsertAtEnd) &&
|
||||||
|
"createMalloc needs only InsertBefore or InsertAtEnd");
|
||||||
|
const PointerType *AllocPtrType = dyn_cast<PointerType>(AllocTy);
|
||||||
|
assert(AllocPtrType && "CreateMalloc passed a non-pointer allocation type");
|
||||||
|
|
||||||
|
ArraySize = checkArraySize(ArraySize, IntPtrTy);
|
||||||
|
|
||||||
|
// malloc(type) becomes i8 *malloc(size)
|
||||||
|
Value *AllocSize = ConstantExpr::getSizeOf(AllocPtrType->getElementType());
|
||||||
|
AllocSize = ConstantExpr::getTruncOrBitCast(cast<Constant>(AllocSize),
|
||||||
|
IntPtrTy);
|
||||||
|
if (!IsConstantOne(ArraySize))
|
||||||
|
if (IsConstantOne(AllocSize)) {
|
||||||
|
AllocSize = ArraySize; // Operand * 1 = Operand
|
||||||
|
} else if (Constant *CO = dyn_cast<Constant>(ArraySize)) {
|
||||||
|
Constant *Scale = ConstantExpr::getIntegerCast(CO, IntPtrTy,
|
||||||
|
false /*ZExt*/);
|
||||||
|
// Malloc arg is constant product of type size and array size
|
||||||
|
AllocSize = ConstantExpr::getMul(Scale, cast<Constant>(AllocSize));
|
||||||
|
} else {
|
||||||
|
Value *Scale = ArraySize;
|
||||||
|
if (Scale->getType() != IntPtrTy)
|
||||||
|
if (InsertBefore)
|
||||||
|
Scale = CastInst::CreateIntegerCast(Scale, IntPtrTy, false /*ZExt*/,
|
||||||
|
"", InsertBefore);
|
||||||
|
else
|
||||||
|
Scale = CastInst::CreateIntegerCast(Scale, IntPtrTy, false /*ZExt*/,
|
||||||
|
"", InsertAtEnd);
|
||||||
|
// Multiply type size by the array size...
|
||||||
|
if (InsertBefore)
|
||||||
|
AllocSize = BinaryOperator::CreateMul(Scale, AllocSize,
|
||||||
|
"", InsertBefore);
|
||||||
|
else
|
||||||
|
AllocSize = BinaryOperator::CreateMul(Scale, AllocSize,
|
||||||
|
"", InsertAtEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the call to Malloc.
|
||||||
|
BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
|
||||||
|
Module* M = BB->getParent()->getParent();
|
||||||
|
const Type *BPTy = PointerType::getUnqual(Type::getInt8Ty(BB->getContext()));
|
||||||
|
// prototype malloc as "void *malloc(size_t)"
|
||||||
|
Constant *MallocFunc = M->getOrInsertFunction("malloc", BPTy,
|
||||||
|
IntPtrTy, NULL);
|
||||||
|
CallInst *MCall = NULL;
|
||||||
|
if (InsertBefore)
|
||||||
|
MCall = CallInst::Create(MallocFunc, AllocSize, NameStr, InsertBefore);
|
||||||
|
else
|
||||||
|
MCall = CallInst::Create(MallocFunc, AllocSize, NameStr, InsertAtEnd);
|
||||||
|
MCall->setTailCall();
|
||||||
|
|
||||||
|
// Create a cast instruction to convert to the right type...
|
||||||
|
const Type* VoidT = Type::getVoidTy(BB->getContext());
|
||||||
|
assert(MCall->getType() != VoidT && "Malloc has void return type");
|
||||||
|
Value *MCast;
|
||||||
|
if (InsertBefore)
|
||||||
|
MCast = new BitCastInst(MCall, AllocPtrType, NameStr, InsertBefore);
|
||||||
|
else
|
||||||
|
MCast = new BitCastInst(MCall, AllocPtrType, NameStr);
|
||||||
|
return MCast;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CreateMalloc - Generate the IR for a call to malloc:
|
||||||
|
/// 1. Compute the malloc call's argument as the specified type's size,
|
||||||
|
/// possibly multiplied by the array size if the array size is not
|
||||||
|
/// constant 1.
|
||||||
|
/// 2. Call malloc with that argument.
|
||||||
|
/// 3. Bitcast the result of the malloc call to the specified type.
|
||||||
|
Value *CallInst::CreateMalloc(Instruction *InsertBefore,
|
||||||
|
const Type *AllocTy, const Type *IntPtrTy,
|
||||||
|
Value *ArraySize, const Twine &NameStr) {
|
||||||
|
return createMalloc(InsertBefore, NULL, AllocTy,
|
||||||
|
IntPtrTy, ArraySize, NameStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CreateMalloc - Generate the IR for a call to malloc:
|
||||||
|
/// 1. Compute the malloc call's argument as the specified type's size,
|
||||||
|
/// possibly multiplied by the array size if the array size is not
|
||||||
|
/// constant 1.
|
||||||
|
/// 2. Call malloc with that argument.
|
||||||
|
/// 3. Bitcast the result of the malloc call to the specified type.
|
||||||
|
/// Note: This function does not add the bitcast to the basic block, that is the
|
||||||
|
/// responsibility of the caller.
|
||||||
|
Value *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
|
||||||
|
const Type *AllocTy, const Type *IntPtrTy,
|
||||||
|
Value *ArraySize, const Twine &NameStr) {
|
||||||
|
return createMalloc(NULL, InsertAtEnd, AllocTy,
|
||||||
|
IntPtrTy, ArraySize, NameStr);
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// InvokeInst Implementation
|
// InvokeInst Implementation
|
||||||
|
|
Loading…
Reference in New Issue