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