static Value::use_iterator skipToNextUser(Value::use_iterator I, Value::use_iterator End) { User *CurUser = I->getUser(); ++I; while (I != End && I->getUser() == CurUser) ++I; return I; }
void DuettoNativeRewriter::rewriteConstructorImplementation(Module& M, Function& F) { //Copy the code in a function with the right signature Function* newFunc=getReturningConstructor(M, &F); if(!newFunc->empty()) return; //Visit each instruction and take note of the ones that needs to be replaced Function::const_iterator B=F.begin(); Function::const_iterator BE=F.end(); ValueToValueMapTy valueMap; CallInst* lowerConstructor = NULL; const CallInst* oldLowerConstructor = NULL; for(;B!=BE;++B) { BasicBlock::const_iterator I=B->begin(); BasicBlock::const_iterator IE=B->end(); for(;I!=IE;++I) { if(I->getOpcode()!=Instruction::Call) continue; const CallInst* callInst=cast<CallInst>(&(*I)); Function* f=callInst->getCalledFunction(); if(!f) continue; const char* startOfType; const char* endOfType; if(!DuettoNativeRewriter::isBuiltinConstructor(f->getName().data(), startOfType, endOfType)) continue; //Check that the constructor is for 'this' if(callInst->getOperand(0)!=F.arg_begin()) continue; //If this is another constructor for the same type, change it to a //returning constructor and use it as the 'this' argument Function* newFunc = getReturningConstructor(M, f); llvm::SmallVector<Value*, 4> newArgs; for(unsigned i=1;i<callInst->getNumArgOperands();i++) newArgs.push_back(callInst->getArgOperand(i)); lowerConstructor = CallInst::Create(newFunc, newArgs); oldLowerConstructor = callInst; break; } if(lowerConstructor) break; } //Clone the linkage first newFunc->setLinkage(F.getLinkage()); Function::arg_iterator origArg=++F.arg_begin(); Function::arg_iterator newArg=newFunc->arg_begin(); valueMap.insert(make_pair(F.arg_begin(), lowerConstructor)); for(unsigned i=1;i<F.arg_size();i++) { valueMap.insert(make_pair(&(*origArg), &(*newArg))); ++origArg; ++newArg; } SmallVector<ReturnInst*, 4> returns; CloneFunctionInto(newFunc, &F, valueMap, false, returns); //Find the right place to add the base construtor call assert(lowerConstructor->getNumArgOperands()<=1 && "Native constructors with multiple args are not supported"); Instruction* callPred = NULL; if (lowerConstructor->getNumArgOperands()==1 && Instruction::classof(lowerConstructor->getArgOperand(0))) { //Switch the argument to the one in the new func lowerConstructor->setArgOperand(0, valueMap[lowerConstructor->getArgOperand(0)]); callPred = cast<Instruction>(lowerConstructor->getArgOperand(0)); } else callPred = &newFunc->getEntryBlock().front(); //Add add it lowerConstructor->insertAfter(callPred); //Override the returs values for(unsigned i=0;i<returns.size();i++) { Instruction* newInst = ReturnInst::Create(M.getContext(),lowerConstructor); newInst->insertBefore(returns[i]); returns[i]->removeFromParent(); } //Recursively move all the users of the lower constructor after the call itself Instruction* insertPoint = lowerConstructor->getNextNode(); SmallVector<Value*, 4> usersQueue(lowerConstructor->getNumUses()); unsigned int i; Value::use_iterator it; for(i=usersQueue.size()-1,it=lowerConstructor->use_begin();it!=lowerConstructor->use_end();++it,i--) usersQueue[i]=it->getUser(); SmallSet<Instruction*, 4> movedInstructions; while(!usersQueue.empty()) { Instruction* cur=dyn_cast<Instruction>(usersQueue.pop_back_val()); if(!cur) continue; if(movedInstructions.count(cur)) continue; movedInstructions.insert(cur); cur->moveBefore(insertPoint); //Add users of this instrucution as well usersQueue.resize(usersQueue.size()+cur->getNumUses()); for(i=usersQueue.size()-1,it=cur->use_begin();it!=cur->use_end();++it,i--) usersQueue[i]=it->getUser(); } cast<Instruction>(valueMap[oldLowerConstructor])->eraseFromParent(); }