Skip to content

Commit

Permalink
PromoteArrayAllocas pass, to transform array allocas to malloc / free.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhengyang92 committed Jun 20, 2016
1 parent ca1c707 commit a6746c5
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 0 deletions.
75 changes: 75 additions & 0 deletions projects/safecode/include/safecode/PromoteArrayAllocas.h
@@ -0,0 +1,75 @@
//===- PromoteArrayAlloca.h - Promote array alloca instructions to malloc ----//
//
// 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 array alloca instuction to malloc
// allocations.
//
//===----------------------------------------------------------------------===//


#ifndef PROMOTE_ARRAY_ALLOCA_H
#define PROMOTE_ARRAY_ALLOCA_H


#include "safecode/Config/config.h"
#include "safecode/SAFECode.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Pass.h"
#include <set>

namespace llvm {

//ModulePass *promoteArrayAllocas();

//
// Pass: PromoteArrayAllocas
//
// Description:
// This pass promotes array allocations to malloc allocations if necessary to
// provide bbac runtime check support.
//

class PromoteArrayAllocas : public ModulePass,
public InstVisitor<PromoteArrayAllocas> {
public:
static char ID;
PromoteArrayAllocas () : ModulePass (ID) {}
const char *getPassName() const { return "Promote Array Allocas";}
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<DominanceFrontier>();
AU.addRequired<DominatorTreeWrapperPass>();
};

// The set of Malloc Instructions that are a result of conversion from
// alloca's due to static array bounds detection failure
std::set<const Instruction *> ArrayMallocs;

void visitAllocaInst(AllocaInst &A);
protected:
Constant *malloc;
Constant *free;
void createProtos(Module & M);
Instruction * transformArrayAlloca (AllocaInst & A);
bool insertFreeForAllocaInEntryBlock(AllocaInst & A, Instruction * MallocInst);
bool insertFreeForAllocaOutOfEntryBlock(AllocaInst &A, Instruction * MallocInst);
const DataLayout * TD;

Type * VoidType;
Type * Int32Type;
};

} //end namespace llvm
#endif
191 changes: 191 additions & 0 deletions projects/safecode/lib/BaggyBoundsChecks/PromoteArrayAllocas.cpp
@@ -0,0 +1,191 @@
//===- PromoteArrayAlloca.cpp - Promote array alloca instructions to malloc --//
//
// 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 array alloca instuction to malloc
// allocations.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "promotearrayalloca"

#include "safecode/Config/config.h"
#include "safecode/Utility.h"
#include "safecode/PromoteArrayAllocas.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/IR/Dominators.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include <iostream>

#include <list>

namespace llvm {

STATISTIC (promoteArrayAllocas, "Number of converted array allocas");
STATISTIC (missingFrees, "Number of frees that we didn't insert");

namespace {
static RegisterPass<PromoteArrayAllocas> paa
("promoteArrayAllocas", "Promote Array Allocas");
}

char PromoteArrayAllocas::ID = 0;

void
PromoteArrayAllocas::createProtos (Module & M) {
ArrayRef<Type *> Arg (Int64Type);
FunctionType *mallocTy = FunctionType::get (getVoidPtrType(M), Arg, false);
malloc = M.getOrInsertFunction ("malloc", mallocTy);

ArrayRef<Type *> FreeArgs (getVoidPtrType(M));
FunctionType *freeTy = FunctionType::get (Type::getVoidTy(M.getContext()), FreeArgs, false);
free = M.getOrInsertFunction ("free", freeTy);

assert ((malloc != 0) && "No malloc function found!\n");
assert ((free != 0) && "No free function found!\n");
}

// Transform Array Allocation to Malloc
Instruction *
PromoteArrayAllocas::transformArrayAlloca (AllocaInst & A) {
BasicBlock *CurrentBlock = A.getParent();

uint64_t TypeSize = TD->getTypeAllocSize (A.getAllocatedType());
Value *AllocSize = ConstantInt::get (Int64Type, TypeSize);
Instruction * MallocInsertPt = &A;
Value *ArraySize = A.getOperand(0);
if (ArraySize->getType() != Int64Type) {
ArraySize = castTo (ArraySize,
Int64Type,
ArraySize->getName()+".casted",
MallocInsertPt);
}
ArraySize = BinaryOperator::Create( Instruction::Mul, AllocSize,
ArraySize, "arrayallocasizetmp",
MallocInsertPt);
ArrayRef<Value *> MallocArgs (ArraySize);
CallInst *MallocCall = CallInst::Create (malloc, MallocArgs, "", MallocInsertPt);
Instruction * CastedMallocCall = castTo (MallocCall,
A.getType(),
MallocCall->getName()+".casted",
MallocInsertPt);

A.replaceAllUsesWith (CastedMallocCall);
promoteArrayAllocas ++;
return MallocCall;
}

//
// There are two kinds of allocas: the allocas in the entry block and the allocas
// out of entry block. For the alloca in the entry block, simply insert the free
// at the end of the block.
//
bool
PromoteArrayAllocas::insertFreeForAllocaInEntryBlock (AllocaInst & A,
Instruction * MallocInst) {
bool isInserted = false;
BasicBlock *CurrentBlock = A.getParent();
Function * F = CurrentBlock->getParent();
std::vector<Instruction*> FreePoints;
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
if (isa<ReturnInst>(BB->getTerminator()) ||
isa<ResumeInst>(BB->getTerminator()))
FreePoints.push_back(BB->getTerminator());

std::vector<Instruction*>::iterator fpI = FreePoints.begin(),
fpE = FreePoints.end();
for (; fpI != fpE ; ++ fpI) {
Instruction *InsertPt = *fpI;
ArrayRef<Value *> args(MallocInst);
CallInst::Create (free, args, "", InsertPt);
isInserted = true;
}
return isInserted;
}

//
// For the allocas of of entry block, For 'Definations must dominate uses', we must ensure
// that the free() is dominated by the malloc().
//
bool
PromoteArrayAllocas::insertFreeForAllocaOutOfEntryBlock (AllocaInst & A,
Instruction * MallocInst) {
BasicBlock *CurrentBlock = A.getParent();
Function * F = CurrentBlock->getParent();
DominanceFrontier * dfmt = &getAnalysis<DominanceFrontier>(*F);
DominatorTree * domTree = &getAnalysis<DominatorTreeWrapperPass>(*F).getDomTree();

DominanceFrontier::const_iterator it = dfmt->find(CurrentBlock);
if (it != dfmt->end()) {
const DominanceFrontier::DomSetType &S = it->second;
if (S.size() > 0) {
DominanceFrontier::DomSetType::iterator pCurrent = S.begin(), pEnd = S.end();
for (; pCurrent != pEnd; ++pCurrent) {
BasicBlock *frontierBlock = *pCurrent;
// One of its predecessors is dominated by CurrentBlock;
// need to insert a free in that predecessor
for (pred_iterator SI = pred_begin(frontierBlock),
SE = pred_end(frontierBlock);
SI != SE; ++SI) {
BasicBlock *predecessorBlock = *SI;
if (domTree->dominates (predecessorBlock, CurrentBlock)) {
// Get the terminator
Instruction *InsertPt = predecessorBlock->getTerminator();
ArrayRef<Value *> args(MallocInst);
CallInst::Create (free, args, "", InsertPt);
}
}
}
return true;
}
}
return insertFreeForAllocaInEntryBlock(A, MallocInst);
}

void
PromoteArrayAllocas::visitAllocaInst(AllocaInst &A)
{
if(!A.isArrayAllocation() || isa<ConstantInt>(A.getOperand(0)))
return;

Instruction * I = transformArrayAlloca(A);
BasicBlock * Parent = A.getParent();
bool isInserted = false;
if(Parent == &Parent->getParent()->front())
isInserted = insertFreeForAllocaInEntryBlock(A, I);
else
isInserted = insertFreeForAllocaOutOfEntryBlock(A, I);

if (!isInserted) missingFrees ++;

Parent->getInstList().erase(A);
}

bool
PromoteArrayAllocas::runOnModule (Module & M) {
TD = &M.getDataLayout();
//
// Get needed LLVM types.
//
VoidType = Type::getVoidTy(getGlobalContext());
Int32Type = IntegerType::getInt32Ty(getGlobalContext());
Int64Type = IntegerType::getInt64Ty(getGlobalContext());

//
// Add protype for run-time functions.
//
createProtos(M);

visit(M);
return true;
}

} //end namespace llvm

2 changes: 2 additions & 0 deletions projects/safecode/tools/clang/lib/CodeGen/BackendUtil.cpp
Expand Up @@ -61,6 +61,7 @@
#include "safecode/SAFECodeMSCInfo.h"
#include "safecode/SAFECodePasses.h"
#include "safecode/SpecializeCMSCalls.h"
#include "safecode/PromoteArrayAllocas.h"
#include "SoftBound/InitializeSoftBound.h"
#include "SoftBound/SoftBoundCETSPass.h"

Expand Down Expand Up @@ -516,6 +517,7 @@ void EmitAssemblyHelper::CreatePasses() {
}

if (CodeGenOpts.BaggyBounds) {
MPM->add (new PromoteArrayAllocas());
MPM->add (new InsertBaggyBoundsChecks());
}

Expand Down

1 comment on commit a6746c5

@zhengyang92
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More comment's will be added

Please sign in to comment.