Remove building with NOCRYPTO option
[minix.git] / minix / llvm / passes / include / magic / support / MagicDebugFunction.h
blob6f980fe5c689b89b07f7b0955e7a66995c5a9289
1 #ifndef MAGIC_DEBUG_FUNCTION_H_
2 #define MAGIC_DEBUG_FUNCTION_H_
4 #include <pass.h>
6 #define NUM_DEBUG_ARGS 1
8 using namespace llvm;
10 namespace llvm {
12 class MagicDebugFunction {
13 public:
14 MagicDebugFunction(Function *function);
16 Function* getFunction() const;
17 void addHooks(std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs);
18 void fixCalls(Module &M, const std::string &baseDir="");
20 void print(raw_ostream &OS) const;
21 void printDescription(raw_ostream &OS) const;
22 const std::string getDescription() const;
23 static bool inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags, std::vector<unsigned> argsMapping,
24 std::vector<Value*> trailingArgs);
25 Function* getDebugFunction(Module &M);
27 private:
28 Function *function;
30 std::pair<Function*, Function*> hooks;
31 unsigned flags;
32 std::vector<unsigned> argsMapping;
33 std::vector<Value*> trailingArgs;
35 Function* getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType);
38 inline raw_ostream &operator<<(raw_ostream &OS, const MagicDebugFunction &aMagicDebugFunction) {
39 aMagicDebugFunction.print(OS);
40 return OS;
43 inline void MagicDebugFunction::print(raw_ostream &OS) const {
44 OS << getDescription();
47 inline void MagicDebugFunction::printDescription(raw_ostream &OS) const {
48 OS << "[ function = ";
49 OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ") ]";
52 inline const std::string MagicDebugFunction::getDescription() const {
53 std::string string;
54 raw_string_ostream ostream(string);
55 printDescription(ostream);
56 ostream.flush();
57 return string;
60 inline Function* MagicDebugFunction::getDebugClone(Function* function, const Twine wrapperName, TYPECONST Type* debugArgType) {
61 Function* wrapper;
62 std::vector<TYPECONST Type*> ArgTypes;
63 VALUE_TO_VALUE_MAP_TY VMap;
65 // Build arg types for wrapper
66 ArgTypes.push_back(debugArgType);
67 Function::const_arg_iterator E = function->arg_end();
68 for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
69 ArgTypes.push_back(I->getType());
71 // Create a new function type...
72 FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
74 // Create the wrapper
75 wrapper = Function::Create(FTy, function->getLinkage(), wrapperName, function->getParent());
77 // Loop over the arguments, copying the names of the mapped arguments over...
78 Function::arg_iterator DestI = wrapper->arg_begin();
79 Value *magicTypeValue = DestI;
80 magicTypeValue->setName("cs_info");
81 DestI++;
82 for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
83 DestI->setName(I->getName());
84 VMap[I] = DestI++;
87 SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
88 CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
89 return wrapper;
92 inline MagicDebugFunction::MagicDebugFunction(Function *function) {
93 this->function = function;
96 inline void MagicDebugFunction::addHooks(std::pair<Function*, Function*> aHooks, unsigned aFlags, std::vector<unsigned> aArgsMapping,
97 std::vector<Value*> aTrailingArgs) {
98 hooks = aHooks;
99 flags = aFlags;
100 trailingArgs = aTrailingArgs;
101 argsMapping = aArgsMapping;
104 inline Function* MagicDebugFunction::getFunction() const {
105 return function;
108 inline Function* MagicDebugFunction::getDebugFunction(Module &M) {
109 PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
110 Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
111 bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
112 if (ret) {
113 return debugFunction;
114 } else {
115 return NULL;
119 inline void MagicDebugFunction::fixCalls(Module &M, const std::string &baseDir) {
120 PointerType* PointerTy = PointerType::get(IntegerType::get((&M)->getContext(), 8), 0);
121 Function* debugFunction = MagicDebugFunction::getDebugClone(function, "debug_magic_" + function->getName(), PointerTy);
122 bool ret = MagicDebugFunction::inlineHookCalls(debugFunction, hooks, flags, argsMapping, trailingArgs);
123 assert(ret && "Unable to inline the calls to the hook functions.");
125 std::vector<User*> Users(function->user_begin(), function->user_end());
126 std::vector<Value*> EqPointers;
127 while (!Users.empty()) {
128 User *U = Users.back();
129 Users.pop_back();
131 if (Instruction * I = dyn_cast<Instruction>(U)) {
132 CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
133 if (CS.getInstruction()
134 && (MagicUtil::getCalledFunctionFromCS(CS) == function
135 || std::find(EqPointers.begin(), EqPointers.end(), CS.getCalledValue()) != EqPointers.end())) {
136 Function *parentFunction = CS.getInstruction()->getParent()->getParent();
137 StringRef callParentName = MagicUtil::getFunctionSourceName(M, parentFunction, NULL, baseDir);
138 //extend function name with debug information
139 if (MDNode *N = I->getMetadata("dbg")) {
140 DILocation Loc(N);
141 std::string string;
142 raw_string_ostream ostream(string);
143 ostream << callParentName << MAGIC_ALLOC_NAME_SEP << Loc.getFilename() << MAGIC_ALLOC_NAME_SEP << Loc.getLineNumber();
144 ostream.flush();
145 callParentName = string;
147 Value* callParentNameValue = MagicUtil::getArrayPtr(M, MagicUtil::getStringRef(M, callParentName));
148 std::vector<Value*> debugArgs;
149 debugArgs.push_back(callParentNameValue);
150 debugArgs.insert(debugArgs.end(), CS.arg_begin(), CS.arg_end());
151 CallInst* newInst = MagicUtil::createCallInstruction(debugFunction, debugArgs, "", I);
152 newInst->takeName(I);
153 MagicUtil::replaceCallInst(I, newInst, 1);
155 } else if (GlobalValue * GV = dyn_cast<GlobalValue>(U)) {
156 Users.insert(Users.end(), GV->user_begin(), GV->user_end());
157 EqPointers.push_back(GV);
158 } else if (ConstantExpr * CE = dyn_cast<ConstantExpr>(U)) {
159 if (CE->isCast()) {
160 Users.insert(Users.end(), CE->user_begin(), CE->user_end());
161 EqPointers.push_back(CE);
169 // inlines calls to the pre and post hooks and returns true if the inlining succeeded, false otherwise
170 inline bool MagicDebugFunction::inlineHookCalls(Function* function, std::pair<Function*, Function*> hooks, unsigned flags,
171 std::vector<unsigned> argsMapping, std::vector<Value*> trailingArgs) {
172 std::vector<Value*> emptyArgs;
173 std::vector<unsigned> emptyMapping;
174 std::vector<unsigned> debugEmptyMapping;
175 std::vector<unsigned> debugArgsMapping;
177 // debug version of the function, argument mapping has to be adjusted
178 if (flags & MAGIC_HOOK_DEBUG_MASK) {
179 // re-adjusted the index of the arguments (do not re-adjust return value)
180 for (unsigned i = 0; i < argsMapping.size(); i++) {
181 if (argsMapping[i] > 0) {
182 argsMapping[i] += NUM_DEBUG_ARGS;
185 // first come the debug argument
186 for (unsigned i = 1; i <= NUM_DEBUG_ARGS; i++) {
187 debugEmptyMapping.push_back(i);
188 debugArgsMapping.push_back(i);
190 debugArgsMapping.insert(debugArgsMapping.end(), argsMapping.begin(), argsMapping.end());
193 if (hooks.first != NULL) {
194 // inline first hook call at the beginning of the function, according to the flag
195 switch (flags & MAGIC_PRE_HOOK_FLAGS_MASK) {
196 case MAGIC_PRE_HOOK_SIMPLE_CALL:
197 MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
198 emptyArgs);
199 break;
200 case MAGIC_PRE_HOOK_FORWARDING_CALL:
201 MagicUtil::inlinePreHookForwardingCall(function, hooks.first, (flags & MAGIC_PRE_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
202 trailingArgs);
203 break;
204 default:
205 // unknown flag
206 return false;
210 if (hooks.second != NULL) {
211 // inline the second wrapper call at the end of the function, according to the flag
212 switch (flags & MAGIC_POST_HOOK_FLAGS_MASK) {
213 case MAGIC_POST_HOOK_SIMPLE_CALL:
214 MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugEmptyMapping : emptyMapping,
215 emptyArgs);
216 break;
217 case MAGIC_POST_HOOK_FORWARDING_CALL:
218 MagicUtil::inlinePostHookForwardingCall(function, hooks.second, (flags & MAGIC_POST_HOOK_DEBUG) ? debugArgsMapping : argsMapping,
219 trailingArgs);
220 break;
221 default:
222 // unknown flag
223 return false;
227 return true;
230 #endif /* MAGIC_DEBUG_FUNCTION_H_ */