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) ...@@ -283,6 +283,7 @@ SB_LDFLAGS := $(LINKOPTLEVEL) $(LD_EXTRA)
# compile, in the hope of improving parallel build time. # compile, in the hope of improving parallel build time.
SRCS = \ SRCS = \
IceAssemblerARM32.cpp \ IceAssemblerARM32.cpp \
IceInstrumentation.cpp \
IceInstARM32.cpp \ IceInstARM32.cpp \
IceInstMIPS32.cpp \ IceInstMIPS32.cpp \
IceInstX8632.cpp \ IceInstX8632.cpp \
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "IceELFObjectWriter.h" #include "IceELFObjectWriter.h"
#include "IceGlobalInits.h" #include "IceGlobalInits.h"
#include "IceInst.h" #include "IceInst.h"
#include "IceInstrumentation.h"
#include "IceInstVarIter.h" #include "IceInstVarIter.h"
#include "IceLiveness.h" #include "IceLiveness.h"
#include "IceLoopAnalyzer.h" #include "IceLoopAnalyzer.h"
...@@ -238,6 +239,12 @@ void Cfg::translate() { ...@@ -238,6 +239,12 @@ void Cfg::translate() {
if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Var)) if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Var))
Var64On32->initHiLo(this); 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 // The set of translation passes and their order are determined by the
// target. // target.
getTarget()->translate(); getTarget()->translate();
......
...@@ -257,6 +257,11 @@ struct dev_list_flag {}; ...@@ -257,6 +257,11 @@ struct dev_list_flag {};
X(RepeatRegAlloc, bool, dev_opt_flag, "regalloc-repeat", \ X(RepeatRegAlloc, bool, dev_opt_flag, "regalloc-repeat", \
cl::desc("Repeat register allocation until convergence"), cl::init(true)) \ 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", \ X(ShouldDoNopInsertion, bool, dev_opt_flag, "nop-insertion", \
cl::desc("Randomly insert NOPs"), cl::init(false)) \ cl::desc("Randomly insert NOPs"), cl::init(false)) \
\ \
...@@ -357,6 +362,7 @@ struct dev_list_flag {}; ...@@ -357,6 +362,7 @@ struct dev_list_flag {};
X(WasmBoundsCheck, bool, dev_opt_flag, "wasm-bounds-check", \ X(WasmBoundsCheck, bool, dev_opt_flag, "wasm-bounds-check", \
cl::desc("Add bounds checking code in WASM frontend"), \ cl::desc("Add bounds checking code in WASM frontend"), \
cl::init(true)) cl::init(true))
//#define X(Name, Type, ClType, ...) //#define X(Name, Type, ClType, ...)
} // end of namespace Ice } // end of namespace Ice
......
...@@ -241,6 +241,13 @@ void CLCompileServer::run() { ...@@ -241,6 +241,13 @@ void CLCompileServer::run() {
} }
Ctx.reset(new GlobalContext(Ls.get(), Os.get(), Ls.get(), ELFStr.get())); 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) { if (getFlags().getNumTranslationThreads() != 0) {
std::thread CompileThread([this, &Flags, &InputStream]() { std::thread CompileThread([this, &Flags, &InputStream]() {
Ctx->initParserThread(); Ctx->initParserThread();
......
...@@ -486,6 +486,10 @@ void GlobalContext::lowerGlobals(const std::string &SectionSuffix) { ...@@ -486,6 +486,10 @@ void GlobalContext::lowerGlobals(const std::string &SectionSuffix) {
RandomShuffle(Globals.begin(), Globals.end(), RandomShuffle(Globals.begin(), Globals.end(),
[&RNG](int N) { return (uint32_t)RNG.next(N); }); [&RNG](int N) { return (uint32_t)RNG.next(N); });
} }
if (!BuildDefs::minimal() && Instrumentor)
Instrumentor->instrumentGlobals();
DataLowering->lowerGlobals(Globals, SectionSuffix); DataLowering->lowerGlobals(Globals, SectionSuffix);
if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) { if (ProfileBlockInfos.empty() && DisposeGlobalVariablesAfterLowering) {
Globals.clearAndPurge(); Globals.clearAndPurge();
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "IceDefs.h" #include "IceDefs.h"
#include "IceClFlags.h" #include "IceClFlags.h"
#include "IceInstrumentation.h"
#include "IceIntrinsics.h" #include "IceIntrinsics.h"
#include "IceRNG.h" #include "IceRNG.h"
#include "IceStringPool.h" #include "IceStringPool.h"
...@@ -44,6 +45,7 @@ namespace Ice { ...@@ -44,6 +45,7 @@ namespace Ice {
class ConstantPool; class ConstantPool;
class EmitterWorkItem; class EmitterWorkItem;
class FuncSigType; class FuncSigType;
class Instrumentation;
// Runtime helper function IDs // Runtime helper function IDs
...@@ -426,6 +428,17 @@ public: ...@@ -426,6 +428,17 @@ public:
void waitForWorkerThreads(); 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. /// Translation thread startup routine.
void translateFunctionsWrapper(ThreadContext *MyTLS) { void translateFunctionsWrapper(ThreadContext *MyTLS) {
ICE_TLS_SET_FIELD(TLS, MyTLS); ICE_TLS_SET_FIELD(TLS, MyTLS);
...@@ -552,6 +565,9 @@ private: ...@@ -552,6 +565,9 @@ private:
/// program global variables) until the first code WorkItem is seen. /// program global variables) until the first code WorkItem is seen.
// TODO(jpp): move to EmitterContext. // TODO(jpp): move to EmitterContext.
bool HasSeenCode = false; 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. // TODO(jpp): move to EmitterContext.
VariableDeclaration *ProfileBlockInfoVarDecl = nullptr; VariableDeclaration *ProfileBlockInfoVarDecl = nullptr;
std::vector<VariableDeclaration *> ProfileBlockInfos; 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