// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Clone functions that take GEPs as arguments // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool GEPExprArgs::runOnModule(Module& M) { bool changed; do { changed = false; for (Module::iterator F = M.begin(); F != M.end(); ++F){ for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { CallInst *CI = dyn_cast<CallInst>(I++); if(!CI) continue; if(CI->hasByValArgument()) continue; // if the GEP calls a function, that is externally defined, // or might be changed, ignore this call site. Function *F = CI->getCalledFunction(); if (!F || (F->isDeclaration() || F->mayBeOverridden())) continue; if(F->hasStructRetAttr()) continue; if(F->isVarArg()) continue; // find the argument we must replace Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); unsigned argNum = 1; for(; argNum < CI->getNumOperands();argNum++, ++ai) { if(ai->use_empty()) continue; if (isa<GEPOperator>(CI->getOperand(argNum))) break; } // if no argument was a GEP operator to be changed if(ai == ae) continue; GEPOperator *GEP = dyn_cast<GEPOperator>(CI->getOperand(argNum)); if(!GEP->hasAllConstantIndices()) continue; // Construct the new Type // Appends the struct Type at the beginning std::vector<Type*>TP; TP.push_back(GEP->getPointerOperand()->getType()); for(unsigned c = 1; c < CI->getNumOperands();c++) { TP.push_back(CI->getOperand(c)->getType()); } //return type is same as that of original instruction FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); Function *NewF; numSimplified++; if(numSimplified > 800) return true; NewF = Function::Create(NewFTy, GlobalValue::InternalLinkage, F->getName().str() + ".TEST", &M); Function::arg_iterator NI = NewF->arg_begin(); NI->setName("GEParg"); ++NI; ValueToValueMapTy ValueMap; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) { ValueMap[II] = NI; NI->setName(II->getName()); NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1)); } NewF->setAttributes(NewF->getAttributes().addAttr( 0, F->getAttributes().getRetAttributes())); // Perform the cloning. SmallVector<ReturnInst*,100> Returns; CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NewF->setAttributes(NewF->getAttributes().addAttr( ~0, F->getAttributes().getFnAttributes())); //Get the point to insert the GEP instr. SmallVector<Value*, 8> Ops(CI->op_begin()+1, CI->op_end()); Instruction *InsertPoint; for (BasicBlock::iterator insrt = NewF->front().begin(); isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;} NI = NewF->arg_begin(); SmallVector<Value*, 8> Indices; Indices.append(GEP->op_begin()+1, GEP->op_end()); GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast<Value>(NI), Indices, "", InsertPoint); fargs.at(argNum)->replaceAllUsesWith(GEP_new); unsigned j = argNum + 1; for(; j < CI->getNumOperands();j++) { if(CI->getOperand(j) == GEP) fargs.at(j)->replaceAllUsesWith(GEP_new); } SmallVector<AttributeWithIndex, 8> AttributesVec; // Get the initial attributes of the call AttrListPtr CallPAL = CI->getAttributes(); Attributes RAttrs = CallPAL.getRetAttributes(); Attributes FnAttrs = CallPAL.getFnAttributes(); if (RAttrs) AttributesVec.push_back(AttributeWithIndex::get(0, RAttrs)); SmallVector<Value*, 8> Args; Args.push_back(GEP->getPointerOperand()); for(unsigned j =1;j<CI->getNumOperands();j++) { Args.push_back(CI->getOperand(j)); // position in the AttributesVec if (Attributes Attrs = CallPAL.getParamAttributes(j)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } // Create the new attributes vec. if (FnAttrs != Attribute::None) AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); CI->eraseFromParent(); changed = true; } } } } while(changed); return true; }
/// DeleteDeadVarargs - If this is an function that takes a ... list, and if /// llvm.vastart is never called, the varargs list is dead for the function. bool DAE::DeleteDeadVarargs(Function &Fn) { assert(Fn.getFunctionType()->isVarArg() && "Function isn't varargs!"); if (Fn.isDeclaration() || !Fn.hasLocalLinkage()) return false; // Ensure that the function is only directly called. if (Fn.hasAddressTaken()) return false; // Okay, we know we can transform this function if safe. Scan its body // looking for calls to llvm.vastart. for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) { if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { if (II->getIntrinsicID() == Intrinsic::vastart) return false; } } } // If we get here, there are no calls to llvm.vastart in the function body, // remove the "..." and adjust all the calls. // Start by computing a new prototype for the function, which is the same as // the old function, but doesn't have isVarArg set. const FunctionType *FTy = Fn.getFunctionType(); std::vector<const Type*> Params(FTy->param_begin(), FTy->param_end()); FunctionType *NFTy = FunctionType::get(FTy->getReturnType(), Params, false); unsigned NumArgs = Params.size(); // Create the new function body and insert it into the module... Function *NF = Function::Create(NFTy, Fn.getLinkage()); NF->copyAttributesFrom(&Fn); Fn.getParent()->getFunctionList().insert(&Fn, NF); NF->takeName(&Fn); // Loop over all of the callers of the function, transforming the call sites // to pass in a smaller number of arguments into the new function. // std::vector<Value*> Args; while (!Fn.use_empty()) { CallSite CS = CallSite::get(Fn.use_back()); Instruction *Call = CS.getInstruction(); // Pass all the same arguments. Args.assign(CS.arg_begin(), CS.arg_begin()+NumArgs); // Drop any attributes that were on the vararg arguments. AttrListPtr PAL = CS.getAttributes(); if (!PAL.isEmpty() && PAL.getSlot(PAL.getNumSlots() - 1).Index > NumArgs) { SmallVector<AttributeWithIndex, 8> AttributesVec; for (unsigned i = 0; PAL.getSlot(i).Index <= NumArgs; ++i) AttributesVec.push_back(PAL.getSlot(i)); if (Attributes FnAttrs = PAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, FnAttrs)); PAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); } Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args.begin(), Args.end(), "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(PAL); } else { New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(PAL); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } if (MDNode *N = Call->getDbgMetadata()) New->setDbgMetadata(N); Args.clear(); if (!Call->use_empty()) Call->replaceAllUsesWith(New); New->takeName(Call); // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } // Since we have now created the new function, splice the body of the old // function right into the new function, leaving the old rotting hulk of the // function empty. NF->getBasicBlockList().splice(NF->begin(), Fn.getBasicBlockList()); // Loop over the argument list, transfering uses of the old arguments over to // the new arguments, also transfering over the names as well. While we're at // it, remove the dead arguments from the DeadArguments list. // for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end(), I2 = NF->arg_begin(); I != E; ++I, ++I2) { // Move the name and users over to the new version. I->replaceAllUsesWith(I2); I2->takeName(I); } // Finally, nuke the old function. Fn.eraseFromParent(); return true; }