LLVM  4.0.0
AVRInstrumentFunctions.cpp
Go to the documentation of this file.
1 //===-- AVRInstrumentFunctions.cpp - Insert instrumentation for testing ---===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass takes a function and inserts calls to hook functions which are
11 // told the name, arguments, and results of function calls.
12 //
13 // The hooks can do anything with the information given. It is possible to
14 // send the data through a serial connection in order to runs tests on
15 // bare metal.
16 //
17 //===----------------------------------------------------------------------===//
18 
19 #include "AVR.h"
20 
21 #include <llvm/IR/Function.h>
22 #include <llvm/IR/Module.h>
23 
24 using namespace llvm;
25 
26 #define AVR_INSTRUMENT_FUNCTIONS_NAME "AVR function instrumentation pass"
27 
28 namespace {
29 
30 // External symbols that we emit calls to.
31 namespace symbols {
32 
33 #define SYMBOL_PREFIX "avr_instrumentation"
34 
36 
37  // void (i16 argCount);
38  const StringRef BEGIN_FUNCTION_SIGNATURE = SYMBOL_PREFIX "_begin_signature";
39  // void(i16 argCount);
40  const StringRef END_FUNCTION_SIGNATURE = SYMBOL_PREFIX "_end_signature";
41 
42 #undef SYMBOL_PREFIX
43 }
44 
45 class AVRInstrumentFunctions : public FunctionPass {
46 public:
47  static char ID;
48 
49  AVRInstrumentFunctions() : FunctionPass(ID) {
51  }
52 
53  bool runOnFunction(Function &F) override;
54 
55  StringRef getPassName() const override { return AVR_INSTRUMENT_FUNCTIONS_NAME; }
56 };
57 
59 
60 /// Creates a pointer to a string.
61 static Value *CreateStringPtr(BasicBlock &BB, StringRef Str) {
62  LLVMContext &Ctx = BB.getContext();
64 
65  Constant *ConstantStr = ConstantDataArray::getString(Ctx, Str);
66  GlobalVariable *GlobalStr = new GlobalVariable(*BB.getParent()->getParent(),
67  ConstantStr->getType(),
68  true, /* is a constant */
70  ConstantStr);
71  return GetElementPtrInst::CreateInBounds(GlobalStr,
72  {ConstantInt::get(I8, 0), ConstantInt::get(I8, 0)}, "", &BB);
73 }
74 
75 static std::string GetTypeName(Type &Ty) {
76  if (auto *IntTy = dyn_cast<IntegerType>(&Ty)) {
77  return std::string("i") + std::to_string(IntTy->getBitWidth());
78  }
79 
80  if (Ty.isFloatingPointTy()) {
81  return std::string("f") + std::to_string(Ty.getPrimitiveSizeInBits());
82  }
83 
84  llvm_unreachable("unknown return type");
85 }
86 
87 /// Builds a call to one of the signature begin/end hooks.
88 static void BuildSignatureCall(StringRef SymName, BasicBlock &BB, Function &F) {
89  LLVMContext &Ctx = F.getContext();
91 
93  {Type::getInt8PtrTy(Ctx), I16}, false);
94 
95  Constant *Fn = F.getParent()->getOrInsertFunction(SymName, FnType);
96  Value *FunctionName = CreateStringPtr(BB, F.getName());
97 
98  Value *Args[] = {FunctionName,
99  ConstantInt::get(I16, F.getArgumentList().size())};
100  CallInst::Create(Fn, Args, "", &BB);
101 }
102 
103 /// Builds instructions to call into an external function to
104 /// notify about a function signature beginning.
105 static void BuildBeginSignature(BasicBlock &BB, Function &F) {
106  return BuildSignatureCall(symbols::BEGIN_FUNCTION_SIGNATURE, BB, F);
107 }
108 
109 /// Builds instructions to call into an external function to
110 /// notify about a function signature ending.
111 static void BuildEndSignature(BasicBlock &BB, Function &F) {
112  return BuildSignatureCall(symbols::END_FUNCTION_SIGNATURE, BB, F);
113 }
114 
115 /// Get the name of the external symbol that we need to call
116 /// to notify about this argument.
117 static std::string GetArgumentSymbolName(Argument &Arg) {
118  return (symbols::PREFIX + "_argument_" + GetTypeName(*Arg.getType())).str();
119 }
120 
121 /// Builds a call to one of the argument hooks.
122 static void BuildArgument(BasicBlock &BB, Argument &Arg) {
123  Function &F = *Arg.getParent();
124  LLVMContext &Ctx = F.getContext();
125 
126  Type *I8 = Type::getInt8Ty(Ctx);
127 
129  {Type::getInt8PtrTy(Ctx), I8, Arg.getType()}, false);
130 
132  GetArgumentSymbolName(Arg), FnType);
133  Value *ArgName = CreateStringPtr(BB, Arg.getName());
134 
135  Value *Args[] = {ArgName, ConstantInt::get(I8, Arg.getArgNo()), &Arg};
136  CallInst::Create(Fn, Args, "", &BB);
137 }
138 
139 /// Builds a call to all of the function signature hooks.
140 static void BuildSignature(BasicBlock &BB, Function &F) {
141  BuildBeginSignature(BB, F);
142  for (Argument &Arg : F.args()) { BuildArgument(BB, Arg); }
143  BuildEndSignature(BB, F);
144 }
145 
146 /// Builds the instrumentation entry block.
147 static void BuildEntryBlock(Function &F) {
148  BasicBlock &EntryBlock = F.getEntryBlock();
149 
150  // Create a new basic block at the start of the existing entry block.
152  "instrumentation_entry",
153  &F, &EntryBlock);
154 
155  BuildSignature(*BB, F);
156 
157  // Jump to the actual entry block.
158  BranchInst::Create(&EntryBlock, BB);
159 }
160 
161 static std::string GetReturnSymbolName(Value &Val) {
162  return (symbols::PREFIX + "_result_" + GetTypeName(*Val.getType())).str();
163 }
164 
165 static void BuildExitHook(Instruction &I) {
166  Function &F = *I.getParent()->getParent();
167  LLVMContext &Ctx = F.getContext();
168 
169  if (auto *Ret = dyn_cast<ReturnInst>(&I)) {
170  Value *RetVal = Ret->getReturnValue();
171  assert(RetVal && "should only be instrumenting functions with return values");
172 
174  {RetVal->getType()}, false);
175 
177  GetReturnSymbolName(*RetVal), FnType);
178 
179  // Call the result hook just before the return.
180  CallInst::Create(Fn, {RetVal}, "", &I);
181  }
182 }
183 
184 /// Runs return hooks before all returns in a function.
185 static void BuildExitHooks(Function &F) {
186  for (BasicBlock &BB : F) {
187  auto BBI = BB.begin(), E = BB.end();
188  while (BBI != E) {
189  auto NBBI = std::next(BBI);
190 
191  BuildExitHook(*BBI);
192 
193  // Modified |= expandMI(BB, MBBI);
194  BBI = NBBI;
195  }
196  }
197 }
198 
199 static bool ShouldInstrument(Function &F) {
200  // No point reporting results if there are none.
201  return !F.getReturnType()->isVoidTy();
202 }
203 
204 bool AVRInstrumentFunctions::runOnFunction(Function &F) {
205  if (ShouldInstrument(F)) {
206  BuildEntryBlock(F);
207  BuildExitHooks(F);
208  }
209 
210  return true;
211 }
212 
213 } // end of anonymous namespace
214 
215 INITIALIZE_PASS(AVRInstrumentFunctions, "avr-instrument-functions",
216  AVR_INSTRUMENT_FUNCTIONS_NAME, false, false)
217 
218 namespace llvm {
219 
220 FunctionPass *createAVRInstrumentFunctionsPass() { return new AVRInstrumentFunctions(); }
221 
222 } // end of namespace llvm
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
Definition: Constants.cpp:2471
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:226
LLVM Argument representation.
Definition: Argument.h:34
#define SYMBOL_PREFIX
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:57
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.cpp:238
const Function * getParent() const
Return the enclosing method, or null if none.
Definition: BasicBlock.h:100
static IntegerType * getInt16Ty(LLVMContext &C)
Definition: Type.cpp:168
#define PREFIX(NAME, VALUE)
Definition: LibDriver.cpp:38
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:191
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:228
Class to represent function types.
Definition: DerivedTypes.h:102
static GetElementPtrInst * CreateInBounds(Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Create an "inbounds" getelementptr.
Definition: Instructions.h:891
#define F(x, y, z)
Definition: MD5.cpp:51
INITIALIZE_PASS(AVRInstrumentFunctions,"avr-instrument-functions", AVR_INSTRUMENT_FUNCTIONS_NAME, false, false) namespace llvm
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:291
bool isFloatingPointTy() const
Return true if this is one of the six floating-point types.
Definition: Type.h:160
void initializeAVRInstrumentFunctionsPass(PassRegistry &)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
Definition: Module.cpp:123
LLVM Basic Block Representation.
Definition: BasicBlock.h:51
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:48
const Function * getParent() const
Definition: Argument.h:48
This is an important base class in LLVM.
Definition: Constant.h:42
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:154
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:93
Class to represent integer types.
Definition: DerivedTypes.h:39
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:213
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
iterator end()
Definition: BasicBlock.h:230
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:230
FunctionPass * createAVRInstrumentFunctionsPass()
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:558
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
const BasicBlock & getEntryBlock() const
Definition: Function.h:519
#define AVR_INSTRUMENT_FUNCTIONS_NAME
#define I(x, y, z)
Definition: MD5.cpp:54
const std::string to_string(const T &Value)
Definition: ScopedPrinter.h:62
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVMContext & getContext() const
Get the context in which this basic block lives.
Definition: BasicBlock.cpp:33
unsigned getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition: Type.cpp:108
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:537
LLVM Value Representation.
Definition: Value.h:71
const ArgumentListType & getArgumentList() const
Get the underlying elements of the Function...
Definition: Function.h:499
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Definition: Function.cpp:57
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
static IntegerType * getInt8Ty(LLVMContext &C)
Definition: Type.cpp:167
const BasicBlock * getParent() const
Definition: Instruction.h:62
iterator_range< arg_iterator > args()
Definition: Function.h:568
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139