LLVM API Documentation
00001 //===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This files implements a few helper functions which are used by profile 00011 // instrumentation code to instrument the code. This allows the profiler pass 00012 // to worry about *what* to insert, and these functions take care of *how* to do 00013 // it. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #include "ProfilingUtils.h" 00018 #include "llvm/Constants.h" 00019 #include "llvm/DerivedTypes.h" 00020 #include "llvm/Instructions.h" 00021 #include "llvm/Module.h" 00022 00023 void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, 00024 GlobalValue *Array) { 00025 const Type *ArgVTy = PointerType::get(PointerType::get(Type::SByteTy)); 00026 const PointerType *UIntPtr = PointerType::get(Type::UIntTy); 00027 Module &M = *MainFn->getParent(); 00028 Function *InitFn = M.getOrInsertFunction(FnName, Type::IntTy, Type::IntTy, 00029 ArgVTy, UIntPtr, Type::UIntTy, 0); 00030 00031 // This could force argc and argv into programs that wouldn't otherwise have 00032 // them, but instead we just pass null values in. 00033 std::vector<Value*> Args(4); 00034 Args[0] = Constant::getNullValue(Type::IntTy); 00035 Args[1] = Constant::getNullValue(ArgVTy); 00036 00037 // Skip over any allocas in the entry block. 00038 BasicBlock *Entry = MainFn->begin(); 00039 BasicBlock::iterator InsertPos = Entry->begin(); 00040 while (isa<AllocaInst>(InsertPos)) ++InsertPos; 00041 00042 std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::IntTy)); 00043 unsigned NumElements = 0; 00044 if (Array) { 00045 Args[2] = ConstantExpr::getGetElementPtr(Array, GEPIndices); 00046 NumElements = 00047 cast<ArrayType>(Array->getType()->getElementType())->getNumElements(); 00048 } else { 00049 // If this profiling instrumentation doesn't have a constant array, just 00050 // pass null. 00051 Args[2] = ConstantPointerNull::get(UIntPtr); 00052 } 00053 Args[3] = ConstantUInt::get(Type::UIntTy, NumElements); 00054 00055 Instruction *InitCall = new CallInst(InitFn, Args, "newargc", InsertPos); 00056 00057 // If argc or argv are not available in main, just pass null values in. 00058 Function::aiterator AI; 00059 switch (MainFn->asize()) { 00060 default: 00061 case 2: 00062 AI = MainFn->abegin(); ++AI; 00063 if (AI->getType() != ArgVTy) { 00064 InitCall->setOperand(2, new CastInst(AI, ArgVTy, "argv.cast", InitCall)); 00065 } else { 00066 InitCall->setOperand(2, AI); 00067 } 00068 00069 case 1: 00070 AI = MainFn->abegin(); 00071 // If the program looked at argc, have it look at the return value of the 00072 // init call instead. 00073 if (AI->getType() != Type::IntTy) { 00074 if (!AI->use_empty()) 00075 AI->replaceAllUsesWith(new CastInst(InitCall, AI->getType(), "", 00076 InsertPos)); 00077 InitCall->setOperand(1, new CastInst(AI, Type::IntTy, "argc.cast", 00078 InitCall)); 00079 } else { 00080 AI->replaceAllUsesWith(InitCall); 00081 InitCall->setOperand(1, AI); 00082 } 00083 00084 case 0: break; 00085 } 00086 } 00087 00088 void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, 00089 GlobalValue *CounterArray) { 00090 // Insert the increment after any alloca or PHI instructions... 00091 BasicBlock::iterator InsertPos = BB->begin(); 00092 while (isa<AllocaInst>(InsertPos) || isa<PHINode>(InsertPos)) 00093 ++InsertPos; 00094 00095 // Create the getelementptr constant expression 00096 std::vector<Constant*> Indices(2); 00097 Indices[0] = Constant::getNullValue(Type::IntTy); 00098 Indices[1] = ConstantSInt::get(Type::IntTy, CounterNum); 00099 Constant *ElementPtr = ConstantExpr::getGetElementPtr(CounterArray, Indices); 00100 00101 // Load, increment and store the value back. 00102 Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); 00103 Value *NewVal = BinaryOperator::create(Instruction::Add, OldVal, 00104 ConstantInt::get(Type::UIntTy, 1), 00105 "NewFuncCounter", InsertPos); 00106 new StoreInst(NewVal, ElementPtr, InsertPos); 00107 }