13e457fe3SDavid van Moolenbroek #ifndef MAGIC_MEM_FUNCTION_H
23e457fe3SDavid van Moolenbroek #define MAGIC_MEM_FUNCTION_H
33e457fe3SDavid van Moolenbroek
43e457fe3SDavid van Moolenbroek #include <pass.h>
53e457fe3SDavid van Moolenbroek #include <magic/support/TypeInfo.h>
63e457fe3SDavid van Moolenbroek
73e457fe3SDavid van Moolenbroek #define NUM_MAGIC_ARGS 3
83e457fe3SDavid van Moolenbroek
93e457fe3SDavid van Moolenbroek using namespace llvm;
103e457fe3SDavid van Moolenbroek
113e457fe3SDavid van Moolenbroek namespace llvm {
123e457fe3SDavid van Moolenbroek
133e457fe3SDavid van Moolenbroek class MagicMemFunction {
143e457fe3SDavid van Moolenbroek public:
15*b7725c85SDavid van Moolenbroek MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, bool isNested, int allocFlags);
163e457fe3SDavid van Moolenbroek
173e457fe3SDavid van Moolenbroek Function* getFunction() const;
183e457fe3SDavid van Moolenbroek Function* getWrapper() const;
193e457fe3SDavid van Moolenbroek bool isDeallocFunction() const;
20*b7725c85SDavid van Moolenbroek bool isNestedFunction() const;
213e457fe3SDavid van Moolenbroek int getAllocFlags() const;
223e457fe3SDavid van Moolenbroek Instruction* getInstruction() const;
233e457fe3SDavid van Moolenbroek Function* getInstructionParent() const;
243e457fe3SDavid van Moolenbroek TypeInfo* getInstructionTypeInfo() const;
253e457fe3SDavid van Moolenbroek Value* getInstructionTypeValue() const;
263e457fe3SDavid van Moolenbroek bool hasInstructionType() const;
273e457fe3SDavid van Moolenbroek std::vector<MagicMemFunction> getInstructionDeps() const;
283e457fe3SDavid van Moolenbroek
293e457fe3SDavid van Moolenbroek void setInstruction(Instruction* I);
303e457fe3SDavid van Moolenbroek void setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName);
313e457fe3SDavid van Moolenbroek void setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue);
323e457fe3SDavid van Moolenbroek void addInstructionDep(MagicMemFunction &function);
333e457fe3SDavid van Moolenbroek void replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
343e457fe3SDavid van Moolenbroek
353e457fe3SDavid van Moolenbroek void print(raw_ostream &OS) const;
363e457fe3SDavid van Moolenbroek void printDescription(raw_ostream &OS) const;
373e457fe3SDavid van Moolenbroek const std::string getDescription() const;
383e457fe3SDavid van Moolenbroek
393e457fe3SDavid van Moolenbroek static int getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo);
403e457fe3SDavid van Moolenbroek static Function* getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
413e457fe3SDavid van Moolenbroek bool isDealloc);
423e457fe3SDavid van Moolenbroek static bool isCustomWrapper(Function *function);
433e457fe3SDavid van Moolenbroek
443e457fe3SDavid van Moolenbroek private:
453e457fe3SDavid van Moolenbroek Module *module;
463e457fe3SDavid van Moolenbroek Function *function;
473e457fe3SDavid van Moolenbroek Function *wrapper;
483e457fe3SDavid van Moolenbroek bool isDealloc;
49*b7725c85SDavid van Moolenbroek bool isNested;
503e457fe3SDavid van Moolenbroek int allocFlags;
513e457fe3SDavid van Moolenbroek Instruction *instruction;
523e457fe3SDavid van Moolenbroek TypeInfo* aTypeInfo;
533e457fe3SDavid van Moolenbroek std::string allocName;
543e457fe3SDavid van Moolenbroek std::string allocParentName;
553e457fe3SDavid van Moolenbroek Value* typeValue;
563e457fe3SDavid van Moolenbroek Value* allocNameValue;
573e457fe3SDavid van Moolenbroek Value* allocParentNameValue;
583e457fe3SDavid van Moolenbroek std::vector<MagicMemFunction> instructionDeps;
593e457fe3SDavid van Moolenbroek
603e457fe3SDavid van Moolenbroek void buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo);
613e457fe3SDavid van Moolenbroek
623e457fe3SDavid van Moolenbroek static Function *lastAllocWrapper;
633e457fe3SDavid van Moolenbroek static std::map<std::string, Function*> allocWrapperCache;
643e457fe3SDavid van Moolenbroek static std::set<Function*> customWrapperSet;
653e457fe3SDavid van Moolenbroek };
663e457fe3SDavid van Moolenbroek
673e457fe3SDavid van Moolenbroek inline raw_ostream &operator<<(raw_ostream &OS, const MagicMemFunction &aMagicMemFunction) {
683e457fe3SDavid van Moolenbroek aMagicMemFunction.print(OS);
693e457fe3SDavid van Moolenbroek return OS;
703e457fe3SDavid van Moolenbroek }
713e457fe3SDavid van Moolenbroek
print(raw_ostream & OS)723e457fe3SDavid van Moolenbroek inline void MagicMemFunction::print(raw_ostream &OS) const {
733e457fe3SDavid van Moolenbroek OS << getDescription();
743e457fe3SDavid van Moolenbroek }
753e457fe3SDavid van Moolenbroek
printDescription(raw_ostream & OS)763e457fe3SDavid van Moolenbroek inline void MagicMemFunction::printDescription(raw_ostream &OS) const {
773e457fe3SDavid van Moolenbroek OS << "[ function = ";
783e457fe3SDavid van Moolenbroek OS << function->getName() << "(" << TypeUtil::getDescription(function->getFunctionType()) << ")";
793e457fe3SDavid van Moolenbroek OS << ", wrapper = ";
803e457fe3SDavid van Moolenbroek if (wrapper) {
813e457fe3SDavid van Moolenbroek OS << wrapper->getName() << "(" << TypeUtil::getDescription(wrapper->getFunctionType()) << ")";
823e457fe3SDavid van Moolenbroek } else
833e457fe3SDavid van Moolenbroek OS << "NULL";
843e457fe3SDavid van Moolenbroek OS << ", isDeallocFunction = ";
853e457fe3SDavid van Moolenbroek OS << isDealloc;
86*b7725c85SDavid van Moolenbroek OS << ", isNestedFunction = ";
87*b7725c85SDavid van Moolenbroek OS << isNested;
883e457fe3SDavid van Moolenbroek OS << ", instruction = ";
893e457fe3SDavid van Moolenbroek if (instruction)
903e457fe3SDavid van Moolenbroek instruction->print(OS);
913e457fe3SDavid van Moolenbroek else
923e457fe3SDavid van Moolenbroek OS << "NULL";
933e457fe3SDavid van Moolenbroek OS << ", typeInfo = ";
943e457fe3SDavid van Moolenbroek if (aTypeInfo)
953e457fe3SDavid van Moolenbroek OS << aTypeInfo->getDescription();
963e457fe3SDavid van Moolenbroek else
973e457fe3SDavid van Moolenbroek OS << "NULL";
983e457fe3SDavid van Moolenbroek OS << ", allocName = ";
993e457fe3SDavid van Moolenbroek OS << allocName;
1003e457fe3SDavid van Moolenbroek OS << ", allocParentName = ";
1013e457fe3SDavid van Moolenbroek OS << allocParentName;
1023e457fe3SDavid van Moolenbroek OS << ", typeValue = ";
1033e457fe3SDavid van Moolenbroek if (typeValue)
1043e457fe3SDavid van Moolenbroek typeValue->print(OS);
1053e457fe3SDavid van Moolenbroek else
1063e457fe3SDavid van Moolenbroek OS << "NULL";
1073e457fe3SDavid van Moolenbroek OS << ", allocNameValue = ";
1083e457fe3SDavid van Moolenbroek if (allocNameValue)
1093e457fe3SDavid van Moolenbroek allocNameValue->print(OS);
1103e457fe3SDavid van Moolenbroek else
1113e457fe3SDavid van Moolenbroek OS << "NULL";
1123e457fe3SDavid van Moolenbroek OS << ", allocParentNameValue = ";
1133e457fe3SDavid van Moolenbroek if (allocParentNameValue)
1143e457fe3SDavid van Moolenbroek allocParentNameValue->print(OS);
1153e457fe3SDavid van Moolenbroek else
1163e457fe3SDavid van Moolenbroek OS << "NULL";
1173e457fe3SDavid van Moolenbroek OS << ", instructionDeps = {";
1183e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < instructionDeps.size(); i++) {
1193e457fe3SDavid van Moolenbroek if (i > 0) {
1203e457fe3SDavid van Moolenbroek OS << ", ";
1213e457fe3SDavid van Moolenbroek }
1223e457fe3SDavid van Moolenbroek instructionDeps[i].print(OS);
1233e457fe3SDavid van Moolenbroek }
1243e457fe3SDavid van Moolenbroek OS << "}]";
1253e457fe3SDavid van Moolenbroek }
1263e457fe3SDavid van Moolenbroek
getDescription()1273e457fe3SDavid van Moolenbroek inline const std::string MagicMemFunction::getDescription() const {
1283e457fe3SDavid van Moolenbroek std::string string;
1293e457fe3SDavid van Moolenbroek raw_string_ostream ostream(string);
1303e457fe3SDavid van Moolenbroek printDescription(ostream);
1313e457fe3SDavid van Moolenbroek ostream.flush();
1323e457fe3SDavid van Moolenbroek return string;
1333e457fe3SDavid van Moolenbroek }
1343e457fe3SDavid van Moolenbroek
MagicMemFunction(Module & M,Function * function,Function * wrapper,bool isDealloc,bool isNested,int allocFlags)135*b7725c85SDavid van Moolenbroek inline MagicMemFunction::MagicMemFunction(Module &M, Function *function, Function *wrapper, bool isDealloc, bool isNested, int allocFlags) {
1363e457fe3SDavid van Moolenbroek this->module = &M;
1373e457fe3SDavid van Moolenbroek this->function = function;
1383e457fe3SDavid van Moolenbroek this->wrapper = wrapper;
1393e457fe3SDavid van Moolenbroek this->isDealloc = isDealloc;
140*b7725c85SDavid van Moolenbroek this->isNested = isNested;
1413e457fe3SDavid van Moolenbroek this->allocFlags = allocFlags;
1423e457fe3SDavid van Moolenbroek this->instruction = NULL;
1433e457fe3SDavid van Moolenbroek this->aTypeInfo = NULL;
1443e457fe3SDavid van Moolenbroek this->allocName = "";
1453e457fe3SDavid van Moolenbroek this->allocParentName = "";
1463e457fe3SDavid van Moolenbroek this->typeValue = NULL;
1473e457fe3SDavid van Moolenbroek this->allocNameValue = NULL;
1483e457fe3SDavid van Moolenbroek this->allocParentNameValue = NULL;
1493e457fe3SDavid van Moolenbroek assert(function);
150*b7725c85SDavid van Moolenbroek if (wrapper && !isDealloc && !isNested) {
1513e457fe3SDavid van Moolenbroek lastAllocWrapper = wrapper;
1523e457fe3SDavid van Moolenbroek }
1533e457fe3SDavid van Moolenbroek if (isDealloc) {
1543e457fe3SDavid van Moolenbroek assert(!allocFlags);
1553e457fe3SDavid van Moolenbroek }
1563e457fe3SDavid van Moolenbroek }
1573e457fe3SDavid van Moolenbroek
getFunction()1583e457fe3SDavid van Moolenbroek inline Function* MagicMemFunction::getFunction() const {
1593e457fe3SDavid van Moolenbroek return function;
1603e457fe3SDavid van Moolenbroek }
1613e457fe3SDavid van Moolenbroek
getWrapper()1623e457fe3SDavid van Moolenbroek inline Function* MagicMemFunction::getWrapper() const {
1633e457fe3SDavid van Moolenbroek return wrapper;
1643e457fe3SDavid van Moolenbroek }
1653e457fe3SDavid van Moolenbroek
isDeallocFunction()1663e457fe3SDavid van Moolenbroek inline bool MagicMemFunction::isDeallocFunction() const {
1673e457fe3SDavid van Moolenbroek return isDealloc;
1683e457fe3SDavid van Moolenbroek }
1693e457fe3SDavid van Moolenbroek
isNestedFunction()170*b7725c85SDavid van Moolenbroek inline bool MagicMemFunction::isNestedFunction() const {
171*b7725c85SDavid van Moolenbroek return isNested;
172*b7725c85SDavid van Moolenbroek }
173*b7725c85SDavid van Moolenbroek
getAllocFlags()1743e457fe3SDavid van Moolenbroek inline int MagicMemFunction::getAllocFlags() const {
1753e457fe3SDavid van Moolenbroek return allocFlags;
1763e457fe3SDavid van Moolenbroek }
1773e457fe3SDavid van Moolenbroek
getInstruction()1783e457fe3SDavid van Moolenbroek inline Instruction* MagicMemFunction::getInstruction() const {
1793e457fe3SDavid van Moolenbroek return instruction;
1803e457fe3SDavid van Moolenbroek }
1813e457fe3SDavid van Moolenbroek
getInstructionParent()1823e457fe3SDavid van Moolenbroek inline Function* MagicMemFunction::getInstructionParent() const {
1833e457fe3SDavid van Moolenbroek if (!instruction) {
1843e457fe3SDavid van Moolenbroek return NULL;
1853e457fe3SDavid van Moolenbroek }
1863e457fe3SDavid van Moolenbroek return instruction->getParent()->getParent();
1873e457fe3SDavid van Moolenbroek }
1883e457fe3SDavid van Moolenbroek
getInstructionTypeInfo()1893e457fe3SDavid van Moolenbroek inline TypeInfo* MagicMemFunction::getInstructionTypeInfo() const {
1903e457fe3SDavid van Moolenbroek return aTypeInfo;
1913e457fe3SDavid van Moolenbroek }
1923e457fe3SDavid van Moolenbroek
getInstructionTypeValue()1933e457fe3SDavid van Moolenbroek inline Value* MagicMemFunction::getInstructionTypeValue() const {
1943e457fe3SDavid van Moolenbroek return typeValue;
1953e457fe3SDavid van Moolenbroek }
1963e457fe3SDavid van Moolenbroek
hasInstructionType()1973e457fe3SDavid van Moolenbroek inline bool MagicMemFunction::hasInstructionType() const {
1983e457fe3SDavid van Moolenbroek return aTypeInfo || typeValue;
1993e457fe3SDavid van Moolenbroek }
2003e457fe3SDavid van Moolenbroek
getInstructionDeps()2013e457fe3SDavid van Moolenbroek inline std::vector<MagicMemFunction> MagicMemFunction::getInstructionDeps() const {
2023e457fe3SDavid van Moolenbroek return instructionDeps;
2033e457fe3SDavid van Moolenbroek }
2043e457fe3SDavid van Moolenbroek
setInstruction(Instruction * I)2053e457fe3SDavid van Moolenbroek inline void MagicMemFunction::setInstruction(Instruction* I) {
2063e457fe3SDavid van Moolenbroek this->instruction = I;
2073e457fe3SDavid van Moolenbroek assert(isa<CallInst>(instruction) || isa<InvokeInst>(instruction));
2083e457fe3SDavid van Moolenbroek }
2093e457fe3SDavid van Moolenbroek
setInstructionTypeInfo(TypeInfo * aTypeInfo,std::string & allocName,std::string & allocParentName)2103e457fe3SDavid van Moolenbroek inline void MagicMemFunction::setInstructionTypeInfo(TypeInfo* aTypeInfo, std::string &allocName, std::string &allocParentName) {
2113e457fe3SDavid van Moolenbroek this->aTypeInfo = aTypeInfo;
2123e457fe3SDavid van Moolenbroek this->allocName = allocName;
2133e457fe3SDavid van Moolenbroek this->allocParentName = allocParentName;
2143e457fe3SDavid van Moolenbroek }
2153e457fe3SDavid van Moolenbroek
setInstructionTypeValue(Value * typeValue,Value * allocNameValue,Value * allocParentNameValue)2163e457fe3SDavid van Moolenbroek inline void MagicMemFunction::setInstructionTypeValue(Value* typeValue, Value* allocNameValue, Value* allocParentNameValue) {
2173e457fe3SDavid van Moolenbroek this->typeValue = typeValue;
2183e457fe3SDavid van Moolenbroek this->allocNameValue = allocNameValue;
2193e457fe3SDavid van Moolenbroek this->allocParentNameValue = allocParentNameValue;
2203e457fe3SDavid van Moolenbroek }
2213e457fe3SDavid van Moolenbroek
addInstructionDep(MagicMemFunction & function)2223e457fe3SDavid van Moolenbroek inline void MagicMemFunction::addInstructionDep(MagicMemFunction &function) {
2233e457fe3SDavid van Moolenbroek assert(wrapper == NULL && "Dependencies are resolved at wrapper building time, so wrapper has to be NULL!");
2243e457fe3SDavid van Moolenbroek instructionDeps.push_back(function);
2253e457fe3SDavid van Moolenbroek allocFlags |= function.getAllocFlags();
2263e457fe3SDavid van Moolenbroek }
2273e457fe3SDavid van Moolenbroek
replaceInstruction(std::map<TypeInfo *,Constant * > & magicArrayTypePtrMap,TypeInfo * voidPtrTypeInfo)2283e457fe3SDavid van Moolenbroek inline void MagicMemFunction::replaceInstruction(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
2293e457fe3SDavid van Moolenbroek Instruction *I = getInstruction();
2303e457fe3SDavid van Moolenbroek assert(I);
2313e457fe3SDavid van Moolenbroek CallSite CS = MagicUtil::getCallSiteFromInstruction(I);
2323e457fe3SDavid van Moolenbroek std::vector<Value*> magicMemArgs;
2333e457fe3SDavid van Moolenbroek unsigned numMagicArgs = 0;
2343e457fe3SDavid van Moolenbroek //if we do not have a wrapper, build one
2353e457fe3SDavid van Moolenbroek if (!wrapper) {
2363e457fe3SDavid van Moolenbroek buildWrapper(magicArrayTypePtrMap, voidPtrTypeInfo);
2373e457fe3SDavid van Moolenbroek }
2383e457fe3SDavid van Moolenbroek //inject magic args
239*b7725c85SDavid van Moolenbroek if (!isDeallocFunction() && !isNestedFunction()) {
2403e457fe3SDavid van Moolenbroek std::map<TypeInfo*, Constant*>::iterator it;
2413e457fe3SDavid van Moolenbroek if (!typeValue) {
2423e457fe3SDavid van Moolenbroek assert(aTypeInfo);
2433e457fe3SDavid van Moolenbroek if (aTypeInfo == voidPtrTypeInfo->getContainedType(0)) {
2443e457fe3SDavid van Moolenbroek typeValue = ConstantPointerNull::get((TYPECONST PointerType*) (wrapper->arg_begin()->getType()));
2453e457fe3SDavid van Moolenbroek } else {
2463e457fe3SDavid van Moolenbroek it = magicArrayTypePtrMap.find(aTypeInfo);
2473e457fe3SDavid van Moolenbroek assert(it != magicArrayTypePtrMap.end());
2483e457fe3SDavid van Moolenbroek typeValue = it->second;
2493e457fe3SDavid van Moolenbroek }
2503e457fe3SDavid van Moolenbroek assert(allocName.compare(""));
2513e457fe3SDavid van Moolenbroek assert(allocParentName.compare(""));
2523e457fe3SDavid van Moolenbroek allocNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocName));
2533e457fe3SDavid van Moolenbroek allocParentNameValue = MagicUtil::getArrayPtr(*module, MagicUtil::getStringRef(*module, allocParentName));
2543e457fe3SDavid van Moolenbroek }
2553e457fe3SDavid van Moolenbroek magicMemArgs.push_back(typeValue);
2563e457fe3SDavid van Moolenbroek magicMemArgs.push_back(allocNameValue);
2573e457fe3SDavid van Moolenbroek magicMemArgs.push_back(allocParentNameValue);
2583e457fe3SDavid van Moolenbroek numMagicArgs = NUM_MAGIC_ARGS;
2593e457fe3SDavid van Moolenbroek }
2603e457fe3SDavid van Moolenbroek //push other args
2613e457fe3SDavid van Moolenbroek unsigned arg_size = MagicUtil::getCalledFunctionFromCS(CS)->getFunctionType()->getNumContainedTypes() - 1;
2623e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < arg_size; i++) {
2633e457fe3SDavid van Moolenbroek Value *arg = CS.getArgument(i);
2643e457fe3SDavid van Moolenbroek TYPECONST Type* wArgType = wrapper->getFunctionType()->getContainedType(i + numMagicArgs + 1);
2653e457fe3SDavid van Moolenbroek if (arg->getType() != wArgType) {
2663e457fe3SDavid van Moolenbroek if (arg->getType()->isPointerTy()) {
2673e457fe3SDavid van Moolenbroek assert(wArgType->isPointerTy());
2683e457fe3SDavid van Moolenbroek arg = CastInst::CreatePointerCast(arg, wArgType, "WrapperCast", I);
2693e457fe3SDavid van Moolenbroek }
2703e457fe3SDavid van Moolenbroek else {
2713e457fe3SDavid van Moolenbroek assert(arg->getType()->isIntegerTy());
2723e457fe3SDavid van Moolenbroek assert(wArgType->isIntegerTy());
2733e457fe3SDavid van Moolenbroek arg = CastInst::CreateIntegerCast(arg, wArgType, false, "WrapperCast", I);
2743e457fe3SDavid van Moolenbroek }
2753e457fe3SDavid van Moolenbroek }
2763e457fe3SDavid van Moolenbroek magicMemArgs.push_back(arg);
2773e457fe3SDavid van Moolenbroek }
2783e457fe3SDavid van Moolenbroek //replace function with wrapper
2793e457fe3SDavid van Moolenbroek CallInst* newInst = MagicUtil::createCallInstruction(wrapper, magicMemArgs, "", I);
2803e457fe3SDavid van Moolenbroek newInst->takeName(I);
2813e457fe3SDavid van Moolenbroek MagicUtil::replaceCallInst(I, newInst, NUM_MAGIC_ARGS);
2823e457fe3SDavid van Moolenbroek }
2833e457fe3SDavid van Moolenbroek
getMemFunctionPointerParam(Function * function,std::set<Function * > & brkFunctions,TypeInfo * voidPtrTypeInfo)2843e457fe3SDavid van Moolenbroek inline int MagicMemFunction::getMemFunctionPointerParam(Function* function, std::set<Function*> &brkFunctions, TypeInfo *voidPtrTypeInfo) {
2853e457fe3SDavid van Moolenbroek TYPECONST Type *type = function->getReturnType();
2863e457fe3SDavid van Moolenbroek if (type == voidPtrTypeInfo->getType()) {
2873e457fe3SDavid van Moolenbroek return 0;
2883e457fe3SDavid van Moolenbroek } else if (brkFunctions.find(function) != brkFunctions.end()) {
2893e457fe3SDavid van Moolenbroek return 1;
2903e457fe3SDavid van Moolenbroek } else {
2913e457fe3SDavid van Moolenbroek unsigned i;
2923e457fe3SDavid van Moolenbroek for (i = 1; i < function->getFunctionType()->getNumContainedTypes(); i++) {
2933e457fe3SDavid van Moolenbroek type = function->getFunctionType()->getContainedType(i);
2943e457fe3SDavid van Moolenbroek if (type->isPointerTy() && type->getContainedType(0) == voidPtrTypeInfo->getType()) {
2953e457fe3SDavid van Moolenbroek return i;
2963e457fe3SDavid van Moolenbroek }
2973e457fe3SDavid van Moolenbroek }
2983e457fe3SDavid van Moolenbroek }
2993e457fe3SDavid van Moolenbroek
3003e457fe3SDavid van Moolenbroek return -1;
3013e457fe3SDavid van Moolenbroek }
3023e457fe3SDavid van Moolenbroek
buildWrapper(std::map<TypeInfo *,Constant * > & magicArrayTypePtrMap,TypeInfo * voidPtrTypeInfo)3033e457fe3SDavid van Moolenbroek inline void MagicMemFunction::buildWrapper(std::map<TypeInfo*, Constant*> &magicArrayTypePtrMap, TypeInfo *voidPtrTypeInfo) {
3043e457fe3SDavid van Moolenbroek assert(!isDeallocFunction());
305*b7725c85SDavid van Moolenbroek assert(!isNestedFunction());
3063e457fe3SDavid van Moolenbroek assert(lastAllocWrapper);
3073e457fe3SDavid van Moolenbroek std::vector<TYPECONST Type*> ArgTypes;
3083e457fe3SDavid van Moolenbroek VALUE_TO_VALUE_MAP_TY VMap;
3093e457fe3SDavid van Moolenbroek
3103e457fe3SDavid van Moolenbroek std::map<std::string, Function*>::iterator allocWrapperCacheIt;
3113e457fe3SDavid van Moolenbroek
3123e457fe3SDavid van Moolenbroek // See if the wrapper is in cache, otherwise create a new wrapper using function cloning
3133e457fe3SDavid van Moolenbroek allocWrapperCacheIt = allocWrapperCache.find(function->getName());
3143e457fe3SDavid van Moolenbroek if (allocWrapperCacheIt != allocWrapperCache.end()) {
3153e457fe3SDavid van Moolenbroek wrapper = allocWrapperCacheIt->second;
3163e457fe3SDavid van Moolenbroek return;
3173e457fe3SDavid van Moolenbroek }
3183e457fe3SDavid van Moolenbroek
3193e457fe3SDavid van Moolenbroek // Build arg types for wrapper
3203e457fe3SDavid van Moolenbroek Function::const_arg_iterator E = lastAllocWrapper->arg_begin();
3213e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
3223e457fe3SDavid van Moolenbroek E++;
3233e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = lastAllocWrapper->arg_begin(); I != E; ++I)
3243e457fe3SDavid van Moolenbroek ArgTypes.push_back(I->getType());
3253e457fe3SDavid van Moolenbroek E = function->arg_end();
3263e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = function->arg_begin(); I != E; ++I)
3273e457fe3SDavid van Moolenbroek ArgTypes.push_back(I->getType());
3283e457fe3SDavid van Moolenbroek
3293e457fe3SDavid van Moolenbroek // Create a new function type...
3303e457fe3SDavid van Moolenbroek FunctionType *FTy = FunctionType::get(function->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
3313e457fe3SDavid van Moolenbroek
3323e457fe3SDavid van Moolenbroek // Create the wrapper
3333e457fe3SDavid van Moolenbroek wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
3343e457fe3SDavid van Moolenbroek
3353e457fe3SDavid van Moolenbroek // Loop over the arguments, copying the names of the mapped arguments over...
3363e457fe3SDavid van Moolenbroek Function::arg_iterator DestI = wrapper->arg_begin();
3373e457fe3SDavid van Moolenbroek Value *magicTypeValue = DestI;
3383e457fe3SDavid van Moolenbroek magicTypeValue->setName("magic_type");
3393e457fe3SDavid van Moolenbroek DestI++;
3403e457fe3SDavid van Moolenbroek Value *magicNameValue = DestI;
3413e457fe3SDavid van Moolenbroek magicNameValue->setName("magic_name");
3423e457fe3SDavid van Moolenbroek DestI++;
3433e457fe3SDavid van Moolenbroek Value *magicParentNameValue = DestI;
3443e457fe3SDavid van Moolenbroek magicParentNameValue->setName("magic_parent_name");
3453e457fe3SDavid van Moolenbroek DestI++;
3463e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
3473e457fe3SDavid van Moolenbroek DestI->setName(I->getName());
3483e457fe3SDavid van Moolenbroek VMap[I] = DestI++;
3493e457fe3SDavid van Moolenbroek }
3503e457fe3SDavid van Moolenbroek
3513e457fe3SDavid van Moolenbroek SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
3523e457fe3SDavid van Moolenbroek CloneFunctionInto(wrapper, function, VMap, false, Returns, "", NULL);
3533e457fe3SDavid van Moolenbroek
3543e457fe3SDavid van Moolenbroek allocWrapperCache.insert(std::pair<std::string, Function*>(function->getName(), wrapper));
3553e457fe3SDavid van Moolenbroek
3563e457fe3SDavid van Moolenbroek // Create a mapping between the function instruction pointers and the wrapper instruction pointers
3573e457fe3SDavid van Moolenbroek std::vector<Instruction *> wrapperInstructionDeps;
3583e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < instructionDeps.size(); i++) {
3593e457fe3SDavid van Moolenbroek Instruction *instruction = instructionDeps[i].getInstruction();
3603e457fe3SDavid van Moolenbroek Instruction *wrapperInstruction = NULL;
3613e457fe3SDavid van Moolenbroek unsigned instructionOffset = 0;
3623e457fe3SDavid van Moolenbroek for (inst_iterator I = inst_begin(function), E = inst_end(function); I != E; ++I, instructionOffset++) {
3633e457fe3SDavid van Moolenbroek if (instruction == &(*I)) {
3643e457fe3SDavid van Moolenbroek break;
3653e457fe3SDavid van Moolenbroek }
3663e457fe3SDavid van Moolenbroek }
3673e457fe3SDavid van Moolenbroek assert(instructionOffset > 0);
3683e457fe3SDavid van Moolenbroek for (inst_iterator I = inst_begin(wrapper), E = inst_end(wrapper); I != E; ++I, instructionOffset--) {
3693e457fe3SDavid van Moolenbroek if (instructionOffset == 0) {
3703e457fe3SDavid van Moolenbroek wrapperInstruction = &(*I);
3713e457fe3SDavid van Moolenbroek break;
3723e457fe3SDavid van Moolenbroek }
3733e457fe3SDavid van Moolenbroek }
3743e457fe3SDavid van Moolenbroek assert(wrapperInstruction);
3753e457fe3SDavid van Moolenbroek wrapperInstructionDeps.push_back(wrapperInstruction);
3763e457fe3SDavid van Moolenbroek }
3773e457fe3SDavid van Moolenbroek
3783e457fe3SDavid van Moolenbroek // Forward magic type argument to any dependent instruction and replace it
3793e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < wrapperInstructionDeps.size(); i++) {
3803e457fe3SDavid van Moolenbroek instructionDeps[i].setInstruction(wrapperInstructionDeps[i]);
3813e457fe3SDavid van Moolenbroek instructionDeps[i].setInstructionTypeValue(magicTypeValue, magicNameValue, magicParentNameValue);
3823e457fe3SDavid van Moolenbroek instructionDeps[i].replaceInstruction(magicArrayTypePtrMap, voidPtrTypeInfo);
3833e457fe3SDavid van Moolenbroek }
3843e457fe3SDavid van Moolenbroek }
3853e457fe3SDavid van Moolenbroek
getCustomWrapper(Function * function,Function * stdFunction,Function * stdWrapper,std::vector<unsigned> argMapping,bool isDealloc)3863e457fe3SDavid van Moolenbroek inline Function* MagicMemFunction::getCustomWrapper(Function* function, Function* stdFunction, Function* stdWrapper, std::vector<unsigned> argMapping,
3873e457fe3SDavid van Moolenbroek bool isDealloc) {
3883e457fe3SDavid van Moolenbroek Function* wrapper;
3893e457fe3SDavid van Moolenbroek std::vector<TYPECONST Type*> ArgTypes;
3903e457fe3SDavid van Moolenbroek VALUE_TO_VALUE_MAP_TY VMap;
3913e457fe3SDavid van Moolenbroek
3923e457fe3SDavid van Moolenbroek // Build arg types for wrapper
3933e457fe3SDavid van Moolenbroek // add magic arguments
3943e457fe3SDavid van Moolenbroek if (!isDealloc) {
3953e457fe3SDavid van Moolenbroek Function::const_arg_iterator E = stdWrapper->arg_begin();
3963e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++)
3973e457fe3SDavid van Moolenbroek E++;
3983e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = stdWrapper->arg_begin(); I != E; ++I) {
3993e457fe3SDavid van Moolenbroek ArgTypes.push_back(I->getType());
4003e457fe3SDavid van Moolenbroek }
4013e457fe3SDavid van Moolenbroek }
4023e457fe3SDavid van Moolenbroek // add original function arguments
4033e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
4043e457fe3SDavid van Moolenbroek ArgTypes.push_back(I->getType());
4053e457fe3SDavid van Moolenbroek }
4063e457fe3SDavid van Moolenbroek
4073e457fe3SDavid van Moolenbroek // Create a new function type...
4083e457fe3SDavid van Moolenbroek FunctionType *FTy = FunctionType::get(stdWrapper->getFunctionType()->getReturnType(), ArgTypes, function->getFunctionType()->isVarArg());
4093e457fe3SDavid van Moolenbroek
4103e457fe3SDavid van Moolenbroek // Create the wrapper
4113e457fe3SDavid van Moolenbroek wrapper = Function::Create(FTy, function->getLinkage(), "magic_" + function->getName(), function->getParent());
4123e457fe3SDavid van Moolenbroek
4133e457fe3SDavid van Moolenbroek // Loop over the arguments, copying the names of the mapped arguments over...
4143e457fe3SDavid van Moolenbroek Function::arg_iterator DestI = wrapper->arg_begin();
4153e457fe3SDavid van Moolenbroek std::vector<Value*> wrapperArgs;
4163e457fe3SDavid van Moolenbroek if (!isDealloc) {
4173e457fe3SDavid van Moolenbroek std::string magicArgs[] = { "magic_type", "magic_name", "magic_parent_name" };
4183e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
4193e457fe3SDavid van Moolenbroek DestI->setName(magicArgs[i]);
4203e457fe3SDavid van Moolenbroek wrapperArgs.push_back(DestI);
4213e457fe3SDavid van Moolenbroek DestI++;
4223e457fe3SDavid van Moolenbroek }
4233e457fe3SDavid van Moolenbroek }
4243e457fe3SDavid van Moolenbroek for (Function::const_arg_iterator I = function->arg_begin(), E = function->arg_end(); I != E; ++I) {
4253e457fe3SDavid van Moolenbroek DestI->setName(I->getName());
4263e457fe3SDavid van Moolenbroek wrapperArgs.push_back(DestI);
4273e457fe3SDavid van Moolenbroek DestI++;
4283e457fe3SDavid van Moolenbroek }
4293e457fe3SDavid van Moolenbroek
4303e457fe3SDavid van Moolenbroek // map the arguments of the standard wrapper to the arguments of the new custom wrapper
4313e457fe3SDavid van Moolenbroek if ((!isDealloc) || argMapping.size()) {
4323e457fe3SDavid van Moolenbroek Function::const_arg_iterator W = stdWrapper->arg_begin();
4333e457fe3SDavid van Moolenbroek if (!isDealloc) {
4343e457fe3SDavid van Moolenbroek // magic arguments are in the same position
4353e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
4363e457fe3SDavid van Moolenbroek VMap[W] = wrapperArgs[i];
4373e457fe3SDavid van Moolenbroek W++;
4383e457fe3SDavid van Moolenbroek }
4393e457fe3SDavid van Moolenbroek }
4403e457fe3SDavid van Moolenbroek // map the selected arguments of the custom wrapper using the mapping provided as input
4413e457fe3SDavid van Moolenbroek unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
4423e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < argMapping.size(); i++) {
4433e457fe3SDavid van Moolenbroek VMap[W] = wrapperArgs[argOffset + argMapping[i] - 1];
4443e457fe3SDavid van Moolenbroek W++;
4453e457fe3SDavid van Moolenbroek }
4463e457fe3SDavid van Moolenbroek }
4473e457fe3SDavid van Moolenbroek
4483e457fe3SDavid van Moolenbroek SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned...
4493e457fe3SDavid van Moolenbroek CloneFunctionInto(wrapper, stdWrapper, VMap, false, Returns, "", NULL);
4503e457fe3SDavid van Moolenbroek
4513e457fe3SDavid van Moolenbroek // check whether some of the arguments of the custom wrapper need to be casted
4523e457fe3SDavid van Moolenbroek // in order to match the basic wrapper implementation
4533e457fe3SDavid van Moolenbroek Instruction *FirstInst = MagicUtil::getFirstNonAllocaInst(wrapper);
4543e457fe3SDavid van Moolenbroek Function::const_arg_iterator W = stdWrapper->arg_begin();
4553e457fe3SDavid van Moolenbroek unsigned argOffset = 0;
4563e457fe3SDavid van Moolenbroek if (!isDealloc) {
4573e457fe3SDavid van Moolenbroek argOffset = NUM_MAGIC_ARGS;
4583e457fe3SDavid van Moolenbroek // skip the magic arguments, they are always the same
4593e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < NUM_MAGIC_ARGS; i++) {
4603e457fe3SDavid van Moolenbroek W++;
4613e457fe3SDavid van Moolenbroek }
4623e457fe3SDavid van Moolenbroek }
4633e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < argMapping.size(); i++) {
4643e457fe3SDavid van Moolenbroek TYPECONST Type* StdParamType = W->getType();
4653e457fe3SDavid van Moolenbroek Value* ParamValue = wrapperArgs[argOffset + argMapping[i] - 1];
4663e457fe3SDavid van Moolenbroek TYPECONST Type* ParamType = ParamValue->getType();
4673e457fe3SDavid van Moolenbroek if (!MagicUtil::isCompatibleType(ParamType, StdParamType)) {
4683e457fe3SDavid van Moolenbroek assert(CastInst::isCastable(ParamType, StdParamType) && "The type of the parameter of the custom wrapper "
4693e457fe3SDavid van Moolenbroek "cannot be casted to the type of the basic wrapper to which it is corresponding.");
4703e457fe3SDavid van Moolenbroek Instruction::CastOps CastOpCode = CastInst::getCastOpcode(ParamValue, false, StdParamType, false);
4713e457fe3SDavid van Moolenbroek Instruction *ParamCastInst = CastInst::Create(CastOpCode, ParamValue, StdParamType, "", FirstInst);
4723e457fe3SDavid van Moolenbroek
4733e457fe3SDavid van Moolenbroek for (Value::use_iterator it = ParamValue->use_begin(); it != ParamValue->use_end(); it++) {
4743e457fe3SDavid van Moolenbroek if (Constant * C = dyn_cast<Constant>(*it)) {
4753e457fe3SDavid van Moolenbroek if (!isa<GlobalValue>(C)) {
4763e457fe3SDavid van Moolenbroek C->replaceUsesOfWith(ParamValue, ParamCastInst);
4773e457fe3SDavid van Moolenbroek continue;
4783e457fe3SDavid van Moolenbroek }
4793e457fe3SDavid van Moolenbroek }
4803e457fe3SDavid van Moolenbroek Instruction *I = dyn_cast<Instruction>(*it);
4813e457fe3SDavid van Moolenbroek if (I && (I != ParamCastInst)) {
4823e457fe3SDavid van Moolenbroek // replace all uses, except for the calls to the wrapped function
4833e457fe3SDavid van Moolenbroek CallInst *CI = dyn_cast<CallInst>(I);
4843e457fe3SDavid van Moolenbroek if (CI && (CI->getCalledFunction() == function)) {
4853e457fe3SDavid van Moolenbroek continue;
4863e457fe3SDavid van Moolenbroek }
4873e457fe3SDavid van Moolenbroek I->replaceUsesOfWith(ParamValue, ParamCastInst);
4883e457fe3SDavid van Moolenbroek }
4893e457fe3SDavid van Moolenbroek }
4903e457fe3SDavid van Moolenbroek }
4913e457fe3SDavid van Moolenbroek W++;
4923e457fe3SDavid van Moolenbroek }
4933e457fe3SDavid van Moolenbroek
4943e457fe3SDavid van Moolenbroek // replace the call(s) to the standard function with calls to our function
4953e457fe3SDavid van Moolenbroek for (Function::iterator BI = wrapper->getBasicBlockList().begin(), BE = wrapper->getBasicBlockList().end(); BI != BE; ++BI) {
4963e457fe3SDavid van Moolenbroek unsigned pos = 0;
4973e457fe3SDavid van Moolenbroek unsigned bbSize = BI->getInstList().size();
4983e457fe3SDavid van Moolenbroek while (pos < bbSize) {
4993e457fe3SDavid van Moolenbroek BasicBlock::iterator it = BI->getInstList().begin();
5003e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < pos; i++) {
5013e457fe3SDavid van Moolenbroek it++;
5023e457fe3SDavid van Moolenbroek }
5033e457fe3SDavid van Moolenbroek Instruction *inst = &(*it);
5043e457fe3SDavid van Moolenbroek // find the calls to the standard function
5053e457fe3SDavid van Moolenbroek CallInst *callInst = dyn_cast<CallInst>(inst);
5063e457fe3SDavid van Moolenbroek if (callInst && callInst->getCalledFunction() && (callInst->getCalledFunction()->getFunctionType() == stdFunction->getFunctionType())
5073e457fe3SDavid van Moolenbroek && (!callInst->getCalledFunction()->getName().compare(stdFunction->getName()))) {
5083e457fe3SDavid van Moolenbroek CallSite CS = MagicUtil::getCallSiteFromInstruction(callInst);
5093e457fe3SDavid van Moolenbroek unsigned numStdParams = stdFunction->getFunctionType()->getNumParams();
5103e457fe3SDavid van Moolenbroek unsigned numParams = function->getFunctionType()->getNumParams();
5113e457fe3SDavid van Moolenbroek // construct the parameter array
5123e457fe3SDavid van Moolenbroek std::vector<Value*> callArgs(numParams, NULL);
5133e457fe3SDavid van Moolenbroek // first add the arguments that are common to the custom and standard function
5143e457fe3SDavid van Moolenbroek // add casts where necessary
5153e457fe3SDavid van Moolenbroek for (unsigned i = 0; i < numStdParams; i++) {
5163e457fe3SDavid van Moolenbroek Value *argValue = CS.getArgument(i);
5173e457fe3SDavid van Moolenbroek TYPECONST Type* paramType = function->getFunctionType()->getParamType(i);
5183e457fe3SDavid van Moolenbroek TYPECONST Type* argType = argValue->getType();
5193e457fe3SDavid van Moolenbroek if (paramType != argType) {
5203e457fe3SDavid van Moolenbroek assert(CastInst::isCastable(argType, paramType) && "The value of the argument cannot be "
5213e457fe3SDavid van Moolenbroek "casted to the parameter type required by the function to be called.");
5223e457fe3SDavid van Moolenbroek Instruction::CastOps opcode = CastInst::getCastOpcode(argValue, false, paramType, false);
5233e457fe3SDavid van Moolenbroek argValue = CastInst::Create(opcode, argValue, paramType, "", callInst);
5243e457fe3SDavid van Moolenbroek }
5253e457fe3SDavid van Moolenbroek callArgs[argMapping[i] - 1] = argValue;
5263e457fe3SDavid van Moolenbroek }
5273e457fe3SDavid van Moolenbroek // the other arguments are just forwarded from the wrapper's argument list
5283e457fe3SDavid van Moolenbroek // skip the magic arguments of the wrapper from the beginning of the argument list
5293e457fe3SDavid van Moolenbroek unsigned argOffset = isDealloc ? 0 : NUM_MAGIC_ARGS;
5303e457fe3SDavid van Moolenbroek for (unsigned i = argOffset; i < wrapper->getFunctionType()->getNumParams(); i++) {
5313e457fe3SDavid van Moolenbroek if (callArgs[i - argOffset] == NULL) {
5323e457fe3SDavid van Moolenbroek Value* arg = wrapperArgs[i];
5333e457fe3SDavid van Moolenbroek callArgs[i - argOffset] = arg;
5343e457fe3SDavid van Moolenbroek }
5353e457fe3SDavid van Moolenbroek }
5363e457fe3SDavid van Moolenbroek
5373e457fe3SDavid van Moolenbroek CallInst* newCallInst = MagicUtil::createCallInstruction(function, callArgs, "", callInst);
5383e457fe3SDavid van Moolenbroek newCallInst->takeName(callInst);
5393e457fe3SDavid van Moolenbroek MagicUtil::replaceCallInst(callInst, newCallInst, argOffset);
5403e457fe3SDavid van Moolenbroek }
5413e457fe3SDavid van Moolenbroek pos++;
5423e457fe3SDavid van Moolenbroek }
5433e457fe3SDavid van Moolenbroek }
5443e457fe3SDavid van Moolenbroek
5453e457fe3SDavid van Moolenbroek customWrapperSet.insert(wrapper);
5463e457fe3SDavid van Moolenbroek return wrapper;
5473e457fe3SDavid van Moolenbroek }
5483e457fe3SDavid van Moolenbroek
isCustomWrapper(Function * function)5493e457fe3SDavid van Moolenbroek inline bool MagicMemFunction::isCustomWrapper(Function *function)
5503e457fe3SDavid van Moolenbroek {
5513e457fe3SDavid van Moolenbroek return customWrapperSet.find(function) != customWrapperSet.end();
5523e457fe3SDavid van Moolenbroek }
5533e457fe3SDavid van Moolenbroek
5543e457fe3SDavid van Moolenbroek }
5553e457fe3SDavid van Moolenbroek
5563e457fe3SDavid van Moolenbroek #endif
5573e457fe3SDavid van Moolenbroek
558