static bool expandIntrinsic(Module *M, Intrinsic::ID ID) { SmallVector<Type *, 3> Types; Types.push_back(Type::getInt8PtrTy(M->getContext())); if (ID != Intrinsic::memset) Types.push_back(Type::getInt8PtrTy(M->getContext())); unsigned LengthTypePos = Types.size(); Types.push_back(Type::getInt64Ty(M->getContext())); std::string OldName = Intrinsic::getName(ID, Types); Function *OldIntrinsic = M->getFunction(OldName); if (!OldIntrinsic) return false; Types[LengthTypePos] = Type::getInt32Ty(M->getContext()); Function *NewIntrinsic = Intrinsic::getDeclaration(M, ID, Types); for (Value::use_iterator CallIter = OldIntrinsic->use_begin(), E = OldIntrinsic->use_end(); CallIter != E; ) { CallInst *Call = dyn_cast<CallInst>(*CallIter++); if (!Call) { report_fatal_error("CanonicalizeMemIntrinsics: Taking the address of an " "intrinsic is not allowed: " + OldName); } // This temporarily leaves Call non-well-typed. Call->setCalledFunction(NewIntrinsic); // Truncate the "len" argument. No overflow check. IRBuilder<> Builder(Call); Value *Length = Builder.CreateTrunc(Call->getArgOperand(2), Type::getInt32Ty(M->getContext()), "mem_len_truncate"); Call->setArgOperand(2, Length); } OldIntrinsic->eraseFromParent(); return true; }
void ExtractContracts::visitCallInst(CallInst &I) { if (auto F = I.getCalledFunction()) { auto name = F->getName(); if (name == Naming::CONTRACT_REQUIRES || name == Naming::CONTRACT_ENSURES || name == Naming::CONTRACT_INVARIANT) { validateAnnotation(I); if (auto J = dyn_cast<CallInst>(I.getArgOperand(0))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(0), I.getParent()); I.setArgOperand(0, CallInst::Create(EF, Args, "", &I)); modified = true; // TODO can we somehow force LLVM to consider calls to the obsoleted // forall, exists, etc., to be dead code? } else if (name == Naming::CONTRACT_FORALL || name == Naming::CONTRACT_EXISTS) { if (auto J = dyn_cast<CallInst>(I.getArgOperand(1))) if (auto G = J->getCalledFunction()) if (G->getName().find(Naming::CONTRACT_EXPR) != std::string::npos) return; Function* EF; std::vector<Value*> Args; tie(EF, Args) = extractExpression(I.getArgOperand(1), I.getParent()); I.setArgOperand(1, CallInst::Create(EF, Args, "", &I)); modified = true; } } }
void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, GlobalValue *Array, PointerType *arrayType) { LLVMContext &Context = MainFn->getContext(); Type *ArgVTy = PointerType::getUnqual(Type::getInt8PtrTy(Context)); PointerType *UIntPtr = arrayType ? arrayType : Type::getInt64PtrTy(Context); Module &M = *MainFn->getParent(); Constant *InitFn = M.getOrInsertFunction(FnName, Type::getInt32Ty(Context), Type::getInt32Ty(Context), ArgVTy, UIntPtr, Type::getInt64Ty(Context), (Type *)0); // This could force argc and argv into programs that wouldn't otherwise have // them, but instead we just pass null values in. std::vector<Value*> Args(4); Args[0] = Constant::getNullValue(Type::getInt32Ty(Context)); Args[1] = Constant::getNullValue(ArgVTy); // Skip over any allocas in the entry block. BasicBlock *Entry = MainFn->begin(); BasicBlock::iterator InsertPos = Entry->begin(); while (isa<AllocaInst>(InsertPos)) ++InsertPos; std::vector<Constant*> GEPIndices(2, Constant::getNullValue(Type::getInt64Ty(Context))); unsigned NumElements = 0; if (Array) { Args[2] = ConstantExpr::getGetElementPtr(Array, GEPIndices); NumElements = cast<ArrayType>(Array->getType()->getElementType())->getNumElements(); } else { // If this profiling instrumentation doesn't have a constant array, just // pass null. Args[2] = ConstantPointerNull::get(UIntPtr); } Args[3] = ConstantInt::get(Type::getInt64Ty(Context), NumElements); CallInst *InitCall = CallInst::Create(InitFn, Args, "newargc", InsertPos); // If argc or argv are not available in main, just pass null values in. Function::arg_iterator AI; switch (MainFn->arg_size()) { default: case 2: AI = MainFn->arg_begin(); ++AI; if (AI->getType() != ArgVTy) { Instruction::CastOps opcode = CastInst::getCastOpcode(AI, false, ArgVTy, false); InitCall->setArgOperand(1, CastInst::Create(opcode, AI, ArgVTy, "argv.cast", InitCall)); } else { InitCall->setArgOperand(1, AI); } /* FALL THROUGH */ case 1: AI = MainFn->arg_begin(); // If the program looked at argc, have it look at the return value of the // init call instead. if (!AI->getType()->isIntegerTy(32)) { Instruction::CastOps opcode; if (!AI->use_empty()) { opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true); AI->replaceAllUsesWith( CastInst::Create(opcode, InitCall, AI->getType(), "", InsertPos)); } opcode = CastInst::getCastOpcode(AI, true, Type::getInt32Ty(Context), true); InitCall->setArgOperand(0, CastInst::Create(opcode, AI, Type::getInt32Ty(Context), "argc.cast", InitCall)); } else { AI->replaceAllUsesWith(InitCall); InitCall->setArgOperand(0, AI); } case 0: break; } }
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(); }