~ubuntu-branches/ubuntu/quantal/llvm-3.1/quantal

« back to all changes in this revision

Viewing changes to lib/Transforms/Instrumentation/ProfilingUtils.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2012-03-29 19:09:51 UTC
  • Revision ID: package-import@ubuntu.com-20120329190951-aq83ivog4cg8bxun
Tags: upstream-3.1~svn153643
ImportĀ upstreamĀ versionĀ 3.1~svn153643

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
24
void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName,
 
25
                                   GlobalValue *Array,
 
26
                                   PointerType *arrayType) {
 
27
  LLVMContext &Context = MainFn->getContext();
 
28
  Type *ArgVTy =
 
29
    PointerType::getUnqual(Type::getInt8PtrTy(Context));
 
30
  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),
 
35
                                           ArgVTy, UIntPtr,
 
36
                                           Type::getInt32Ty(Context),
 
37
                                           (Type *)0);
 
38
 
 
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);
 
44
 
 
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;
 
49
 
 
50
  std::vector<Constant*> GEPIndices(2,
 
51
                             Constant::getNullValue(Type::getInt32Ty(Context)));
 
52
  unsigned NumElements = 0;
 
53
  if (Array) {
 
54
    Args[2] = ConstantExpr::getGetElementPtr(Array, GEPIndices);
 
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
  CallInst *InitCall = CallInst::Create(InitFn, Args, "newargc", InsertPos);
 
65
 
 
66
  // If argc or argv are not available in main, just pass null values in.
 
67
  Function::arg_iterator AI;
 
68
  switch (MainFn->arg_size()) {
 
69
  default:
 
70
  case 2:
 
71
    AI = MainFn->arg_begin(); ++AI;
 
72
    if (AI->getType() != ArgVTy) {
 
73
      Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy,
 
74
                                                            false);
 
75
      InitCall->setArgOperand(1,
 
76
          CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall));
 
77
    } else {
 
78
      InitCall->setArgOperand(1, AI);
 
79
    }
 
80
    /* FALL THROUGH */
 
81
 
 
82
  case 1:
 
83
    AI = MainFn->arg_begin();
 
84
    // If the program looked at argc, have it look at the return value of the
 
85
    // init call instead.
 
86
    if (!AI->getType()->isIntegerTy(32)) {
 
87
      Instruction::CastOps opcode;
 
88
      if (!AI->use_empty()) {
 
89
        opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true);
 
90
        AI->replaceAllUsesWith(
 
91
          CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos));
 
92
      }
 
93
      opcode = CastInst::getCastOpcode(AI, true,
 
94
                                       Type::getInt32Ty(Context), true);
 
95
      InitCall->setArgOperand(0,
 
96
          CastInst::Create(opcode, AI, Type::getInt32Ty(Context),
 
97
                           "argc.cast", InitCall));
 
98
    } else {
 
99
      AI->replaceAllUsesWith(InitCall);
 
100
      InitCall->setArgOperand(0, AI);
 
101
    }
 
102
 
 
103
  case 0: break;
 
104
  }
 
105
}
 
106
 
 
107
void llvm::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
 
108
                                   GlobalValue *CounterArray, bool beginning) {
 
109
  // Insert the increment after any alloca or PHI instructions...
 
110
  BasicBlock::iterator InsertPos = beginning ? BB->getFirstInsertionPt() :
 
111
                                   BB->getTerminator();
 
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);
 
123
 
 
124
  // Load, increment and store the value back.
 
125
  Value *OldVal = new LoadInst(ElementPtr, "OldFuncCounter", InsertPos);
 
126
  Value *NewVal = BinaryOperator::Create(Instruction::Add, OldVal,
 
127
                                 ConstantInt::get(Type::getInt32Ty(Context), 1),
 
128
                                         "NewFuncCounter", InsertPos);
 
129
  new StoreInst(NewVal, ElementPtr, InsertPos);
 
130
}
 
131
 
 
132
void llvm::InsertProfilingShutdownCall(Function *Callee, Module *Mod) {
 
133
  // llvm.global_dtors is an array of type { i32, void ()* }. Prepare those
 
134
  // types.
 
135
  Type *GlobalDtorElems[2] = {
 
136
    Type::getInt32Ty(Mod->getContext()),
 
137
    FunctionType::get(Type::getVoidTy(Mod->getContext()), false)->getPointerTo()
 
138
  };
 
139
  StructType *GlobalDtorElemTy =
 
140
      StructType::get(Mod->getContext(), GlobalDtorElems, false);
 
141
 
 
142
  // Construct the new element we'll be adding.
 
143
  Constant *Elem[2] = {
 
144
    ConstantInt::get(Type::getInt32Ty(Mod->getContext()), 65535),
 
145
    ConstantExpr::getBitCast(Callee, GlobalDtorElems[1])
 
146
  };
 
147
 
 
148
  // If llvm.global_dtors exists, make a copy of the things in its list and
 
149
  // delete it, to replace it with one that has a larger array type.
 
150
  std::vector<Constant *> dtors;
 
151
  if (GlobalVariable *GlobalDtors = Mod->getNamedGlobal("llvm.global_dtors")) {
 
152
    if (ConstantArray *InitList =
 
153
        dyn_cast<ConstantArray>(GlobalDtors->getInitializer())) {
 
154
      for (unsigned i = 0, e = InitList->getType()->getNumElements();
 
155
           i != e; ++i)
 
156
        dtors.push_back(cast<Constant>(InitList->getOperand(i)));
 
157
    }
 
158
    GlobalDtors->eraseFromParent();
 
159
  }
 
160
 
 
161
  // Build up llvm.global_dtors with our new item in it.
 
162
  GlobalVariable *GlobalDtors = new GlobalVariable(
 
163
      *Mod, ArrayType::get(GlobalDtorElemTy, 1), false,
 
164
      GlobalValue::AppendingLinkage, NULL, "llvm.global_dtors");
 
165
                                    
 
166
  dtors.push_back(ConstantStruct::get(GlobalDtorElemTy, Elem));
 
167
  GlobalDtors->setInitializer(ConstantArray::get(
 
168
      cast<ArrayType>(GlobalDtors->getType()->getElementType()), dtors));
 
169
}