1 #ifndef MAGIC_MEM_FUNCTION_H
2 #define MAGIC_MEM_FUNCTION_H
3 
4 #include <pass.h>
5 #include <magic/support/TypeInfo.h>
6 
7 #define NUM_MAGIC_ARGS  3
8 
9 using namespace llvm;
10 
11 namespace llvm {
12 
13 class MagicMemFunction {
14 public:
15 	MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, bool isNested, int allocFlags);
16 
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;
28 
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);
34 
35 	void print(raw_ostream &OS) const;
36 	void printDescription(raw_ostream &OS) const;
37 	const std::string getDescription() const;
38 
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);
43 
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;
59 
60 	void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
61 
62 	static Function *lastAllocWrapper;
63 	static std::map<std::string, Function*> allocWrapperCache;
64 	static std::set<Function*> customWrapperSet;
65 };
66 
67 inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
68 	aMagicMemFunction.print(OS);
69 	return OS;
70 }
71 
print(raw_ostream & OS)72 inline void MagicMemFunction::print(raw_ostream &OS) const {
73 	OS << getDescription();
74 }
75 
printDescription(raw_ostream & OS)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 << ", ";
121 		}
122 		instructionDeps[i].print(OS);
123 	}
124 	OS << "}]";
125 }
126 
getDescription()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;
133 }
134 
MagicMemFunction(Module & M,Function * function,Function * wrapper,bool isDealloc,bool isNested,int allocFlags)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;
152 	}
153 	if (isDealloc) {
154 		assert(!allocFlags);
155 	}
156 }
157 
getFunction()158 inline Function* MagicMemFunction::getFunction() const {
159 	return function;
160 }
161 
getWrapper()162 inline Function* MagicMemFunction::getWrapper() const {
163 	return wrapper;
164 }
165 
isDeallocFunction()166 inline bool MagicMemFunction::isDeallocFunction() const {
167 	return isDealloc;
168 }
169 
isNestedFunction()170 inline bool MagicMemFunction::isNestedFunction() const {
171 	return isNested;
172 }
173 
getAllocFlags()174 inline int MagicMemFunction::getAllocFlags() const {
175 	return allocFlags;
176 }
177 
getInstruction()178 inline Instruction* MagicMemFunction::getInstruction() const {
179 	return instruction;
180 }
181 
getInstructionParent()182 inline Function* MagicMemFunction::getInstructionParent() const {
183 	if (!instruction) {
184 		return NULL;
185 	}
186 	return instruction->getParent()->getParent();
187 }
188 
getInstructionTypeInfo()189 inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
190 	return aTypeInfo;
191 }
192 
getInstructionTypeValue()193 inline Value* MagicMemFunction::getInstructionTypeValue() const {
194 	return typeValue;
195 }
196 
hasInstructionType()197 inline bool MagicMemFunction::hasInstructionType() const {
198 	return aTypeInfo || typeValue;
199 }
200 
getInstructionDeps()201 inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
202 	return instructionDeps;
203 }
204 
setInstruction(Instruction * I)205 inline void MagicMemFunction::setInstruction(Instruction* I) {
206 	this->instruction = I;
207 	assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
208 }
209 
setInstructionTypeInfo(TypeInfo * aTypeInfo,std::string & allocName,std::string & allocParentName)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;
214 }
215 
setInstructionTypeValue(Value * typeValue,Value * allocNameValue,Value * allocParentNameValue)216 inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
217 	this->typeValue = typeValue;
218 	this->allocNameValue = allocNameValue;
219 	this->allocParentNameValue = allocParentNameValue;
220 }
221 
addInstructionDep(MagicMemFunction & function)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();
226 }
227 
replaceInstruction(std::map<TypeInfo *,Constant * > & magicArrayTypePtrMap,TypeInfo * voidPtrTypeInfo)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);
237 	}
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;
249 			}
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));
254 		}
255 		magicMemArgs.push_back(typeValue);
256 		magicMemArgs.push_back(allocNameValue);
257 		magicMemArgs.push_back(allocParentNameValue);
258 		numMagicArgs = NUM_MAGIC_ARGS;
259 	}
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);
269 			}
270 			else {
271 			    assert(arg->getType()->isIntegerTy());
272 			    assert(wArgType->isIntegerTy());
273 			    arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
274 			}
275 		}
276 		magicMemArgs.push_back(arg);
277 	}
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);
282 }
283 
getMemFunctionPointerParam(Function * function,std::set<Function * > & brkFunctions,TypeInfo * voidPtrTypeInfo)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;
296 			}
297 		}
298 	}
299 
300 	return -1;
301 }
302 
buildWrapper(std::map<TypeInfo *,Constant * > & magicArrayTypePtrMap,TypeInfo * voidPtrTypeInfo)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;
309 
310 	std::map<std::string, Function*>::iterator allocWrapperCacheIt;
311 
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;
317 	}
318 
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());
328 
329 	// Create a new function type...
330 	FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
331 
332 	// Create the wrapper
333 	wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
334 
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++;
349 	}
350 
351 	SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
352 	CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
353 
354 	allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
355 
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;
365             }
366         }
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;
372             }
373         }
374         assert(wrapperInstruction);
375         wrapperInstructionDeps.push_back(wrapperInstruction);
376     }
377 
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);
383     }
384 }
385 
getCustomWrapper(Function * function,Function * stdFunction,Function * stdWrapper,std::vector<unsigned> argMapping,bool isDealloc)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;
391 
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());
400 		}
401 	}
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());
405 	}
406 
407 	// Create a new function type...
408 	FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
409 
410 	// Create the wrapper
411 	wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
412 
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++;
422 		}
423 	}
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++;
428 	}
429 
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++;
438 			}
439 		}
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++;
445 		}
446 	}
447 
448 	SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
449 	CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
450 
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++;
461 		}
462 	}
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);
472 
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;
478 					}
479 				}
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;
486 					}
487 					I->replaceUsesOfWith(ParamValue, ParamCastInst);
488 				}
489 			}
490 		}
491 		W++;
492 	}
493 
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++;
502 			}
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);
524 					}
525 					callArgs[argMapping[i] - 1] = argValue;
526 				}
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;
534 					}
535 				}
536 
537 				CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
538 				newCallInst->takeName(callInst);
539 				MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
540 			}
541 			pos++;
542 		}
543 	}
544 
545 	customWrapperSet.insert(wrapper);
546 	return wrapper;
547 }
548 
isCustomWrapper(Function * function)549 inline bool MagicMemFunction::isCustomWrapper(Function *function)
550 {
551 	return customWrapperSet.find(function) != customWrapperSet.end();
552 }
553 
554 }
555 
556 #endif
557 
558