blob: bdcac72c19b40934acceaf7407541f4103114e87 [file] [log] [blame]
//===- Dyncount.cpp - Test pass for using constraints -----------*- C++ -*-===//
//
// 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 test pass which helps test the generation of formulas
// and constraints.
//
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "dsa/TypeSafety.h"
using namespace llvm;
class Dyncount : public ModulePass {
protected:
void instrumentLoad (GlobalVariable * Counter, LoadInst * LI);
void instrumentStore (GlobalVariable * Counter, StoreInst * SI);
dsa::TypeSafety<TDDataStructures> *TS;
public:
static char ID;
Dyncount () : ModulePass (ID) { }
const char *getPassName() const {
return "Count safe/unsafe load/store";
}
virtual bool runOnModule (Module & M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<DataLayoutPass>();
AU.addRequired<dsa::TypeSafety<TDDataStructures> >();
}
};
char Dyncount::ID = 0;
static RegisterPass<Dyncount>
X ("dyncount", "Instrument code to count number of Load/Stores");
void
Dyncount::instrumentLoad (GlobalVariable * Counter, LoadInst * LI) {
//
// Generate a load, increment, and store right before the GEP.
//
LLVMContext & Context = Counter->getParent()->getContext();
ConstantInt * One = ConstantInt::get (Type::getInt64Ty(Context), 1);
LoadInst * OldValue = new LoadInst (Counter, "count", LI);
Instruction * NewValue = BinaryOperator::Create (BinaryOperator::Add,
OldValue,
One,
"count",
LI);
new StoreInst (NewValue, Counter, LI);
return;
}
void
Dyncount::instrumentStore (GlobalVariable * Counter, StoreInst * SI) {
//
// Generate a load, increment, and store right before the GEP.
//
LLVMContext & Context = Counter->getParent()->getContext();
ConstantInt * One = ConstantInt::get (Type::getInt64Ty(Context), 1);
LoadInst * OldValue = new LoadInst (Counter, "count", SI);
Instruction * NewValue = BinaryOperator::Create (BinaryOperator::Add,
OldValue,
One,
"count",
SI);
new StoreInst (NewValue, Counter, SI);
return;
}
//
// Method: runOnModule()
//
// Description:
// Entry point for this pass.
//
bool
Dyncount::runOnModule (Module & M) {
//
// Create two global counters within the module.
//
TS = &getAnalysis<dsa::TypeSafety<TDDataStructures> >();
ConstantInt * Zero = ConstantInt::get (Type::getInt64Ty(M.getContext()), 0);
GlobalVariable * Total = new GlobalVariable (M,
Type::getInt64Ty(M.getContext()),
false,
GlobalValue::InternalLinkage,
Zero,
"Total");
GlobalVariable * Safe = new GlobalVariable (M,
Type::getInt64Ty(M.getContext()),
false,
GlobalValue::InternalLinkage,
Zero,
"Safe");
for (Module::iterator F = M.begin(); F != M.end(); ++F){
for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) {
for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE; I++) {
if(LoadInst *LI = dyn_cast<LoadInst>(I)) {
instrumentLoad(Total, LI);
if(TS->isTypeSafe(LI->getOperand(0),LI->getParent()->getParent()))
instrumentLoad(Safe, LI);
// check if safe
} else if(StoreInst *SI = dyn_cast<StoreInst>(I)) {
instrumentStore(Total, SI);
if(TS->isTypeSafe(SI->getOperand(1),SI->getParent()->getParent()))
instrumentStore(Safe, SI);
// check if safe
}
}
}
}
//
// Add a call to main() that will record the values on exit().
//
Function *MainFunc = M.getFunction("main") ? M.getFunction("main")
: M.getFunction ("MAIN__");
BasicBlock & BB = MainFunc->getEntryBlock();
Constant * Setup = M.getOrInsertFunction ("DYN_COUNT_setup", Type::getVoidTy(M.getContext()), Total->getType(), Safe->getType(), NULL);
std::vector<Value *> args;
args.push_back (Total);
args.push_back (Safe);
CallInst::Create (Setup, args, "", BB.getFirstNonPHI());
return true;
}