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, 00030 (Type *)0); 00031 00032 // This could force argc and argv into programs that wouldn't otherwise have 00033 // them, but instead we just pass null values in. 00034 std::vector<Value*> Args(4); 00035 Args[0] = Constant::getNullValue(Type::IntTy); 00036 Args[1] = Constant::getNullValue(ArgVTy); 00037 00038 // Skip over any allocas in the entry block. 00039 BasicBlock *Entry = MainFn->begin(); 00040 BasicBlock::iterator InsertPos = Entry->begin(); 00041 while (isa<AllocaInst>(InsertPos)) ++InsertPos; 00042 00043 std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::IntTy)); 00044 unsigned NumElements = 0; 00045 if (Array) { 00046 Args[2] = ConstantExpr::getGetElementPtr(Array, GEPIndices); 00047 NumElements = 00048 cast<ArrayType>(Array->getType()->getElementType())->getNumElements(); 00049 } else { 00050 // If this profiling instrumentation doesn't have a constant array, just 00051 // pass null. 00052 Args[2] = ConstantPointerNull::get(UIntPtr); 00053 } 00054 Args[3] = ConstantUInt::get(Type::UIntTy, NumElements); 00055 00056 Instruction *InitCall = new CallInst(InitFn, Args, "newargc", InsertPos); 00057 00058 // If argc or argv are not available in main, just pass null values in. 00059 Function::arg_iterator AI; 00060 switch (MainFn->arg_size()) { 00061 default: 00062 case 2: 00063 AI = MainFn->arg_begin(); ++AI; 00064 if (AI->getType() != ArgVTy) { 00065 InitCall->setOperand(2, new CastInst(AI, ArgVTy, "argv.cast", InitCall)); 00066 } else { 00067 InitCall->setOperand(2, AI); 00068 } 00069 00070 case 1: 00071 AI = MainFn->arg_begin(); 00072 // If the program looked at argc, have it look at the return value of the 00073 // init call instead. 00074 if (AI->getType() != Type::IntTy) { 00075 if (!AI->use_empty()) 00076 AI->replaceAllUsesWith(new CastInst(InitCall, AI->getType(), "", 00077 InsertPos)); 00078 InitCall->setOperand(1, new CastInst(AI, Type::IntTy, "argc.cast", 00079 InitCall)); 00080 } else { 00081 AI->replaceAllUsesWith(InitCall); 00082 InitCall->setOperand(1, AI); 00083 } 00084 00085 case 0: break; 00086 } 00087 } 00088 00089 void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, 00090 GlobalValue *CounterArray) { 00091 // Insert the increment after any alloca or PHI instructions... 00092 BasicBlock::iterator InsertPos = BB->begin(); 00093 while (isa<AllocaInst>(InsertPos) || isa<PHINode>(InsertPos)) 00094 ++InsertPos; 00095 00096 // Create the getelementptr constant expression 00097 std::vector<Constant*> Indices(2); 00098 Indices[0] = Constant::getNullValue(Type::IntTy); 00099 Indices[1] = ConstantSInt::get(Type::IntTy, CounterNum); 00100 Constant *ElementPtr = ConstantExpr::getGetElementPtr(CounterArray, Indices); 00101 00102 // Load, increment and store the value back. 00103 Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); 00104 Value *NewVal = BinaryOperator::create(Instruction::Add, OldVal, 00105 ConstantInt::get(Type::UIntTy, 1), 00106 "NewFuncCounter", InsertPos); 00107 new StoreInst(NewVal, ElementPtr, InsertPos); 00108 }