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 PointerType
*arrayType
) {
27 LLVMContext
&Context
= MainFn
->getContext();
29 PointerType::getUnqual(Type::getInt8PtrTy(Context
));
30 const PointerType
*UIntPtr
= arrayType
? arrayType
:
31 Type::getInt32PtrTy(Context
);
32 Module
&M
= *MainFn
->getParent();
33 Constant
*InitFn
= M
.getOrInsertFunction(FnName
, Type::getInt32Ty(Context
),
34 Type::getInt32Ty(Context
),
36 Type::getInt32Ty(Context
),
39 // This could force argc and argv into programs that wouldn't otherwise have
40 // them, but instead we just pass null values in.
41 std::vector
<Value
*> Args(4);
42 Args
[0] = Constant::getNullValue(Type::getInt32Ty(Context
));
43 Args
[1] = Constant::getNullValue(ArgVTy
);
45 // Skip over any allocas in the entry block.
46 BasicBlock
*Entry
= MainFn
->begin();
47 BasicBlock::iterator InsertPos
= Entry
->begin();
48 while (isa
<AllocaInst
>(InsertPos
)) ++InsertPos
;
50 std::vector
<Constant
*> GEPIndices(2,
51 Constant::getNullValue(Type::getInt32Ty(Context
)));
52 unsigned NumElements
= 0;
54 Args
[2] = ConstantExpr::getGetElementPtr(Array
, &GEPIndices
[0],
57 cast
<ArrayType
>(Array
->getType()->getElementType())->getNumElements();
59 // If this profiling instrumentation doesn't have a constant array, just
61 Args
[2] = ConstantPointerNull::get(UIntPtr
);
63 Args
[3] = ConstantInt::get(Type::getInt32Ty(Context
), NumElements
);
65 CallInst
*InitCall
= CallInst::Create(InitFn
, Args
.begin(), Args
.end(),
66 "newargc", InsertPos
);
68 // If argc or argv are not available in main, just pass null values in.
69 Function::arg_iterator AI
;
70 switch (MainFn
->arg_size()) {
73 AI
= MainFn
->arg_begin(); ++AI
;
74 if (AI
->getType() != ArgVTy
) {
75 Instruction::CastOps opcode
= CastInst::getCastOpcode(AI
, false, ArgVTy
,
77 InitCall
->setArgOperand(1,
78 CastInst::Create(opcode
, AI
, ArgVTy
, "argv.cast", InitCall
));
80 InitCall
->setArgOperand(1, AI
);
85 AI
= MainFn
->arg_begin();
86 // If the program looked at argc, have it look at the return value of the
88 if (!AI
->getType()->isIntegerTy(32)) {
89 Instruction::CastOps opcode
;
90 if (!AI
->use_empty()) {
91 opcode
= CastInst::getCastOpcode(InitCall
, true, AI
->getType(), true);
92 AI
->replaceAllUsesWith(
93 CastInst::Create(opcode
, InitCall
, AI
->getType(), "", InsertPos
));
95 opcode
= CastInst::getCastOpcode(AI
, true,
96 Type::getInt32Ty(Context
), true);
97 InitCall
->setArgOperand(0,
98 CastInst::Create(opcode
, AI
, Type::getInt32Ty(Context
),
99 "argc.cast", InitCall
));
101 AI
->replaceAllUsesWith(InitCall
);
102 InitCall
->setArgOperand(0, AI
);
109 void llvm::IncrementCounterInBlock(BasicBlock
*BB
, unsigned CounterNum
,
110 GlobalValue
*CounterArray
, bool beginning
) {
111 // Insert the increment after any alloca or PHI instructions...
112 BasicBlock::iterator InsertPos
= beginning
? BB
->getFirstNonPHI() :
114 while (isa
<AllocaInst
>(InsertPos
))
117 LLVMContext
&Context
= BB
->getContext();
119 // Create the getelementptr constant expression
120 std::vector
<Constant
*> Indices(2);
121 Indices
[0] = Constant::getNullValue(Type::getInt32Ty(Context
));
122 Indices
[1] = ConstantInt::get(Type::getInt32Ty(Context
), CounterNum
);
123 Constant
*ElementPtr
=
124 ConstantExpr::getGetElementPtr(CounterArray
, &Indices
[0], Indices
.size());
126 // Load, increment and store the value back.
127 Value
*OldVal
= new LoadInst(ElementPtr
, "OldFuncCounter", InsertPos
);
128 Value
*NewVal
= BinaryOperator::Create(Instruction::Add
, OldVal
,
129 ConstantInt::get(Type::getInt32Ty(Context
), 1),
130 "NewFuncCounter", InsertPos
);
131 new StoreInst(NewVal
, ElementPtr
, InsertPos
);
134 void llvm::InsertProfilingShutdownCall(Function
*Callee
, Module
*Mod
) {
135 // llvm.global_dtors is an array of type { i32, void ()* }. Prepare those
137 const Type
*GlobalDtorElems
[2] = {
138 Type::getInt32Ty(Mod
->getContext()),
139 FunctionType::get(Type::getVoidTy(Mod
->getContext()), false)->getPointerTo()
141 const StructType
*GlobalDtorElemTy
=
142 StructType::get(Mod
->getContext(), GlobalDtorElems
, false);
144 // Construct the new element we'll be adding.
145 Constant
*Elem
[2] = {
146 ConstantInt::get(Type::getInt32Ty(Mod
->getContext()), 65535),
147 ConstantExpr::getBitCast(Callee
, GlobalDtorElems
[1])
150 // If llvm.global_dtors exists, make a copy of the things in its list and
151 // delete it, to replace it with one that has a larger array type.
152 std::vector
<Constant
*> dtors
;
153 if (GlobalVariable
*GlobalDtors
= Mod
->getNamedGlobal("llvm.global_dtors")) {
154 if (ConstantArray
*InitList
=
155 dyn_cast
<ConstantArray
>(GlobalDtors
->getInitializer())) {
156 for (unsigned i
= 0, e
= InitList
->getType()->getNumElements();
158 dtors
.push_back(cast
<Constant
>(InitList
->getOperand(i
)));
160 GlobalDtors
->eraseFromParent();
163 // Build up llvm.global_dtors with our new item in it.
164 GlobalVariable
*GlobalDtors
= new GlobalVariable(
165 *Mod
, ArrayType::get(GlobalDtorElemTy
, 1), false,
166 GlobalValue::AppendingLinkage
, NULL
, "llvm.global_dtors");
168 dtors
.push_back(ConstantStruct::get(GlobalDtorElemTy
, Elem
));
169 GlobalDtors
->setInitializer(ConstantArray::get(
170 cast
<ArrayType
>(GlobalDtors
->getType()->getElementType()), dtors
));