Commit aab7099e by Thomas Lively

Created Ice::Instrumentation base class and accompanying hooks.

Also added a command line flag for AddressSanitizer BUG=None R=kschimpf@google.com Review URL: https://codereview.chromium.org/2042063002 .
parent 418135a9
......@@ -283,6 +283,7 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
# compile, in the hope of improving parallel build time.
SRCS = \
IceAssemblerARM32.cpp \
IceInstrumentation.cpp \
IceInstARM32.cpp \
IceInstMIPS32.cpp \
IceInstX8632.cpp \
......
......@@ -22,6 +22,7 @@
#include "IceELFObjectWriter.h"
#include "IceGlobalInits.h"
#include "IceInst.h"
#include "IceInstrumentation.h"
#include "IceInstVarIter.h"
#include "IceLiveness.h"
#include "IceLoopAnalyzer.h"
......@@ -238,6 +239,12 @@ void Cfg::translate() {
if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Var))
Var64On32->initHiLo(this);
// Instrument the Cfg, e.g. with AddressSanitizer
if (!BuildDefs::minimal() && getFlags().getSanitizeAddresses()) {
getContext()->instrumentFunc(this);
dump("Instrumented CFG");
}
// The set of translation passes and their order are determined by the
// target.
getTarget()->translate();
......
......@@ -257,6 +257,11 @@ struct dev_list_flag {};
X(RepeatRegAlloc, bool, dev_opt_flag, "regalloc-repeat", \
cl::desc("Repeat register allocation until convergence"), cl::init(true)) \
\
/* TODO(tlively): Generalize this to handle more sanitizers */ \
X(SanitizeAddresses, bool, dev_opt_flag, "fsanitize-address", \
cl::desc("Instrument compiled code with Address Sanitizer"), \
cl::init(false)) \
\
X(ShouldDoNopInsertion, bool, dev_opt_flag, "nop-insertion", \
cl::desc("Randomly insert NOPs"), cl::init(false)) \
\
......@@ -357,6 +362,7 @@ struct dev_list_flag {};
X(WasmBoundsCheck, bool, dev_opt_flag, "wasm-bounds-check", \
cl::desc("Add bounds checking code in WASM frontend"), \
cl::init(true))
//#define X(Name, Type, ClType, ...)
} // end of namespace Ice
......
......@@ -241,6 +241,13 @@ void CLCompileServer::run() {
}
Ctx.reset(new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get()));
// TODO(tlively): Make this instantiate an instrumentation subclass
if (!BuildDefs::minimal() && getFlags().getSanitizeAddresses()) {
std::unique_ptr<Instrumentation> Instr(new Instrumentation(Ctx.get()));
Ctx->setInstrumentation(std::move(Instr));
}
if (getFlags().getNumTranslationThreads() != 0) {
std::thread CompileThread([this, &Flags, &InputStream]() {
Ctx->initParserThread();
......
......@@ -486,6 +486,10 @@ void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
RandomShuffle(Globals.begin(), Globals.end(),
[&RNG](int N) { return (uint32_t)RNG.next(N); });
}
if (!BuildDefs::minimal() && Instrumentor)
Instrumentor->instrumentGlobals();
DataLowering->lowerGlobals(Globals, SectionSuffix);
if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
Globals.clearAndPurge();
......
......@@ -18,6 +18,7 @@
#include "IceDefs.h"
#include "IceClFlags.h"
#include "IceInstrumentation.h"
#include "IceIntrinsics.h"
#include "IceRNG.h"
#include "IceStringPool.h"
......@@ -44,6 +45,7 @@ namespace Ice {
class ConstantPool;
class EmitterWorkItem;
class FuncSigType;
class Instrumentation;
// Runtime helper function IDs
......@@ -426,6 +428,17 @@ public:
void waitForWorkerThreads();
/// sets the instrumentation object to use.
void setInstrumentation(std::unique_ptr<Instrumentation> Instr) {
if (!BuildDefs::minimal())
Instrumentor = std::move(Instr);
}
void instrumentFunc(Cfg *Func) {
if (!BuildDefs::minimal() && Instrumentor)
Instrumentor->instrumentFunc(Func);
}
/// Translation thread startup routine.
void translateFunctionsWrapper(ThreadContext *MyTLS) {
ICE_TLS_SET_FIELD(TLS, MyTLS);
......@@ -552,6 +565,9 @@ private:
/// program global variables) until the first code WorkItem is seen.
// TODO(jpp): move to EmitterContext.
bool HasSeenCode = false;
// If Instrumentor is not empty then it will be used to instrument globals and
// CFGs.
std::unique_ptr<Instrumentation> Instrumentor = nullptr;
// TODO(jpp): move to EmitterContext.
VariableDeclaration *ProfileBlockInfoVarDecl = nullptr;
std::vector<VariableDeclaration *> ProfileBlockInfos;
......
//===- 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());
LoweringContext Context;
Context.init(Func->getNodes().front());
instrumentFuncStart(Context);
for (CfgNode *Node : Func->getNodes()) {
Context.init(Node);
while (!Context.atEnd()) {
instrumentInst(Context);
// go to next undeleted instruction
Context.advanceCur();
Context.advanceNext();
}
}
}
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;
}
}
} // end of namespace Ice
//===- subzero/src/IceInstrumentation.h - ICE instrumentation ---*- C++ -*-===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Declares the Ice::Instrumentation class.
///
/// Instrumentation is an abstract class used to drive the instrumentation
/// process for tools such as AddressSanitizer and MemorySanitizer. It uses a
/// LoweringContext to enable the insertion of new instructions into a given
/// Cfg. Although Instrumentation is an abstract class, each of its virtual
/// functions has a trivial default implementation to make subclasses more
/// succinct.
///
/// If instrumentation is required by the command line arguments, a single
/// Instrumentation subclass is instantiated and installed in the
/// GlobalContext. If multiple types of instrumentation are requested, a single
/// subclass is still responsible for driving the instrumentation, but it can
/// use other Instrumentation subclasses however it needs to.
///
//===----------------------------------------------------------------------===//
#ifndef SUBZERO_SRC_ICEINSTRUMENTATION_H
#define SUBZERO_SRC_ICEINSTRUMENTATION_H
#include "IceDefs.h"
namespace Ice {
class LoweringContext;
class Instrumentation {
Instrumentation() = delete;
Instrumentation(const Instrumentation &) = delete;
Instrumentation &operator=(const Instrumentation &) = delete;
public:
Instrumentation(GlobalContext *Ctx) : Ctx(Ctx) {}
virtual void instrumentGlobals() {};
void instrumentFunc(Cfg *Func);
private:
void instrumentInst(LoweringContext &Context);
virtual void instrumentFuncStart(LoweringContext &Context) {
(void) Context;
}
virtual void instrumentAlloca(LoweringContext &Context,
const class InstAlloca *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentArithmetic(LoweringContext &Context,
const class InstArithmetic *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentBr(LoweringContext &Context,
const class InstBr *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentCall(LoweringContext &Context,
const class InstCall *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentCast(LoweringContext &Context,
const class InstCast *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentExtractElement(LoweringContext &Context,
const class InstExtractElement *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentFcmp(LoweringContext &Context,
const class InstFcmp *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentIcmp(LoweringContext &Context,
const class InstIcmp *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentInsertElement(LoweringContext &Context,
const class InstInsertElement *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentIntrinsicCall(LoweringContext &Context,
const class InstIntrinsicCall *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentLoad(LoweringContext &Context,
const class InstLoad *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentPhi(LoweringContext &Context,
const class InstPhi *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentRet(LoweringContext &Context,
const class InstRet *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentSelect(LoweringContext &Context,
const class InstSelect *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentStore(LoweringContext &Context,
const class InstStore *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentSwitch(LoweringContext &Context,
const class InstSwitch *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentUnreachable(LoweringContext &Context,
const class InstUnreachable *Instr) {
(void) Context;
(void) Instr;
}
virtual void instrumentLocalVars(Cfg *Func) {
(void) Func;
}
protected:
GlobalContext *Ctx;
};
} // end of namespace Ice
#endif // SUBZERO_SRC_ICEINSTRUMENTATION_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment