blob: 5a8a4ea7fc373f575b4321dd2a1507d04a6cf1dc [file] [log] [blame]
//===- convert.h - Promote unsafe alloca instructions to heap allocations ----//
//
// The SAFECode Compiler
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a pass that promotes unsafe stack allocations to heap
// allocations. It also updates the pointer analysis results accordingly.
//
// This pass relies upon the abcpre, abc, and checkstack safety passes.
//
//===----------------------------------------------------------------------===//
#ifndef CONVERT_ALLOCA_H
#define CONVERT_ALLOCA_H
#include "dsa/DataStructure.h"
#include "llvm/Pass.h"
#include "ArrayBoundsCheck.h"
#include "StackSafety.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Target/TargetData.h"
#include "safecode/Config/config.h"
#ifndef LLVA_KERNEL
#include "poolalloc/PoolAllocate.h"
#endif
#include <set>
namespace llvm {
ModulePass *createConvertUnsafeAllocas();
using namespace ABC;
using namespace CSS;
struct MallocPass : public FunctionPass {
private:
// Private data
Constant * memsetF;
DominatorTree * domTree;
// Private methods
inline bool changeType (DSGraph & TDG, Instruction * Inst);
inline bool TypeContainsPointer(const Type *Ty);
public:
static char ID;
MallocPass() : FunctionPass((intptr_t)(&ID)) {}
const char *getPassName() const { return "Malloc Pass"; }
virtual bool runOnFunction (Function &F);
virtual bool doInitialization (Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetData>();
AU.addRequired<TDDataStructures>();
#ifdef LLVA_KERNEL
AU.setPreservesAll();
#else
//AU.setPreservesAll();
#endif
}
};
namespace CUA {
struct ConvertUnsafeAllocas : public ModulePass {
public:
static char ID;
ConvertUnsafeAllocas (intptr_t IDp = (intptr_t) (&ID)) : ModulePass (IDp) {}
const char *getPassName() const { return "Convert Unsafe Allocas"; }
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<ArrayBoundsCheck>();
AU.addRequired<checkStackSafety>();
AU.addRequired<CompleteBUDataStructures>();
AU.addRequired<TDDataStructures>();
AU.addRequired<TargetData>();
AU.addRequired<DominatorTree>();
AU.addRequired<DominanceFrontier>();
AU.addPreserved<ArrayBoundsCheck>();
// Does not preserve the BU or TD graphs
#ifdef LLVA_KERNEL
AU.setPreservesAll();
#endif
}
DSNode * getDSNode(const Value *I, Function *F);
DSNode * getTDDSNode(const Value *I, Function *F);
std::map<BasicBlock*,std::set<Instruction *>*> &
getUnsafeGetElementPtrsFromABC() {
assert(abcPass != 0 && "First run the array bounds pass correctly");
return abcPass->UnsafeGetElemPtrs;
}
std::set<Instruction *> * getUnsafeGetElementPtrsFromABC(BasicBlock * BB) {
assert(abcPass != 0 && "First run the array bounds pass correctly");
return abcPass->getUnsafeGEPs (BB);
}
// The set of Malloc Instructions that are a result of conversion from
// alloca's due to static array bounds detection failure
std::set<const MallocInst *> ArrayMallocs;
protected:
TDDataStructures * tddsPass;
BUDataStructures * budsPass;
ArrayBoundsCheck * abcPass;
checkStackSafety * cssPass;
TargetData *TD;
#ifdef LLVA_KERNEL
Constant *kmalloc;
Constant *StackPromote;
#endif
std::list<DSNode *> unsafeAllocaNodes;
std::set<DSNode *> reachableAllocaNodes;
bool markReachableAllocas(DSNode *DSN);
bool markReachableAllocasInt(DSNode *DSN);
void TransformAllocasToMallocs(std::list<DSNode *> & unsafeAllocaNodes);
void TransformCSSAllocasToMallocs(std::vector<DSNode *> & cssAllocaNodes);
void getUnsafeAllocsFromABC();
void TransformCollapsedAllocas(Module &M);
virtual void InsertFreesAtEnd(MallocInst *MI);
virtual Value * promoteAlloca(AllocaInst * AI, DSNode * Node);
};
//
// Struct: PAConvertUnsafeAllocas
//
// Description:
// This is an LLVM transform pass that is similar to the original
// ConvertUnsafeAllocas pass. However, instead of promoting unsafe stack
// allocations to malloc instructions, it will promote them to use special
// allocation functions within the pool allocator run-time.
//
// Notes:
// o) By using the pool allocator run-time, this pass should generate faster
// code than the original ConvertUnsafeAllocas pass.
// o) This pass requires that a Pool Allocation pass be executed before this
// transform is executed.
//
struct PAConvertUnsafeAllocas : public ConvertUnsafeAllocas {
private:
PoolAllocateGroup * paPass;
protected:
virtual void InsertFreesAtEndNew(Value * PH, Instruction *MI);
virtual Value * promoteAlloca(AllocaInst * AI, DSNode * Node);
public:
static char ID;
PAConvertUnsafeAllocas () : ConvertUnsafeAllocas ((intptr_t)(&ID)) {}
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<ArrayBoundsCheck>();
AU.addRequired<checkStackSafety>();
AU.addRequired<CompleteBUDataStructures>();
AU.addRequired<TDDataStructures>();
AU.addRequired<TargetData>();
AU.addRequired<DominatorTree>();
AU.addRequired<DominanceFrontier>();
AU.addPreserved<ArrayBoundsCheck>();
AU.addPreserved<PoolAllocateGroup>();
// Does not preserve the BU or TD graphs
#ifdef LLVA_KERNEL
AU.setPreservesAll();
#endif
}
};
}
}
#endif