Remove building with NOCRYPTO option
[minix.git] / minix / llvm / passes / include / magic / support / MagicMemFunction.h
blob0916841746043b29607a555686ec9a21b9c11bc3
1 #ifndef MAGIC_MEM_FUNCTION_H
2 #define MAGIC_MEM_FUNCTION_H
4 #include <pass.h>
5 #include <magic/support/TypeInfo.h>
7 #define NUM_MAGIC_ARGS 3
9 using namespace llvm;
11 namespace llvm {
13 class MagicMemFunction {
14 public:
15 MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, bool isNested, int allocFlags);
17 Function* getFunction() const;
18 Function* getWrapper() const;
19 bool isDeallocFunction() const;
20 bool isNestedFunction() const;
21 int getAllocFlags() const;
22 Instruction* getInstruction() const;
23 Function* getInstructionParent() const;
24 TypeInfo* getInstructionTypeInfo() const;
25 Value* getInstructionTypeValue() const;
26 bool hasInstructionType() const;
27 std::vector<MagicMemFunction> getInstructionDeps() const;
29 void setInstruction(Instruction* I);
30 void setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName);
31 void setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue);
32 void addInstructionDep(MagicMemFunction &function);
33 void replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
35 void print(raw_ostream &OS) const;
36 void printDescription(raw_ostream &OS) const;
37 const std::string getDescription() const;
39 static int getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo);
40 static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
41 bool isDealloc);
42 static bool isCustomWrapper(Function *function);
44 private:
45 Module *module;
46 Function *function;
47 Function *wrapper;
48 bool isDealloc;
49 bool isNested;
50 int allocFlags;
51 Instruction *instruction;
52 TypeInfo* aTypeInfo;
53 std::string allocName;
54 std::string allocParentName;
55 Value* typeValue;
56 Value* allocNameValue;
57 Value* allocParentNameValue;
58 std::vector<MagicMemFunction> instructionDeps;
60 void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
62 static Function *lastAllocWrapper;
63 static std::map<std::string, Function*> allocWrapperCache;
64 static std::set<Function*> customWrapperSet;
67 inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
68 aMagicMemFunction.print(OS);
69 return OS;
72 inline void MagicMemFunction::print(raw_ostream &OS) const {
73 OS << getDescription();
76 inline void MagicMemFunction::printDescription(raw_ostream &OS) const {
77 OS << "[ function = ";
78 OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")";
79 OS << ", wrapper = ";
80 if (wrapper) {
81 OS << wrapper->getName() << "(" << TypeUtil::getDescription(wrapper->getFunctionType()) << ")";
82 } else
83 OS << "NULL";
84 OS << ", isDeallocFunction = ";
85 OS << isDealloc;
86 OS << ", isNestedFunction = ";
87 OS << isNested;
88 OS << ", instruction = ";
89 if (instruction)
90 instruction->print(OS);
91 else
92 OS << "NULL";
93 OS << ", typeInfo = ";
94 if (aTypeInfo)
95 OS << aTypeInfo->getDescription();
96 else
97 OS << "NULL";
98 OS << ", allocName = ";
99 OS << allocName;
100 OS << ", allocParentName = ";
101 OS << allocParentName;
102 OS << ", typeValue = ";
103 if (typeValue)
104 typeValue->print(OS);
105 else
106 OS << "NULL";
107 OS << ", allocNameValue = ";
108 if (allocNameValue)
109 allocNameValue->print(OS);
110 else
111 OS << "NULL";
112 OS << ", allocParentNameValue = ";
113 if (allocParentNameValue)
114 allocParentNameValue->print(OS);
115 else
116 OS << "NULL";
117 OS << ", instructionDeps = {";
118 for (unsigned i = 0; i < instructionDeps.size(); i++) {
119 if (i > 0) {
120 OS << ", ";
122 instructionDeps[i].print(OS);
124 OS << "}]";
127 inline const std::string MagicMemFunction::getDescription() const {
128 std::string string;
129 raw_string_ostream ostream(string);
130 printDescription(ostream);
131 ostream.flush();
132 return string;
135 inline MagicMemFunction::MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, bool isNested, int allocFlags) {
136 this->module = &M;
137 this->function = function;
138 this->wrapper = wrapper;
139 this->isDealloc = isDealloc;
140 this->isNested = isNested;
141 this->allocFlags = allocFlags;
142 this->instruction = NULL;
143 this->aTypeInfo = NULL;
144 this->allocName = "";
145 this->allocParentName = "";
146 this->typeValue = NULL;
147 this->allocNameValue = NULL;
148 this->allocParentNameValue = NULL;
149 assert(function);
150 if (wrapper && !isDealloc && !isNested) {
151 lastAllocWrapper = wrapper;
153 if (isDealloc) {
154 assert(!allocFlags);
158 inline Function* MagicMemFunction::getFunction() const {
159 return function;
162 inline Function* MagicMemFunction::getWrapper() const {
163 return wrapper;
166 inline bool MagicMemFunction::isDeallocFunction() const {
167 return isDealloc;
170 inline bool MagicMemFunction::isNestedFunction() const {
171 return isNested;
174 inline int MagicMemFunction::getAllocFlags() const {
175 return allocFlags;
178 inline Instruction* MagicMemFunction::getInstruction() const {
179 return instruction;
182 inline Function* MagicMemFunction::getInstructionParent() const {
183 if (!instruction) {
184 return NULL;
186 return instruction->getParent()->getParent();
189 inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
190 return aTypeInfo;
193 inline Value* MagicMemFunction::getInstructionTypeValue() const {
194 return typeValue;
197 inline bool MagicMemFunction::hasInstructionType() const {
198 return aTypeInfo || typeValue;
201 inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
202 return instructionDeps;
205 inline void MagicMemFunction::setInstruction(Instruction* I) {
206 this->instruction = I;
207 assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
210 inline void MagicMemFunction::setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName) {
211 this->aTypeInfo = aTypeInfo;
212 this->allocName = allocName;
213 this->allocParentName = allocParentName;
216 inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
217 this->typeValue = typeValue;
218 this->allocNameValue = allocNameValue;
219 this->allocParentNameValue = allocParentNameValue;
222 inline void MagicMemFunction::addInstructionDep(MagicMemFunction &function) {
223 assert(wrapper == NULL && "Dependencies are resolved at wrapper building time, so wrapper has to be NULL!");
224 instructionDeps.push_back(function);
225 allocFlags |= function.getAllocFlags();
228 inline void MagicMemFunction::replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
229 Instruction *I = getInstruction();
230 assert(I);
231 CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
232 std::vector<Value*> magicMemArgs;
233 unsigned numMagicArgs = 0;
234 //if we do not have a wrapper, build one
235 if (!wrapper) {
236 buildWrapper(magicArrayTypePtrMap, voidPtrTypeInfo);
238 //inject magic args
239 if (!isDeallocFunction() && !isNestedFunction()) {
240 std::map<TypeInfo*, Constant*>::iterator it;
241 if (!typeValue) {
242 assert(aTypeInfo);
243 if (aTypeInfo == voidPtrTypeInfo->getContainedType(0)) {
244 typeValue = ConstantPointerNull::get((TYPECONST PointerType*) (wrapper->arg_begin()->getType()));
245 } else {
246 it = magicArrayTypePtrMap.find(aTypeInfo);
247 assert(it != magicArrayTypePtrMap.end());
248 typeValue = it->second;
250 assert(allocName.compare(""));
251 assert(allocParentName.compare(""));
252 allocNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocName));
253 allocParentNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocParentName));
255 magicMemArgs.push_back(typeValue);
256 magicMemArgs.push_back(allocNameValue);
257 magicMemArgs.push_back(allocParentNameValue);
258 numMagicArgs = NUM_MAGIC_ARGS;
260 //push other args
261 unsigned arg_size = MagicUtil::getCalledFunctionFromCS(CS)->getFunctionType()->getNumContainedTypes() - 1;
262 for (unsigned i = 0; i < arg_size; i++) {
263 Value *arg = CS.getArgument(i);
264 TYPECONST Type* wArgType = wrapper->getFunctionType()->getContainedType(i + numMagicArgs + 1);
265 if (arg->getType() != wArgType) {
266 if (arg->getType()->isPointerTy()) {
267 assert(wArgType->isPointerTy());
268 arg = CastInst::CreatePointerCast(arg, wArgType, "WrapperCast", I);
270 else {
271 assert(arg->getType()->isIntegerTy());
272 assert(wArgType->isIntegerTy());
273 arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
276 magicMemArgs.push_back(arg);
278 //replace function with wrapper
279 CallInst* newInst = MagicUtil::createCallInstruction(wrapper, magicMemArgs, "", I);
280 newInst->takeName(I);
281 MagicUtil::replaceCallInst(I, newInst, NUM_MAGIC_ARGS);
284 inline int MagicMemFunction::getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo) {
285 TYPECONST Type *type = function->getReturnType();
286 if (type == voidPtrTypeInfo->getType()) {
287 return 0;
288 } else if (brkFunctions.find(function) != brkFunctions.end()) {
289 return 1;
290 } else {
291 unsigned i;
292 for (i = 1; i < function->getFunctionType()->getNumContainedTypes(); i++) {
293 type = function->getFunctionType()->getContainedType(i);
294 if (type->isPointerTy() && type->getContainedType(0) == voidPtrTypeInfo->getType()) {
295 return i;
300 return -1;
303 inline void MagicMemFunction::buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
304 assert(!isDeallocFunction());
305 assert(!isNestedFunction());
306 assert(lastAllocWrapper);
307 std::vector<TYPECONST Type*> ArgTypes;
308 VALUE_TO_VALUE_MAP_TY VMap;
310 std::map<std::string, Function*>::iterator allocWrapperCacheIt;
312 // See if the wrapper is in cache, otherwise create a new wrapper using function cloning
313 allocWrapperCacheIt = allocWrapperCache.find(function->getName());
314 if (allocWrapperCacheIt != allocWrapperCache.end()) {
315 wrapper = allocWrapperCacheIt->second;
316 return;
319 // Build arg types for wrapper
320 Function::const_arg_iterator E = lastAllocWrapper->arg_begin();
321 for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
322 E++;
323 for (Function::const_arg_iterator I = lastAllocWrapper->arg_begin(); I != E; ++I)
324 ArgTypes.push_back(I->getType());
325 E = function->arg_end();
326 for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
327 ArgTypes.push_back(I->getType());
329 // Create a new function type...
330 FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
332 // Create the wrapper
333 wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
335 // Loop over the arguments, copying the names of the mapped arguments over...
336 Function::arg_iterator DestI = wrapper->arg_begin();
337 Value *magicTypeValue = DestI;
338 magicTypeValue->setName("magic_type");
339 DestI++;
340 Value *magicNameValue = DestI;
341 magicNameValue->setName("magic_name");
342 DestI++;
343 Value *magicParentNameValue = DestI;
344 magicParentNameValue->setName("magic_parent_name");
345 DestI++;
346 for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
347 DestI->setName(I->getName());
348 VMap[I] = DestI++;
351 SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
352 CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
354 allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
356 // Create a mapping between the function instruction pointers and the wrapper instruction pointers
357 std::vector<Instruction *> wrapperInstructionDeps;
358 for (unsigned i = 0; i < instructionDeps.size(); i++) {
359 Instruction *instruction = instructionDeps[i].getInstruction();
360 Instruction *wrapperInstruction = NULL;
361 unsigned instructionOffset = 0;
362 for (inst_iterator I = inst_begin(function), E = inst_end(function); I != E; ++I, instructionOffset++) {
363 if (instruction == &(*I)) {
364 break;
367 assert(instructionOffset > 0);
368 for (inst_iterator I = inst_begin(wrapper), E = inst_end(wrapper); I != E; ++I, instructionOffset--) {
369 if (instructionOffset == 0) {
370 wrapperInstruction = &(*I);
371 break;
374 assert(wrapperInstruction);
375 wrapperInstructionDeps.push_back(wrapperInstruction);
378 // Forward magic type argument to any dependent instruction and replace it
379 for (unsigned i = 0; i < wrapperInstructionDeps.size(); i++) {
380 instructionDeps[i].setInstruction(wrapperInstructionDeps[i]);
381 instructionDeps[i].setInstructionTypeValue(magicTypeValue, magicNameValue, magicParentNameValue);
382 instructionDeps[i].replaceInstruction(magicArrayTypePtrMap, voidPtrTypeInfo);
386 inline Function* MagicMemFunction::getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
387 bool isDealloc) {
388 Function* wrapper;
389 std::vector<TYPECONST Type*> ArgTypes;
390 VALUE_TO_VALUE_MAP_TY VMap;
392 // Build arg types for wrapper
393 // add magic arguments
394 if (!isDealloc) {
395 Function::const_arg_iterator E = stdWrapper->arg_begin();
396 for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
397 E++;
398 for (Function::const_arg_iterator I = stdWrapper->arg_begin(); I != E; ++I) {
399 ArgTypes.push_back(I->getType());
402 // add original function arguments
403 for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
404 ArgTypes.push_back(I->getType());
407 // Create a new function type...
408 FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
410 // Create the wrapper
411 wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
413 // Loop over the arguments, copying the names of the mapped arguments over...
414 Function::arg_iterator DestI = wrapper->arg_begin();
415 std::vector<Value*> wrapperArgs;
416 if (!isDealloc) {
417 std::string magicArgs[] = { "magic_type", "magic_name", "magic_parent_name" };
418 for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
419 DestI->setName(magicArgs[i]);
420 wrapperArgs.push_back(DestI);
421 DestI++;
424 for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
425 DestI->setName(I->getName());
426 wrapperArgs.push_back(DestI);
427 DestI++;
430 // map the arguments of the standard wrapper to the arguments of the new custom wrapper
431 if ((!isDealloc) || argMapping.size()) {
432 Function::const_arg_iterator W = stdWrapper->arg_begin();
433 if (!isDealloc) {
434 // magic arguments are in the same position
435 for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
436 VMap[W] = wrapperArgs[i];
437 W++;
440 // map the selected arguments of the custom wrapper using the mapping provided as input
441 unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
442 for (unsigned i = 0; i < argMapping.size(); i++) {
443 VMap[W] = wrapperArgs[argOffset + argMapping[i] - 1];
444 W++;
448 SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
449 CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
451 // check whether some of the arguments of the custom wrapper need to be casted
452 // in order to match the basic wrapper implementation
453 Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(wrapper);
454 Function::const_arg_iterator W = stdWrapper->arg_begin();
455 unsigned argOffset = 0;
456 if (!isDealloc) {
457 argOffset = NUM_MAGIC_ARGS;
458 // skip the magic arguments, they are always the same
459 for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
460 W++;
463 for (unsigned i = 0; i < argMapping.size(); i++) {
464 TYPECONST Type* StdParamType = W->getType();
465 Value* ParamValue = wrapperArgs[argOffset + argMapping[i] - 1];
466 TYPECONST Type* ParamType = ParamValue->getType();
467 if (!MagicUtil::isCompatibleType(ParamType, StdParamType)) {
468 assert(CastInst::isCastable(ParamType, StdParamType) && "The type of the parameter of the custom wrapper "
469 "cannot be casted to the type of the basic wrapper to which it is corresponding.");
470 Instruction::CastOps CastOpCode = CastInst::getCastOpcode(ParamValue, false, StdParamType, false);
471 Instruction *ParamCastInst = CastInst::Create(CastOpCode, ParamValue, StdParamType, "", FirstInst);
473 for (Value::use_iterator it = ParamValue->use_begin(); it != ParamValue->use_end(); it++) {
474 if (Constant * C = dyn_cast<Constant>(*it)) {
475 if (!isa<GlobalValue>(C)) {
476 C->replaceUsesOfWith(ParamValue, ParamCastInst);
477 continue;
480 Instruction *I = dyn_cast<Instruction>(*it);
481 if (I && (I != ParamCastInst)) {
482 // replace all uses, except for the calls to the wrapped function
483 CallInst *CI = dyn_cast<CallInst>(I);
484 if (CI && (CI->getCalledFunction() == function)) {
485 continue;
487 I->replaceUsesOfWith(ParamValue, ParamCastInst);
491 W++;
494 // replace the call(s) to the standard function with calls to our function
495 for (Function::iterator BI = wrapper->getBasicBlockList().begin(), BE = wrapper->getBasicBlockList().end(); BI != BE; ++BI) {
496 unsigned pos = 0;
497 unsigned bbSize = BI->getInstList().size();
498 while (pos < bbSize) {
499 BasicBlock::iterator it = BI->getInstList().begin();
500 for (unsigned i = 0; i < pos; i++) {
501 it++;
503 Instruction *inst = &(*it);
504 // find the calls to the standard function
505 CallInst *callInst = dyn_cast<CallInst>(inst);
506 if (callInst && callInst->getCalledFunction() && (callInst->getCalledFunction()->getFunctionType() == stdFunction->getFunctionType())
507 && (!callInst->getCalledFunction()->getName().compare(stdFunction->getName()))) {
508 CallSite CS = MagicUtil::getCallSiteFromInstruction(callInst);
509 unsigned numStdParams = stdFunction->getFunctionType()->getNumParams();
510 unsigned numParams = function->getFunctionType()->getNumParams();
511 // construct the parameter array
512 std::vector<Value*> callArgs(numParams, NULL);
513 // first add the arguments that are common to the custom and standard function
514 // add casts where necessary
515 for (unsigned i = 0; i < numStdParams; i++) {
516 Value *argValue = CS.getArgument(i);
517 TYPECONST Type* paramType = function->getFunctionType()->getParamType(i);
518 TYPECONST Type* argType = argValue->getType();
519 if (paramType != argType) {
520 assert(CastInst::isCastable(argType, paramType) && "The value of the argument cannot be "
521 "casted to the parameter type required by the function to be called.");
522 Instruction::CastOps opcode = CastInst::getCastOpcode(argValue, false, paramType, false);
523 argValue = CastInst::Create(opcode, argValue, paramType, "", callInst);
525 callArgs[argMapping[i] - 1] = argValue;
527 // the other arguments are just forwarded from the wrapper's argument list
528 // skip the magic arguments of the wrapper from the beginning of the argument list
529 unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
530 for (unsigned i = argOffset; i < wrapper->getFunctionType()->getNumParams(); i++) {
531 if (callArgs[i - argOffset] == NULL) {
532 Value* arg = wrapperArgs[i];
533 callArgs[i - argOffset] = arg;
537 CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
538 newCallInst->takeName(callInst);
539 MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
541 pos++;
545 customWrapperSet.insert(wrapper);
546 return wrapper;
549 inline bool MagicMemFunction::isCustomWrapper(Function *function)
551 return customWrapperSet.find(function) != customWrapperSet.end();
556 #endif