1 //===- ProfilingUtils.cpp - Helper functions shared by profilers ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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
15 //===----------------------------------------------------------------------===//
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"
24 void llvm::InsertProfilingInitCall(Function
*MainFn
, const char *FnName
,
26 LLVMContext
&Context
= MainFn
->getContext();
28 PointerType::getUnqual(PointerType::getUnqual(Type::getInt8Ty(Context
)));
29 const PointerType
*UIntPtr
=
30 PointerType::getUnqual(Type::getInt32Ty(Context
));
31 Module
&M
= *MainFn
->getParent();
32 Constant
*InitFn
= M
.getOrInsertFunction(FnName
, Type::getInt32Ty(Context
),
33 Type::getInt32Ty(Context
),
35 Type::getInt32Ty(Context
),
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
);
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
;
49 std::vector
<Constant
*> GEPIndices(2,
50 Constant::getNullValue(Type::getInt32Ty(Context
)));
51 unsigned NumElements
= 0;
53 Args
[2] = ConstantExpr::getGetElementPtr(Array
, &GEPIndices
[0],
56 cast
<ArrayType
>(Array
->getType()->getElementType())->getNumElements();
58 // If this profiling instrumentation doesn't have a constant array, just
60 Args
[2] = ConstantPointerNull::get(UIntPtr
);
62 Args
[3] = ConstantInt::get(Type::getInt32Ty(Context
), NumElements
);
64 Instruction
*InitCall
= CallInst::Create(InitFn
, Args
.begin(), Args
.end(),
65 "newargc", InsertPos
);
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()) {
72 AI
= MainFn
->arg_begin(); ++AI
;
73 if (AI
->getType() != ArgVTy
) {
74 Instruction::CastOps opcode
= CastInst::getCastOpcode(AI
, false, ArgVTy
,
76 InitCall
->setOperand(2,
77 CastInst::Create(opcode
, AI
, ArgVTy
, "argv.cast", InitCall
));
79 InitCall
->setOperand(2, AI
);
84 AI
= MainFn
->arg_begin();
85 // If the program looked at argc, have it look at the return value of the
87 if (AI
->getType() != Type::getInt32Ty(Context
)) {
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
));
94 opcode
= CastInst::getCastOpcode(AI
, true,
95 Type::getInt32Ty(Context
), true);
96 InitCall
->setOperand(1,
97 CastInst::Create(opcode
, AI
, Type::getInt32Ty(Context
),
98 "argc.cast", InitCall
));
100 AI
->replaceAllUsesWith(InitCall
);
101 InitCall
->setOperand(1, AI
);
108 void 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
))
115 LLVMContext
&Context
= BB
->getContext();
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],
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
);