1 #ifndef MAGIC_MEM_FUNCTION_H
2 #define MAGIC_MEM_FUNCTION_H
5 #include <magic/support/TypeInfo.h>
7 #define NUM_MAGIC_ARGS 3
13 class MagicMemFunction
{
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
,
42 static bool isCustomWrapper(Function
*function
);
51 Instruction
*instruction
;
53 std::string allocName
;
54 std::string allocParentName
;
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
);
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()) << ")";
81 OS
<< wrapper
->getName() << "(" << TypeUtil::getDescription(wrapper
->getFunctionType()) << ")";
84 OS
<< ", isDeallocFunction = ";
86 OS
<< ", isNestedFunction = ";
88 OS
<< ", instruction = ";
90 instruction
->print(OS
);
93 OS
<< ", typeInfo = ";
95 OS
<< aTypeInfo
->getDescription();
98 OS
<< ", allocName = ";
100 OS
<< ", allocParentName = ";
101 OS
<< allocParentName
;
102 OS
<< ", typeValue = ";
104 typeValue
->print(OS
);
107 OS
<< ", allocNameValue = ";
109 allocNameValue
->print(OS
);
112 OS
<< ", allocParentNameValue = ";
113 if (allocParentNameValue
)
114 allocParentNameValue
->print(OS
);
117 OS
<< ", instructionDeps = {";
118 for (unsigned i
= 0; i
< instructionDeps
.size(); i
++) {
122 instructionDeps
[i
].print(OS
);
127 inline const std::string
MagicMemFunction::getDescription() const {
129 raw_string_ostream
ostream(string
);
130 printDescription(ostream
);
135 inline MagicMemFunction::MagicMemFunction(Module
&M
, Function
*function
, Function
*wrapper
, bool isDealloc
, bool isNested
, int allocFlags
) {
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
;
150 if (wrapper
&& !isDealloc
&& !isNested
) {
151 lastAllocWrapper
= wrapper
;
158 inline Function
* MagicMemFunction::getFunction() const {
162 inline Function
* MagicMemFunction::getWrapper() const {
166 inline bool MagicMemFunction::isDeallocFunction() const {
170 inline bool MagicMemFunction::isNestedFunction() const {
174 inline int MagicMemFunction::getAllocFlags() const {
178 inline Instruction
* MagicMemFunction::getInstruction() const {
182 inline Function
* MagicMemFunction::getInstructionParent() const {
186 return instruction
->getParent()->getParent();
189 inline TypeInfo
* MagicMemFunction::getInstructionTypeInfo() const {
193 inline Value
* MagicMemFunction::getInstructionTypeValue() const {
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();
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
236 buildWrapper(magicArrayTypePtrMap
, voidPtrTypeInfo
);
239 if (!isDeallocFunction() && !isNestedFunction()) {
240 std::map
<TypeInfo
*, Constant
*>::iterator it
;
243 if (aTypeInfo
== voidPtrTypeInfo
->getContainedType(0)) {
244 typeValue
= ConstantPointerNull::get((TYPECONST PointerType
*) (wrapper
->arg_begin()->getType()));
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
;
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
);
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()) {
288 } else if (brkFunctions
.find(function
) != brkFunctions
.end()) {
292 for (i
= 1; i
< function
->getFunctionType()->getNumContainedTypes(); i
++) {
293 type
= function
->getFunctionType()->getContainedType(i
);
294 if (type
->isPointerTy() && type
->getContainedType(0) == voidPtrTypeInfo
->getType()) {
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
;
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
++)
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");
340 Value
*magicNameValue
= DestI
;
341 magicNameValue
->setName("magic_name");
343 Value
*magicParentNameValue
= DestI
;
344 magicParentNameValue
->setName("magic_parent_name");
346 for (Function::const_arg_iterator I
= function
->arg_begin(), E
= function
->arg_end(); I
!= E
; ++I
) {
347 DestI
->setName(I
->getName());
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
)) {
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
);
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
,
389 std::vector
<TYPECONST Type
*> ArgTypes
;
390 VALUE_TO_VALUE_MAP_TY VMap
;
392 // Build arg types for wrapper
393 // add magic arguments
395 Function::const_arg_iterator E
= stdWrapper
->arg_begin();
396 for (unsigned i
= 0; i
< NUM_MAGIC_ARGS
; i
++)
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
;
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
);
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
);
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();
434 // magic arguments are in the same position
435 for (unsigned i
= 0; i
< NUM_MAGIC_ARGS
; i
++) {
436 VMap
[W
] = wrapperArgs
[i
];
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];
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;
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
++) {
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
);
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
)) {
487 I
->replaceUsesOfWith(ParamValue
, ParamCastInst
);
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
) {
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
++) {
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
);
545 customWrapperSet
.insert(wrapper
);
549 inline bool MagicMemFunction::isCustomWrapper(Function
*function
)
551 return customWrapperSet
.find(function
) != customWrapperSet
.end();