|  | //===- 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 |