ProfilingUtils.cpp revision d46fdb45387f46beeadc04472b3a66ad1da3aca1
1//===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements a few helper functions which are used by profile 11// instrumentation code to instrument the code. This allows the profiler pass 12// to worry about *what* to insert, and these functions take care of *how* to do 13// it. 14// 15//===----------------------------------------------------------------------===// 16 17#include "ProfilingUtils.h" 18#include "llvm/Constants.h" 19#include "llvm/DerivedTypes.h" 20#include "llvm/Instructions.h" 21#include "llvm/LLVMContext.h" 22#include "llvm/Module.h" 23 24void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, 25 GlobalValue *Array) { 26 LLVMContext &Context = MainFn->getContext(); 27 const Type *ArgVTy = 28 PointerType::getUnqual(Type::getInt8PtrTy(Context)); 29 const PointerType *UIntPtr = 30 Type::getInt32PtrTy(Context); 31 Module &M = *MainFn->getParent(); 32 Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context), 33 Type::getInt32Ty(Context), 34 ArgVTy, UIntPtr, 35 Type::getInt32Ty(Context), 36 (Type *)0); 37 38 // This could force argc and argv into programs that wouldn't otherwise have 39 // them, but instead we just pass null values in. 40 std::vector<Value*> Args(4); 41 Args[0] = Constant::getNullValue(Type::getInt32Ty(Context)); 42 Args[1] = Constant::getNullValue(ArgVTy); 43 44 // Skip over any allocas in the entry block. 45 BasicBlock *Entry = MainFn->begin(); 46 BasicBlock::iterator InsertPos = Entry->begin(); 47 while (isa<AllocaInst>(InsertPos)) ++InsertPos; 48 49 std::vector<Constant*> GEPIndices(2, 50 Constant::getNullValue(Type::getInt32Ty(Context))); 51 unsigned NumElements = 0; 52 if (Array) { 53 Args[2] = ConstantExpr::getGetElementPtr(Array, &GEPIndices[0], 54 GEPIndices.size()); 55 NumElements = 56 cast<ArrayType>(Array->getType()->getElementType())->getNumElements(); 57 } else { 58 // If this profiling instrumentation doesn't have a constant array, just 59 // pass null. 60 Args[2] = ConstantPointerNull::get(UIntPtr); 61 } 62 Args[3] = ConstantInt::get(Type::getInt32Ty(Context), NumElements); 63 64 Instruction *InitCall = CallInst::Create(InitFn, Args.begin(), Args.end(), 65 "newargc", InsertPos); 66 67 // If argc or argv are not available in main, just pass null values in. 68 Function::arg_iterator AI; 69 switch (MainFn->arg_size()) { 70 default: 71 case 2: 72 AI = MainFn->arg_begin(); ++AI; 73 if (AI->getType() != ArgVTy) { 74 Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy, 75 false); 76 InitCall->setOperand(1, 77 CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall)); 78 } else { 79 InitCall->setOperand(1, AI); 80 } 81 /* FALL THROUGH */ 82 83 case 1: 84 AI = MainFn->arg_begin(); 85 // If the program looked at argc, have it look at the return value of the 86 // init call instead. 87 if (!AI->getType()->isIntegerTy(32)) { 88 Instruction::CastOps opcode; 89 if (!AI->use_empty()) { 90 opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true); 91 AI->replaceAllUsesWith( 92 CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos)); 93 } 94 opcode = CastInst::getCastOpcode(AI, true, 95 Type::getInt32Ty(Context), true); 96 InitCall->setOperand(0, 97 CastInst::Create(opcode, AI, Type::getInt32Ty(Context), 98 "argc.cast", InitCall)); 99 } else { 100 AI->replaceAllUsesWith(InitCall); 101 InitCall->setOperand(0, AI); 102 } 103 104 case 0: break; 105 } 106} 107 108void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum, 109 GlobalValue *CounterArray) { 110 // Insert the increment after any alloca or PHI instructions... 111 BasicBlock::iterator InsertPos = BB->getFirstNonPHI(); 112 while (isa<AllocaInst>(InsertPos)) 113 ++InsertPos; 114 115 LLVMContext &Context = BB->getContext(); 116 117 // Create the getelementptr constant expression 118 std::vector<Constant*> Indices(2); 119 Indices[0] = Constant::getNullValue(Type::getInt32Ty(Context)); 120 Indices[1] = ConstantInt::get(Type::getInt32Ty(Context), CounterNum); 121 Constant *ElementPtr = 122 ConstantExpr::getGetElementPtr(CounterArray, &Indices[0], 123 Indices.size()); 124 125 // Load, increment and store the value back. 126 Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos); 127 Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal, 128 ConstantInt::get(Type::getInt32Ty(Context), 1), 129 "NewFuncCounter", InsertPos); 130 new StoreInst(NewVal, ElementPtr, InsertPos); 131} 132