| //===- subzero/src/IceInstrumentation.cpp - ICE instrumentation framework -===// | 
 | // | 
 | //                        The Subzero Code Generator | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | /// | 
 | /// \file | 
 | /// \brief Implements the Ice::Instrumentation class. | 
 | /// | 
 | /// Subclasses can override particular instrumentation methods to specify how | 
 | /// the the target program should be instrumented. | 
 | /// | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "IceInstrumentation.h" | 
 |  | 
 | #include "IceCfg.h" | 
 | #include "IceInst.h" | 
 | #include "IceTargetLowering.h" | 
 |  | 
 | namespace Ice { | 
 |  | 
 | // Iterate through the instructions in the given CFG and instrument each one. | 
 | // Also instrument the beginning of the function. | 
 | void Instrumentation::instrumentFunc(Cfg *Func) { | 
 |   assert(Func); | 
 |   assert(!Func->getNodes().empty()); | 
 |  | 
 |   if (!isInstrumentable(Func)) | 
 |     return; | 
 |  | 
 |   bool DidInstrumentEntry = false; | 
 |   LoweringContext Context; | 
 |   Context.init(Func->getNodes().front()); | 
 |   for (CfgNode *Node : Func->getNodes()) { | 
 |     Context.init(Node); | 
 |     while (!Context.atEnd()) { | 
 |       if (!DidInstrumentEntry) { | 
 |         instrumentFuncStart(Context); | 
 |         DidInstrumentEntry = true; | 
 |       } | 
 |       instrumentInst(Context); | 
 |       // go to next undeleted instruction | 
 |       Context.advanceCur(); | 
 |       Context.advanceNext(); | 
 |     } | 
 |   } | 
 |  | 
 |   std::string FuncName = Func->getFunctionName().toStringOrEmpty(); | 
 |   if (FuncName == "_start") | 
 |     instrumentStart(Func); | 
 |  | 
 |   finishFunc(Func); | 
 | } | 
 |  | 
 | void Instrumentation::instrumentInst(LoweringContext &Context) { | 
 |   assert(!Context.atEnd()); | 
 |   Inst *Instr = iteratorToInst(Context.getCur()); | 
 |   switch (Instr->getKind()) { | 
 |   case Inst::Alloca: | 
 |     instrumentAlloca(Context, llvm::cast<InstAlloca>(Instr)); | 
 |     break; | 
 |   case Inst::Arithmetic: | 
 |     instrumentArithmetic(Context, llvm::cast<InstArithmetic>(Instr)); | 
 |     break; | 
 |   case Inst::Br: | 
 |     instrumentBr(Context, llvm::cast<InstBr>(Instr)); | 
 |     break; | 
 |   case Inst::Call: | 
 |     instrumentCall(Context, llvm::cast<InstCall>(Instr)); | 
 |     break; | 
 |   case Inst::Cast: | 
 |     instrumentCast(Context, llvm::cast<InstCast>(Instr)); | 
 |     break; | 
 |   case Inst::ExtractElement: | 
 |     instrumentExtractElement(Context, llvm::cast<InstExtractElement>(Instr)); | 
 |     break; | 
 |   case Inst::Fcmp: | 
 |     instrumentFcmp(Context, llvm::cast<InstFcmp>(Instr)); | 
 |     break; | 
 |   case Inst::Icmp: | 
 |     instrumentIcmp(Context, llvm::cast<InstIcmp>(Instr)); | 
 |     break; | 
 |   case Inst::InsertElement: | 
 |     instrumentInsertElement(Context, llvm::cast<InstInsertElement>(Instr)); | 
 |     break; | 
 |   case Inst::IntrinsicCall: | 
 |     instrumentIntrinsicCall(Context, llvm::cast<InstIntrinsicCall>(Instr)); | 
 |     break; | 
 |   case Inst::Load: | 
 |     instrumentLoad(Context, llvm::cast<InstLoad>(Instr)); | 
 |     break; | 
 |   case Inst::Phi: | 
 |     instrumentPhi(Context, llvm::cast<InstPhi>(Instr)); | 
 |     break; | 
 |   case Inst::Ret: | 
 |     instrumentRet(Context, llvm::cast<InstRet>(Instr)); | 
 |     break; | 
 |   case Inst::Select: | 
 |     instrumentSelect(Context, llvm::cast<InstSelect>(Instr)); | 
 |     break; | 
 |   case Inst::Store: | 
 |     instrumentStore(Context, llvm::cast<InstStore>(Instr)); | 
 |     break; | 
 |   case Inst::Switch: | 
 |     instrumentSwitch(Context, llvm::cast<InstSwitch>(Instr)); | 
 |     break; | 
 |   case Inst::Unreachable: | 
 |     instrumentUnreachable(Context, llvm::cast<InstUnreachable>(Instr)); | 
 |     break; | 
 |   default: | 
 |     // Only instrument high-level ICE instructions | 
 |     assert(false && "Instrumentation encountered an unexpected instruction"); | 
 |     break; | 
 |   } | 
 | } | 
 |  | 
 | void Instrumentation::setHasSeenGlobals() { | 
 |   { | 
 |     std::unique_lock<std::mutex> _(GlobalsSeenMutex); | 
 |     HasSeenGlobals = true; | 
 |   } | 
 |   GlobalsSeenCV.notify_all(); | 
 | } | 
 |  | 
 | LockedPtr<VariableDeclarationList> Instrumentation::getGlobals() { | 
 |   std::unique_lock<std::mutex> GlobalsLock(GlobalsSeenMutex); | 
 |   GlobalsSeenCV.wait(GlobalsLock, [this] { return HasSeenGlobals; }); | 
 |   return Ctx->getGlobals(); | 
 | } | 
 |  | 
 | } // end of namespace Ice |