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