1//===- subzero/src/IceInstrumentation.cpp - ICE instrumentation framework -===//
2//
3//                        The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief Implements the Ice::Instrumentation class.
12///
13/// Subclasses can override particular instrumentation methods to specify how
14/// the the target program should be instrumented.
15///
16//===----------------------------------------------------------------------===//
17
18#include "IceInstrumentation.h"
19
20#include "IceCfg.h"
21#include "IceInst.h"
22#include "IceTargetLowering.h"
23
24namespace Ice {
25
26// Iterate through the instructions in the given CFG and instrument each one.
27// Also instrument the beginning of the function.
28void Instrumentation::instrumentFunc(Cfg *Func) {
29  assert(Func);
30  assert(!Func->getNodes().empty());
31
32  if (!isInstrumentable(Func))
33    return;
34
35  bool DidInstrumentEntry = false;
36  LoweringContext Context;
37  Context.init(Func->getNodes().front());
38  for (CfgNode *Node : Func->getNodes()) {
39    Context.init(Node);
40    while (!Context.atEnd()) {
41      if (!DidInstrumentEntry) {
42        instrumentFuncStart(Context);
43        DidInstrumentEntry = true;
44      }
45      instrumentInst(Context);
46      // go to next undeleted instruction
47      Context.advanceCur();
48      Context.advanceNext();
49    }
50  }
51
52  std::string FuncName = Func->getFunctionName().toStringOrEmpty();
53  if (FuncName == "_start")
54    instrumentStart(Func);
55
56  finishFunc(Func);
57}
58
59void Instrumentation::instrumentInst(LoweringContext &Context) {
60  assert(!Context.atEnd());
61  Inst *Instr = iteratorToInst(Context.getCur());
62  switch (Instr->getKind()) {
63  case Inst::Alloca:
64    instrumentAlloca(Context, llvm::cast<InstAlloca>(Instr));
65    break;
66  case Inst::Arithmetic:
67    instrumentArithmetic(Context, llvm::cast<InstArithmetic>(Instr));
68    break;
69  case Inst::Br:
70    instrumentBr(Context, llvm::cast<InstBr>(Instr));
71    break;
72  case Inst::Call:
73    instrumentCall(Context, llvm::cast<InstCall>(Instr));
74    break;
75  case Inst::Cast:
76    instrumentCast(Context, llvm::cast<InstCast>(Instr));
77    break;
78  case Inst::ExtractElement:
79    instrumentExtractElement(Context, llvm::cast<InstExtractElement>(Instr));
80    break;
81  case Inst::Fcmp:
82    instrumentFcmp(Context, llvm::cast<InstFcmp>(Instr));
83    break;
84  case Inst::Icmp:
85    instrumentIcmp(Context, llvm::cast<InstIcmp>(Instr));
86    break;
87  case Inst::InsertElement:
88    instrumentInsertElement(Context, llvm::cast<InstInsertElement>(Instr));
89    break;
90  case Inst::IntrinsicCall:
91    instrumentIntrinsicCall(Context, llvm::cast<InstIntrinsicCall>(Instr));
92    break;
93  case Inst::Load:
94    instrumentLoad(Context, llvm::cast<InstLoad>(Instr));
95    break;
96  case Inst::Phi:
97    instrumentPhi(Context, llvm::cast<InstPhi>(Instr));
98    break;
99  case Inst::Ret:
100    instrumentRet(Context, llvm::cast<InstRet>(Instr));
101    break;
102  case Inst::Select:
103    instrumentSelect(Context, llvm::cast<InstSelect>(Instr));
104    break;
105  case Inst::Store:
106    instrumentStore(Context, llvm::cast<InstStore>(Instr));
107    break;
108  case Inst::Switch:
109    instrumentSwitch(Context, llvm::cast<InstSwitch>(Instr));
110    break;
111  case Inst::Unreachable:
112    instrumentUnreachable(Context, llvm::cast<InstUnreachable>(Instr));
113    break;
114  default:
115    // Only instrument high-level ICE instructions
116    assert(false && "Instrumentation encountered an unexpected instruction");
117    break;
118  }
119}
120
121void Instrumentation::setHasSeenGlobals() {
122  {
123    std::unique_lock<std::mutex> _(GlobalsSeenMutex);
124    HasSeenGlobals = true;
125  }
126  GlobalsSeenCV.notify_all();
127}
128
129LockedPtr<VariableDeclarationList> Instrumentation::getGlobals() {
130  std::unique_lock<std::mutex> GlobalsLock(GlobalsSeenMutex);
131  GlobalsSeenCV.wait(GlobalsLock, [this] { return HasSeenGlobals; });
132  return Ctx->getGlobals();
133}
134
135} // end of namespace Ice
136