]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AVR/AVRInstrumentFunctions.cpp
Update lldb to trunk r290819 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AVR / AVRInstrumentFunctions.cpp
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
35   const StringRef PREFIX = SYMBOL_PREFIX;
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) {
50     initializeAVRInstrumentFunctionsPass(*PassRegistry::getPassRegistry());
51   }
52
53   bool runOnFunction(Function &F) override;
54
55   StringRef getPassName() const override { return AVR_INSTRUMENT_FUNCTIONS_NAME; }
56 };
57
58 char AVRInstrumentFunctions::ID = 0;
59
60 /// Creates a pointer to a string.
61 static Value *CreateStringPtr(BasicBlock &BB, StringRef Str) {
62   LLVMContext &Ctx = BB.getContext();
63   IntegerType *I8 = Type::getInt8Ty(Ctx);
64
65   Constant *ConstantStr = ConstantDataArray::getString(Ctx, Str);
66   GlobalVariable *GlobalStr = new GlobalVariable(*BB.getParent()->getParent(),
67                                                  ConstantStr->getType(),
68                                                  true, /* is a constant */
69                                                  GlobalValue::PrivateLinkage,
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();
90   IntegerType *I16 = Type::getInt16Ty(Ctx);
91
92   FunctionType *FnType = FunctionType::get(Type::getVoidTy(Ctx),
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
128   FunctionType *FnType = FunctionType::get(Type::getVoidTy(Ctx),
129     {Type::getInt8PtrTy(Ctx), I8, Arg.getType()}, false);
130
131   Constant *Fn = F.getParent()->getOrInsertFunction(
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.
151   BasicBlock *BB = BasicBlock::Create(F.getContext(),
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
173     FunctionType *FnType = FunctionType::get(Type::getVoidTy(Ctx),
174       {RetVal->getType()}, false);
175
176     Constant *Fn = F.getParent()->getOrInsertFunction(
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