/* * Generate a piece of code in F that enforces I, protecting calls to call */ void protectCall(Function* F, Function* const call, const FunctionContract& I) { std::vector<Value*> ary; ary.reserve(F->getArgumentList().size()); for (Function::ArgumentListType::iterator i = F->getArgumentList().begin(), e = F->getArgumentList().end(); i != e; ++i) { ary.push_back(&*i); } BasicBlock* call_bb = BasicBlock::Create(F->getContext()); { F->getBasicBlockList().push_back(call_bb); IRBuilder<> builder(call_bb); if (F->getReturnType() == Type::getVoidTy(F->getContext())) { CallInst* ci = builder.CreateCall(call, ArrayRef<Value*> (ary), ""); ci->setTailCall(true); builder.CreateRetVoid(); } else { CallInst* ci = builder.CreateCall(call, ArrayRef<Value*> (ary), "delegate"); ci->setTailCall(true); builder.CreateRet(ci); } } BasicBlock* fail_bb = BasicBlock::Create(F->getContext()); { std::vector<Type*> arg_types; arg_types.reserve(1); arg_types.push_back(Type::getInt8PtrTy(F->getContext())); FunctionType* policyErrorType = FunctionType::get(Type::getVoidTy( F->getContext()), ArrayRef<Type*> (arg_types), true); Constant* policyError = F->getParent()->getOrInsertFunction( "policyError", policyErrorType); F->getBasicBlockList().push_back(fail_bb); IRBuilder<> builder(fail_bb); Constant* name = llvm::ConstantDataArray::getString(F->getContext(), F->getName(), true); GlobalVariable *gv = new GlobalVariable(*F->getParent(), name->getType(), true, GlobalVariable::LinkOnceODRLinkage, name, ""); Value* v = builder.CreateConstGEP2_32(gv, 0, 0); ary.insert(ary.begin(), v); builder.CreateCall(policyError, ArrayRef<Value*> (ary), ""); if (F->getReturnType() == Type::getVoidTy(F->getContext())) { builder.CreateRetVoid(); } else { builder.CreateRet(UndefValue::get(F->getReturnType())); } } I.emitEntryTest(F, call_bb, fail_bb); }
/// Generate a thunk that puts the LSDA of ParentFunc in EAX and then calls /// PersonalityFn, forwarding the parameters passed to PEXCEPTION_ROUTINE: /// typedef _EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)( /// _EXCEPTION_RECORD *, void *, _CONTEXT *, void *); /// We essentially want this code: /// movl $lsda, %eax /// jmpl ___CxxFrameHandler3 Function *WinEHStatePass::generateLSDAInEAXThunk(Function *ParentFunc) { LLVMContext &Context = ParentFunc->getContext(); Type *Int32Ty = Type::getInt32Ty(Context); Type *Int8PtrType = Type::getInt8PtrTy(Context); Type *ArgTys[5] = {Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType, Int8PtrType}; FunctionType *TrampolineTy = FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 4), /*isVarArg=*/false); FunctionType *TargetFuncTy = FunctionType::get(Int32Ty, makeArrayRef(&ArgTys[0], 5), /*isVarArg=*/false); Function *Trampoline = Function::Create( TrampolineTy, GlobalValue::InternalLinkage, Twine("__ehhandler$") + ParentFunc->getName(), TheModule); BasicBlock *EntryBB = BasicBlock::Create(Context, "entry", Trampoline); IRBuilder<> Builder(EntryBB); Value *LSDA = emitEHLSDA(Builder, ParentFunc); Value *CastPersonality = Builder.CreateBitCast(PersonalityFn, TargetFuncTy->getPointerTo()); auto AI = Trampoline->arg_begin(); Value *Args[5] = {LSDA, AI++, AI++, AI++, AI++}; CallInst *Call = Builder.CreateCall(CastPersonality, Args); // Can't use musttail due to prototype mismatch, but we can use tail. Call->setTailCall(true); // Set inreg so we pass it in EAX. Call->addAttribute(1, Attribute::InReg); Builder.CreateRet(Call); return Trampoline; }
void WorklessInstrument::CreateIfElseBlock(Loop * pLoop, vector<BasicBlock *> & vecAdded) { BasicBlock * pPreHeader = pLoop->getLoopPreheader(); BasicBlock * pHeader = pLoop->getHeader(); Function * pInnerFunction = pPreHeader->getParent(); Module * pModule = pPreHeader->getParent()->getParent(); BasicBlock * pElseBody = NULL; TerminatorInst * pTerminator = NULL; BranchInst * pBranch = NULL; LoadInst * pLoad1 = NULL; LoadInst * pLoad2 = NULL; LoadInst * pLoadnumGlobalCounter = NULL; BinaryOperator * pAddOne = NULL; StoreInst * pStoreNew = NULL; CmpInst * pCmp = NULL; CallInst * pCall = NULL; StoreInst * pStore = NULL; AttributeSet emptySet; pTerminator = pPreHeader->getTerminator(); pLoadnumGlobalCounter = new LoadInst(this->numGlobalCounter, "", false, pTerminator); pLoadnumGlobalCounter->setAlignment(8); pAddOne = BinaryOperator::Create(Instruction::Add, pLoadnumGlobalCounter, this->ConstantLong1, "add", pTerminator); pStoreNew = new StoreInst(pAddOne, this->numGlobalCounter, false, pTerminator); pStoreNew->setAlignment(8); pElseBody = BasicBlock::Create(pModule->getContext(), ".else.body.CPI", pInnerFunction, 0); pLoad2 = new LoadInst(this->CURRENT_SAMPLE, "", false, pTerminator); pLoad2->setAlignment(8); pCmp = new ICmpInst(pTerminator, ICmpInst::ICMP_SLT, pAddOne, pLoad2, ""); pBranch = BranchInst::Create(pHeader, pElseBody, pCmp ); ReplaceInstWithInst(pTerminator, pBranch); pLoad1 = new LoadInst(this->SAMPLE_RATE, "", false, pElseBody); pCall = CallInst::Create(this->geo, pLoad1, "", pElseBody); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", pElseBody); //pBinary = BinaryOperator::Create(Instruction::Add, pLoad2, pCast, "add", pIfBody); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, pElseBody); pStore->setAlignment(8); pStore = new StoreInst(this->ConstantLong0, this->numGlobalCounter, false, pElseBody); pStore->setAlignment(8); pLoad1 = new LoadInst(this->numInstances, "", false, pElseBody); pLoad1->setAlignment(8); pAddOne = BinaryOperator::Create(Instruction::Add, pLoad1, this->ConstantLong1, "add", pElseBody); pStore = new StoreInst(pAddOne, this->numInstances, false, pElseBody); pStore->setAlignment(8); vecAdded.push_back(pPreHeader); vecAdded.push_back(pElseBody); }
Function* PrepareCSI::switchIndirect(Function* F, GlobalVariable* switcher, vector<Function*>& replicas){ F->dropAllReferences(); BasicBlock* newEntry = BasicBlock::Create(*Context, "newEntry", F); vector<Value*> callArgs; for(Function::arg_iterator k = F->arg_begin(), ke = F->arg_end(); k != ke; ++k) callArgs.push_back(k); // set up the switch LoadInst* whichCall = new LoadInst(switcher, "chooseCall", true, newEntry); SwitchInst* callSwitch = NULL; // stuff we need IntegerType* tInt = Type::getInt32Ty(*Context); // create one bb for each possible call (instrumentation scheme) bool aZero = false; for(unsigned int i = 0; i < replicas.size(); ++i){ Function* newF = replicas[i]; BasicBlock* bb = BasicBlock::Create(*Context, "call", F); if(callSwitch == NULL){ callSwitch = SwitchInst::Create(whichCall, bb, replicas.size(), newEntry); } string funcName = newF->getName().str(); if(funcName.length() > 5 && funcName.substr(funcName.length()-5, 5) == "$none"){ callSwitch->addCase(ConstantInt::get(tInt, 0), bb); if(aZero) report_fatal_error("multiple defaults for function '" + F->getName() + "'"); aZero = true; } else callSwitch->addCase(ConstantInt::get(tInt, i+1), bb); CallInst* oneCall = CallInst::Create(newF, callArgs, (F->getReturnType()->isVoidTy()) ? "" : "theCall", bb); oneCall->setTailCall(true); if(F->getReturnType()->isVoidTy()) ReturnInst::Create(*Context, bb); else ReturnInst::Create(*Context, oneCall, bb); } // note that we intentionally started numbering the cases from 1 so that the // zero case is reserved for the uninstrumented variant (if there is one) if(!aZero) switcher->setInitializer(ConstantInt::get(tInt, 1)); return(F); }
/// WriteThunk - Replace G with a simple tail call to bitcast(F). Also replace /// direct uses of G with bitcast(F). Deletes G. void MergeFunctions::WriteThunk(Function *F, Function *G) const { if (!G->mayBeOverridden()) { // Redirect direct callers of G to F. Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); for (Value::use_iterator UI = G->use_begin(), UE = G->use_end(); UI != UE;) { Value::use_iterator TheIter = UI; ++UI; CallSite CS(*TheIter); if (CS && CS.isCallee(TheIter)) TheIter.getUse().set(BitcastF); } } // If G was internal then we may have replaced all uses of G with F. If so, // stop here and delete G. There's no need for a thunk. if (G->hasLocalLinkage() && G->use_empty()) { G->eraseFromParent(); return; } Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", G->getParent()); BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG); IRBuilder<false> Builder(BB); SmallVector<Value *, 16> Args; unsigned i = 0; const FunctionType *FFTy = F->getFunctionType(); for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end(); AI != AE; ++AI) { Args.push_back(Builder.CreateBitCast(AI, FFTy->getParamType(i))); ++i; } CallInst *CI = Builder.CreateCall(F, Args.begin(), Args.end()); CI->setTailCall(); CI->setCallingConv(F->getCallingConv()); if (NewG->getReturnType()->isVoidTy()) { Builder.CreateRetVoid(); } else { Builder.CreateRet(Builder.CreateBitCast(CI, NewG->getReturnType())); } NewG->copyAttributesFrom(G); NewG->takeName(G); G->replaceAllUsesWith(NewG); G->eraseFromParent(); DEBUG(dbgs() << "WriteThunk: " << NewG->getName() << '\n'); ++NumThunksWritten; }
static InstTransResult doCallPC(InstPtr ip, BasicBlock *&b, VA tgtAddr) { Module *M = b->getParent()->getParent(); Function *ourF = b->getParent(); //insert a call to the call function //this function will be a translated function that we emit, so we should //be able to look it up in our module. std::string fname = "sub_"+to_string<VA>(tgtAddr, std::hex); Function *F = M->getFunction(fname); TASSERT( F != NULL, "Could not find function: " + fname ); writeFakeReturnAddr(b); //we need to wrap up our current context writeLocalsToContext(b, 32, ABICallStore); //make the call, the only argument should be our parents arguments TASSERT(ourF->arg_size() == 1, ""); std::vector<Value*> subArgs; subArgs.push_back(ourF->arg_begin()); CallInst *c = CallInst::Create(F, subArgs, "", b); c->setCallingConv(F->getCallingConv()); if ( ip->has_local_noreturn() ) { // noreturn functions just hit unreachable std::cout << __FUNCTION__ << ": Adding Unreachable Instruction to local noreturn" << std::endl; c->setDoesNotReturn(); c->setTailCall(); Value *unreachable = new UnreachableInst(b->getContext(), b); return EndBlock; } //spill our context back writeContextToLocals(b, 32, ABIRetSpill); //and we can continue to run the old code return ContinueBlock; }
// Replace G with a simple tail call to bitcast(F). Also replace direct uses // of G with bitcast(F). Deletes G. void MergeFunctions::writeThunk(Function *F, Function *G) { if (!G->mayBeOverridden()) { // Redirect direct callers of G to F. replaceDirectCallers(G, F); } // If G was internal then we may have replaced all uses of G with F. If so, // stop here and delete G. There's no need for a thunk. if (G->hasLocalLinkage() && G->use_empty()) { G->eraseFromParent(); return; } Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", G->getParent()); BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG); IRBuilder<false> Builder(BB); SmallVector<Value *, 16> Args; unsigned i = 0; FunctionType *FFTy = F->getFunctionType(); for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end(); AI != AE; ++AI) { Args.push_back(createCast(Builder, (Value*)AI, FFTy->getParamType(i))); ++i; } CallInst *CI = Builder.CreateCall(F, Args); CI->setTailCall(); CI->setCallingConv(F->getCallingConv()); if (NewG->getReturnType()->isVoidTy()) { Builder.CreateRetVoid(); } else { Builder.CreateRet(createCast(Builder, CI, NewG->getReturnType())); } NewG->copyAttributesFrom(G); NewG->takeName(G); removeUsers(G); G->replaceAllUsesWith(NewG); G->eraseFromParent(); DEBUG(dbgs() << "writeThunk: " << NewG->getName() << '\n'); ++NumThunksWritten; }
void makeStub(Function &F, Value &ImplPointer) { assert(F.isDeclaration() && "Can't turn a definition into a stub."); assert(F.getParent() && "Function isn't in a module."); Module &M = *F.getParent(); BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F); IRBuilder<> Builder(EntryBlock); LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer); std::vector<Value*> CallArgs; for (auto &A : F.args()) CallArgs.push_back(&A); CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs); Call->setTailCall(); Call->setAttributes(F.getAttributes()); if (F.getReturnType()->isVoidTy()) Builder.CreateRetVoid(); else Builder.CreateRet(Call); }
/// Replace \p Thunk with a simple tail call to \p ToFunc. Also add parameters /// to the call to \p ToFunc, which are defined by the FuncIdx's value in /// \p Params. void SwiftMergeFunctions::writeThunk(Function *ToFunc, Function *Thunk, const ParamInfos &Params, unsigned FuncIdx) { // Delete the existing content of Thunk. Thunk->dropAllReferences(); BasicBlock *BB = BasicBlock::Create(Thunk->getContext(), "", Thunk); IRBuilder<> Builder(BB); SmallVector<Value *, 16> Args; unsigned ParamIdx = 0; FunctionType *ToFuncTy = ToFunc->getFunctionType(); // Add arguments which are passed through Thunk. for (Argument & AI : Thunk->args()) { Args.push_back(createCast(Builder, &AI, ToFuncTy->getParamType(ParamIdx))); ++ParamIdx; } // Add new arguments defined by Params. for (const ParamInfo &PI : Params) { assert(ParamIdx < ToFuncTy->getNumParams()); Args.push_back(createCast(Builder, PI.Values[FuncIdx], ToFuncTy->getParamType(ParamIdx))); ++ParamIdx; } CallInst *CI = Builder.CreateCall(ToFunc, Args); CI->setTailCall(); CI->setCallingConv(ToFunc->getCallingConv()); CI->setAttributes(ToFunc->getAttributes()); if (Thunk->getReturnType()->isVoidTy()) { Builder.CreateRetVoid(); } else { Builder.CreateRet(createCast(Builder, CI, Thunk->getReturnType())); } LLVM_DEBUG(dbgs() << " writeThunk: " << Thunk->getName() << '\n'); ++NumSwiftThunksWritten; }
static void ThunkGToF(Function *F, Function *G) { Function *NewG = Function::Create(G->getFunctionType(), G->getLinkage(), "", G->getParent()); BasicBlock *BB = BasicBlock::Create(F->getContext(), "", NewG); std::vector<Value *> Args; unsigned i = 0; const FunctionType *FFTy = F->getFunctionType(); for (Function::arg_iterator AI = NewG->arg_begin(), AE = NewG->arg_end(); AI != AE; ++AI) { if (FFTy->getParamType(i) == AI->getType()) Args.push_back(AI); else { Value *BCI = new BitCastInst(AI, FFTy->getParamType(i), "", BB); Args.push_back(BCI); } ++i; } CallInst *CI = CallInst::Create(F, Args.begin(), Args.end(), "", BB); CI->setTailCall(); CI->setCallingConv(F->getCallingConv()); if (NewG->getReturnType() == Type::getVoidTy(F->getContext())) { ReturnInst::Create(F->getContext(), BB); } else if (CI->getType() != NewG->getReturnType()) { Value *BCI = new BitCastInst(CI, NewG->getReturnType(), "", BB); ReturnInst::Create(F->getContext(), BCI, BB); } else { ReturnInst::Create(F->getContext(), CI, BB); } NewG->copyAttributesFrom(G); NewG->takeName(G); G->replaceAllUsesWith(NewG); G->eraseFromParent(); // TODO: look at direct callers to G and make them all direct callers to F. }
/// run - Start execution with the specified function and arguments. /// GenericValue JIT::runFunction(Function *F, const std::vector<GenericValue> &ArgValues) { assert(F && "Function *F was null at entry to run()"); void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); const FunctionType *FTy = F->getFunctionType(); const Type *RetTy = FTy->getReturnType(); assert((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && "Wrong number of arguments passed into function!"); assert(FTy->getNumParams() == ArgValues.size() && "This doesn't support passing arguments through varargs (yet)!"); // Handle some common cases first. These cases correspond to common `main' // prototypes. if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { switch (ArgValues.size()) { case 3: if (FTy->getParamType(0)->isIntegerTy(32) && FTy->getParamType(1)->isPointerTy() && FTy->getParamType(2)->isPointerTy()) { int (*PF)(int, char **, const char **) = (int(*)(int, char **, const char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]), (const char **)GVTOP(ArgValues[2]))); return rv; } break; case 2: if (FTy->getParamType(0)->isIntegerTy(32) && FTy->getParamType(1)->isPointerTy()) { int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]))); return rv; } break; case 1: if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) { GenericValue rv; int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); return rv; } break; } } // Handle cases where no arguments are passed first. if (ArgValues.empty()) { GenericValue rv; switch (RetTy->getTypeID()) { default: llvm_unreachable("Unknown return type for function call!"); case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); if (BitWidth == 1) rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); else if (BitWidth <= 8) rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); else if (BitWidth <= 16) rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); else if (BitWidth <= 32) rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); else if (BitWidth <= 64) rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); else llvm_unreachable("Integer types > 64 bits not supported"); return rv; } case Type::VoidTyID: rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); return rv; case Type::FloatTyID: rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); return rv; case Type::DoubleTyID: rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); return rv; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: llvm_unreachable("long double not supported yet"); return rv; case Type::PointerTyID: return PTOGV(((void*(*)())(intptr_t)FPtr)()); } } // Okay, this is not one of our quick and easy cases. Because we don't have a // full FFI, we have to codegen a nullary stub function that just calls the // function we are interested in, passing in constants for all of the // arguments. Make this function and return. // First, create the function. FunctionType *STy=FunctionType::get(RetTy, false); Function *Stub = Function::Create(STy, Function::InternalLinkage, "", F->getParent()); // Insert a basic block. BasicBlock *StubBB = BasicBlock::Create(F->getContext(), "", Stub); // Convert all of the GenericValue arguments over to constants. Note that we // currently don't support varargs. SmallVector<Value*, 8> Args; for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) { Constant *C = 0; const Type *ArgTy = FTy->getParamType(i); const GenericValue &AV = ArgValues[i]; switch (ArgTy->getTypeID()) { default: llvm_unreachable("Unknown argument type for function call!"); case Type::IntegerTyID: C = ConstantInt::get(F->getContext(), AV.IntVal); break; case Type::FloatTyID: C = ConstantFP::get(F->getContext(), APFloat(AV.FloatVal)); break; case Type::DoubleTyID: C = ConstantFP::get(F->getContext(), APFloat(AV.DoubleVal)); break; case Type::PPC_FP128TyID: case Type::X86_FP80TyID: case Type::FP128TyID: C = ConstantFP::get(F->getContext(), APFloat(AV.IntVal)); break; case Type::PointerTyID: void *ArgPtr = GVTOP(AV); if (sizeof(void*) == 4) C = ConstantInt::get(Type::getInt32Ty(F->getContext()), (int)(intptr_t)ArgPtr); else C = ConstantInt::get(Type::getInt64Ty(F->getContext()), (intptr_t)ArgPtr); // Cast the integer to pointer C = ConstantExpr::getIntToPtr(C, ArgTy); break; } Args.push_back(C); } CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(), "", StubBB); TheCall->setCallingConv(F->getCallingConv()); TheCall->setTailCall(); if (!TheCall->getType()->isVoidTy()) // Return result of the call. ReturnInst::Create(F->getContext(), TheCall, StubBB); else ReturnInst::Create(F->getContext(), StubBB); // Just return void. // Finally, call our nullary stub function. GenericValue Result = runFunction(Stub, std::vector<GenericValue>()); // Erase it, since no other function can have a reference to it. Stub->eraseFromParent(); // And return the result. return Result; }
/// DoPromotion - This method actually performs the promotion of the specified /// arguments, and returns the new function. At this point, we know that it's /// safe to do so. CallGraphNode *ArgPromotion::DoPromotion(Function *F, SmallPtrSetImpl<Argument*> &ArgsToPromote, SmallPtrSetImpl<Argument*> &ByValArgsToTransform) { // Start by computing a new prototype for the function, which is the same as // the old function, but has modified arguments. FunctionType *FTy = F->getFunctionType(); std::vector<Type*> Params; typedef std::set<IndicesVector> ScalarizeTable; // ScalarizedElements - If we are promoting a pointer that has elements // accessed out of it, keep track of which elements are accessed so that we // can add one argument for each. // // Arguments that are directly loaded will have a zero element value here, to // handle cases where there are both a direct load and GEP accesses. // std::map<Argument*, ScalarizeTable> ScalarizedElements; // OriginalLoads - Keep track of a representative load instruction from the // original function so that we can tell the alias analysis implementation // what the new GEP/Load instructions we are inserting look like. // We need to keep the original loads for each argument and the elements // of the argument that are accessed. std::map<std::pair<Argument*, IndicesVector>, LoadInst*> OriginalLoads; // Attribute - Keep track of the parameter attributes for the arguments // that we are *not* promoting. For the ones that we do promote, the parameter // attributes are lost SmallVector<AttributeSet, 8> AttributesVec; const AttributeSet &PAL = F->getAttributes(); // Add any return attributes. if (PAL.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(F->getContext(), PAL.getRetAttributes())); // First, determine the new argument list unsigned ArgIndex = 1; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgIndex) { if (ByValArgsToTransform.count(I)) { // Simple byval argument? Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) Params.push_back(STy->getElementType(i)); ++NumByValArgsPromoted; } else if (!ArgsToPromote.count(I)) { // Unchanged argument Params.push_back(I->getType()); AttributeSet attrs = PAL.getParamAttributes(ArgIndex); if (attrs.hasAttributes(ArgIndex)) { AttrBuilder B(attrs, ArgIndex); AttributesVec. push_back(AttributeSet::get(F->getContext(), Params.size(), B)); } } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) ++NumArgumentsDead; } else { // Okay, this is being promoted. This means that the only uses are loads // or GEPs which are only used by loads // In this table, we will track which indices are loaded from the argument // (where direct loads are tracked as no indices). ScalarizeTable &ArgIndices = ScalarizedElements[I]; for (User *U : I->users()) { Instruction *UI = cast<Instruction>(U); assert(isa<LoadInst>(UI) || isa<GetElementPtrInst>(UI)); IndicesVector Indices; Indices.reserve(UI->getNumOperands() - 1); // Since loads will only have a single operand, and GEPs only a single // non-index operand, this will record direct loads without any indices, // and gep+loads with the GEP indices. for (User::op_iterator II = UI->op_begin() + 1, IE = UI->op_end(); II != IE; ++II) Indices.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Indices.size() == 1 && Indices.front() == 0) Indices.clear(); ArgIndices.insert(Indices); LoadInst *OrigLoad; if (LoadInst *L = dyn_cast<LoadInst>(UI)) OrigLoad = L; else // Take any load, we will use it only to update Alias Analysis OrigLoad = cast<LoadInst>(UI->user_back()); OriginalLoads[std::make_pair(I, Indices)] = OrigLoad; } // Add a parameter to the function for each element passed in. for (ScalarizeTable::iterator SI = ArgIndices.begin(), E = ArgIndices.end(); SI != E; ++SI) { // not allowed to dereference ->begin() if size() is 0 Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), *SI)); assert(Params.back()); } if (ArgIndices.size() == 1 && ArgIndices.begin()->empty()) ++NumArgumentsPromoted; else ++NumAggregatesPromoted; } } // Add any function attributes. if (PAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(FTy->getContext(), PAL.getFnAttributes())); Type *RetTy = FTy->getReturnType(); // Construct the new function type using the new arguments. FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); NF->copyAttributesFrom(F); // Patch the pointer to LLVM function in debug info descriptor. auto DI = FunctionDIs.find(F); if (DI != FunctionDIs.end()) { DISubprogram SP = DI->second; SP.replaceFunction(NF); // Ensure the map is updated so it can be reused on subsequent argument // promotions of the same function. FunctionDIs.erase(DI); FunctionDIs[NF] = SP; } DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" << "From: " << *F); // Recompute the parameter attributes list based on the new arguments for // the function. NF->setAttributes(AttributeSet::get(F->getContext(), AttributesVec)); AttributesVec.clear(); F->getParent()->getFunctionList().insert(F, NF); NF->takeName(F); // Get the alias analysis information that we need to update to reflect our // changes. AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); // Get the callgraph information that we need to update to reflect our // changes. CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); // Get a new callgraph node for NF. CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); // Loop over all of the callers of the function, transforming the call sites // to pass in the loaded pointers. // SmallVector<Value*, 16> Args; while (!F->use_empty()) { CallSite CS(F->user_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttributeSet &CallPAL = CS.getAttributes(); // Add any return attributes. if (CallPAL.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeSet::get(F->getContext(), CallPAL.getRetAttributes())); // Loop over the operands, inserting GEP and loads in the caller as // appropriate. CallSite::arg_iterator AI = CS.arg_begin(); ArgIndex = 1; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++AI, ++ArgIndex) if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { Args.push_back(*AI); // Unmodified argument if (CallPAL.hasAttributes(ArgIndex)) { AttrBuilder B(CallPAL, ArgIndex); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } else if (ByValArgsToTransform.count(I)) { // Emit a GEP and load for each element of the struct. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr }; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create(*AI, Idxs, (*AI)->getName()+"."+utostr(i), Call); // TODO: Tell AA about the new values? Args.push_back(new LoadInst(Idx, Idx->getName()+".val", Call)); } } else if (!I->use_empty()) { // Non-dead argument: insert GEPs and loads as appropriate. ScalarizeTable &ArgIndices = ScalarizedElements[I]; // Store the Value* version of the indices in here, but declare it now // for reuse. std::vector<Value*> Ops; for (ScalarizeTable::iterator SI = ArgIndices.begin(), E = ArgIndices.end(); SI != E; ++SI) { Value *V = *AI; LoadInst *OrigLoad = OriginalLoads[std::make_pair(I, *SI)]; if (!SI->empty()) { Ops.reserve(SI->size()); Type *ElTy = V->getType(); for (IndicesVector::const_iterator II = SI->begin(), IE = SI->end(); II != IE; ++II) { // Use i32 to index structs, and i64 for others (pointers/arrays). // This satisfies GEP constraints. Type *IdxTy = (ElTy->isStructTy() ? Type::getInt32Ty(F->getContext()) : Type::getInt64Ty(F->getContext())); Ops.push_back(ConstantInt::get(IdxTy, *II)); // Keep track of the type we're currently indexing. ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(*II); } // And create a GEP to extract those indices. V = GetElementPtrInst::Create(V, Ops, V->getName()+".idx", Call); Ops.clear(); AA.copyValue(OrigLoad->getOperand(0), V); } // Since we're replacing a load make sure we take the alignment // of the previous load. LoadInst *newLoad = new LoadInst(V, V->getName()+".val", Call); newLoad->setAlignment(OrigLoad->getAlignment()); // Transfer the AA info too. AAMDNodes AAInfo; OrigLoad->getAAMetadata(AAInfo); newLoad->setAAMetadata(AAInfo); Args.push_back(newLoad); AA.copyValue(OrigLoad, Args.back()); } } // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { Args.push_back(*AI); if (CallPAL.hasAttributes(ArgIndex)) { AttrBuilder B(CallPAL, ArgIndex); AttributesVec. push_back(AttributeSet::get(F->getContext(), Args.size(), B)); } } // Add any function attributes. if (CallPAL.hasAttributes(AttributeSet::FunctionIndex)) AttributesVec.push_back(AttributeSet::get(Call->getContext(), CallPAL.getFnAttributes())); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(AttributeSet::get(II->getContext(), AttributesVec)); } else { New = CallInst::Create(NF, Args, "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(AttributeSet::get(New->getContext(), AttributesVec)); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } New->setDebugLoc(Call->getDebugLoc()); Args.clear(); AttributesVec.clear(); // Update the alias analysis implementation to know that we are replacing // the old call with a new one. AA.replaceWithNewValue(Call, New); // Update the callgraph to know that the callsite has been transformed. CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; CalleeNode->replaceCallEdge(Call, New, NF_CGN); 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(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. // for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I) { if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) { // If this is an unmodified argument, move the name and users over to the // new version. I->replaceAllUsesWith(I2); I2->takeName(I); AA.replaceWithNewValue(I, I2); ++I2; continue; } if (ByValArgsToTransform.count(I)) { // In the callee, we create an alloca, and store each of the new incoming // arguments into the alloca. Instruction *InsertPt = NF->begin()->begin(); // Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, nullptr, "", InsertPt); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr }; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create(TheAlloca, Idxs, TheAlloca->getName()+"."+Twine(i), InsertPt); I2->setName(I->getName()+"."+Twine(i)); new StoreInst(I2++, Idx, InsertPt); } // Anything that used the arg should now use the alloca. I->replaceAllUsesWith(TheAlloca); TheAlloca->takeName(I); AA.replaceWithNewValue(I, TheAlloca); // If the alloca is used in a call, we must clear the tail flag since // the callee now uses an alloca from the caller. for (User *U : TheAlloca->users()) { CallInst *Call = dyn_cast<CallInst>(U); if (!Call) continue; Call->setTailCall(false); } continue; } if (I->use_empty()) { AA.deleteValue(I); continue; } // Otherwise, if we promoted this argument, then all users are load // instructions (or GEPs with only load users), and all loads should be // using the new argument that we added. ScalarizeTable &ArgIndices = ScalarizedElements[I]; while (!I->use_empty()) { if (LoadInst *LI = dyn_cast<LoadInst>(I->user_back())) { assert(ArgIndices.begin()->empty() && "Load element should sort to front!"); I2->setName(I->getName()+".val"); LI->replaceAllUsesWith(I2); AA.replaceWithNewValue(LI, I2); LI->eraseFromParent(); DEBUG(dbgs() << "*** Promoted load of argument '" << I->getName() << "' in function '" << F->getName() << "'\n"); } else { GetElementPtrInst *GEP = cast<GetElementPtrInst>(I->user_back()); IndicesVector Operands; Operands.reserve(GEP->getNumIndices()); for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); II != IE; ++II) Operands.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Operands.size() == 1 && Operands.front() == 0) Operands.clear(); Function::arg_iterator TheArg = I2; for (ScalarizeTable::iterator It = ArgIndices.begin(); *It != Operands; ++It, ++TheArg) { assert(It != ArgIndices.end() && "GEP not handled??"); } std::string NewName = I->getName(); for (unsigned i = 0, e = Operands.size(); i != e; ++i) { NewName += "." + utostr(Operands[i]); } NewName += ".val"; TheArg->setName(NewName); DEBUG(dbgs() << "*** Promoted agg argument '" << TheArg->getName() << "' of function '" << NF->getName() << "'\n"); // All of the uses must be load instructions. Replace them all with // the argument specified by ArgNo. while (!GEP->use_empty()) { LoadInst *L = cast<LoadInst>(GEP->user_back()); L->replaceAllUsesWith(TheArg); AA.replaceWithNewValue(L, TheArg); L->eraseFromParent(); } AA.deleteValue(GEP); GEP->eraseFromParent(); } } // Increment I2 past all of the arguments added for this promoted pointer. std::advance(I2, ArgIndices.size()); } // Tell the alias analysis that the old function is about to disappear. AA.replaceWithNewValue(F, NF); NF_CGN->stealCalledFunctionsFrom(CG[F]); // Now that the old function is dead, delete it. If there is a dangling // reference to the CallgraphNode, just leave the dead function around for // someone else to nuke. CallGraphNode *CGN = CG[F]; if (CGN->getNumReferences() == 0) delete CG.removeFunctionFromModule(CGN); else F->setLinkage(Function::ExternalLinkage); return NF_CGN; }
static bool markTails(Function &F, bool &AllCallsAreTailCalls) { if (F.callsFunctionThatReturnsTwice()) return false; AllCallsAreTailCalls = true; // The local stack holds all alloca instructions and all byval arguments. AllocaDerivedValueTracker Tracker; for (Argument &Arg : F.args()) { if (Arg.hasByValAttr()) Tracker.walk(&Arg); } for (auto &BB : F) { for (auto &I : BB) if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) Tracker.walk(AI); } bool Modified = false; // Track whether a block is reachable after an alloca has escaped. Blocks that // contain the escaping instruction will be marked as being visited without an // escaped alloca, since that is how the block began. enum VisitType { UNVISITED, UNESCAPED, ESCAPED }; DenseMap<BasicBlock *, VisitType> Visited; // We propagate the fact that an alloca has escaped from block to successor. // Visit the blocks that are propagating the escapedness first. To do this, we // maintain two worklists. SmallVector<BasicBlock *, 32> WorklistUnescaped, WorklistEscaped; // We may enter a block and visit it thinking that no alloca has escaped yet, // then see an escape point and go back around a loop edge and come back to // the same block twice. Because of this, we defer setting tail on calls when // we first encounter them in a block. Every entry in this list does not // statically use an alloca via use-def chain analysis, but may find an alloca // through other means if the block turns out to be reachable after an escape // point. SmallVector<CallInst *, 32> DeferredTails; BasicBlock *BB = &F.getEntryBlock(); VisitType Escaped = UNESCAPED; do { for (auto &I : *BB) { if (Tracker.EscapePoints.count(&I)) Escaped = ESCAPED; CallInst *CI = dyn_cast<CallInst>(&I); if (!CI || CI->isTailCall()) continue; bool IsNoTail = CI->isNoTailCall() || CI->hasOperandBundles(); if (!IsNoTail && CI->doesNotAccessMemory()) { // A call to a readnone function whose arguments are all things computed // outside this function can be marked tail. Even if you stored the // alloca address into a global, a readnone function can't load the // global anyhow. // // Note that this runs whether we know an alloca has escaped or not. If // it has, then we can't trust Tracker.AllocaUsers to be accurate. bool SafeToTail = true; for (auto &Arg : CI->arg_operands()) { if (isa<Constant>(Arg.getUser())) continue; if (Argument *A = dyn_cast<Argument>(Arg.getUser())) if (!A->hasByValAttr()) continue; SafeToTail = false; break; } if (SafeToTail) { emitOptimizationRemark( F.getContext(), "tailcallelim", F, CI->getDebugLoc(), "marked this readnone call a tail call candidate"); CI->setTailCall(); Modified = true; continue; } } if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) { DeferredTails.push_back(CI); } else { AllCallsAreTailCalls = false; } } for (auto *SuccBB : make_range(succ_begin(BB), succ_end(BB))) { auto &State = Visited[SuccBB]; if (State < Escaped) { State = Escaped; if (State == ESCAPED) WorklistEscaped.push_back(SuccBB); else WorklistUnescaped.push_back(SuccBB); } } if (!WorklistEscaped.empty()) { BB = WorklistEscaped.pop_back_val(); Escaped = ESCAPED; } else { BB = nullptr; while (!WorklistUnescaped.empty()) { auto *NextBB = WorklistUnescaped.pop_back_val(); if (Visited[NextBB] == UNESCAPED) { BB = NextBB; Escaped = UNESCAPED; break; } } } } while (BB); for (CallInst *CI : DeferredTails) { if (Visited[CI->getParent()] != ESCAPED) { // If the escape point was part way through the block, calls after the // escape point wouldn't have been put into DeferredTails. emitOptimizationRemark(F.getContext(), "tailcallelim", F, CI->getDebugLoc(), "marked this call a tail call candidate"); CI->setTailCall(); Modified = true; } else { AllCallsAreTailCalls = false; } } return Modified; }
// Convert the given call to use normalized argument/return types. template <class T> static bool ConvertCall(T *Call, Pass *P) { // Don't try to change calls to intrinsics. if (isa<IntrinsicInst>(Call)) return false; FunctionType *FTy = cast<FunctionType>( Call->getCalledValue()->getType()->getPointerElementType()); FunctionType *NFTy = NormalizeFunctionType(FTy); if (NFTy == FTy) return false; // No change needed. // Convert arguments. SmallVector<Value *, 8> Args; for (unsigned I = 0; I < Call->getNumArgOperands(); ++I) { Value *Arg = Call->getArgOperand(I); if (NFTy->getParamType(I) != FTy->getParamType(I)) { Instruction::CastOps CastType = Call->getAttributes().hasAttribute(I + 1, Attribute::SExt) ? Instruction::SExt : Instruction::ZExt; Arg = CopyDebug(CastInst::Create(CastType, Arg, NFTy->getParamType(I), "arg_ext", Call), Call); } Args.push_back(Arg); } Value *CastFunc = CopyDebug(new BitCastInst(Call->getCalledValue(), NFTy->getPointerTo(), Call->getName() + ".arg_cast", Call), Call); Value *Result = NULL; if (CallInst *OldCall = dyn_cast<CallInst>(Call)) { CallInst *NewCall = CopyDebug(CallInst::Create(CastFunc, Args, "", OldCall), OldCall); NewCall->takeName(OldCall); NewCall->setAttributes(OldCall->getAttributes()); NewCall->setCallingConv(OldCall->getCallingConv()); NewCall->setTailCall(OldCall->isTailCall()); Result = NewCall; if (FTy->getReturnType() != NFTy->getReturnType()) { Result = CopyDebug(new TruncInst(NewCall, FTy->getReturnType(), NewCall->getName() + ".ret_trunc", Call), Call); } } else if (InvokeInst *OldInvoke = dyn_cast<InvokeInst>(Call)) { BasicBlock *Parent = OldInvoke->getParent(); BasicBlock *NormalDest = OldInvoke->getNormalDest(); BasicBlock *UnwindDest = OldInvoke->getUnwindDest(); if (FTy->getReturnType() != NFTy->getReturnType()) { if (BasicBlock *SplitDest = SplitCriticalEdge(Parent, NormalDest)) { NormalDest = SplitDest; } } InvokeInst *New = CopyDebug(InvokeInst::Create(CastFunc, NormalDest, UnwindDest, Args, "", OldInvoke), OldInvoke); New->takeName(OldInvoke); if (FTy->getReturnType() != NFTy->getReturnType()) { Result = CopyDebug(new TruncInst(New, FTy->getReturnType(), New->getName() + ".ret_trunc", NormalDest->getTerminator()), OldInvoke); } else { Result = New; } New->setAttributes(OldInvoke->getAttributes()); New->setCallingConv(OldInvoke->getCallingConv()); } Call->replaceAllUsesWith(Result); Call->eraseFromParent(); return true; }
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Function *F = CI->getCalledFunction(); LLVMContext &C = CI->getContext(); ImmutableCallSite CS(CI); assert(F && "CallInst has no function associated with it."); if (!NewFn) { if (F->getName() == "llvm.x86.sse.loadu.ps" || F->getName() == "llvm.x86.sse2.loadu.dq" || F->getName() == "llvm.x86.sse2.loadu.pd") { // Convert to a native, unaligned load. const Type *VecTy = CI->getType(); const Type *IntTy = IntegerType::get(C, 128); IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), PointerType::getUnqual(IntTy), "cast"); LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); LI->setAlignment(1); // Unaligned load. BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); // Fix up all the uses with our new load. if (!CI->use_empty()) CI->replaceAllUsesWith(BC); // Remove intrinsic. CI->eraseFromParent(); } else if (F->getName() == "llvm.x86.sse.movnt.ps" || F->getName() == "llvm.x86.sse2.movnt.dq" || F->getName() == "llvm.x86.sse2.movnt.pd" || F->getName() == "llvm.x86.sse2.movnt.i") { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); Module *M = F->getParent(); SmallVector<Value *, 1> Elts; Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); MDNode *Node = MDNode::get(C, Elts); Value *Arg0 = CI->getArgOperand(0); Value *Arg1 = CI->getArgOperand(1); // Convert the type of the pointer to a pointer to the stored type. Value *BC = Builder.CreateBitCast(Arg0, PointerType::getUnqual(Arg1->getType()), "cast"); StoreInst *SI = Builder.CreateStore(Arg1, BC); SI->setMetadata(M->getMDKindID("nontemporal"), Node); SI->setAlignment(16); // Remove intrinsic. CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } return; } switch (NewFn->getIntrinsicID()) { case Intrinsic::prefetch: { IRBuilder<> Builder(C); Builder.SetInsertPoint(CI->getParent(), CI); const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CI->getContext()); // Add the extra "data cache" argument Value *Operands[4] = { CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), llvm::ConstantInt::get(I32Ty, 1) }; CallInst *NewCI = CallInst::Create(NewFn, Operands, CI->getName(), CI); NewCI->setTailCall(CI->isTailCall()); NewCI->setCallingConv(CI->getCallingConv()); // Handle any uses of the old CallInst. if (!CI->use_empty()) // Replace all uses of the old call with the new cast which has the // correct type. CI->replaceAllUsesWith(NewCI); // Clean up the old call now that it has been completely upgraded. CI->eraseFromParent(); break; } } }
/// Replaces the given call site (Call or Invoke) with a gc.statepoint /// intrinsic with an empty deoptimization arguments list. This does /// NOT do explicit relocation for GC support. static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */ Pass *P) { BasicBlock *BB = CS.getInstruction()->getParent(); Function *F = BB->getParent(); Module *M = F->getParent(); assert(M && "must be set"); // TODO: technically, a pass is not allowed to get functions from within a // function pass since it might trigger a new function addition. Refactor // this logic out to the initialization of the pass. Doesn't appear to // matter in practice. // Fill in the one generic type'd argument (the function is also vararg) std::vector<Type *> argTypes; argTypes.push_back(CS.getCalledValue()->getType()); Function *gc_statepoint_decl = Intrinsic::getDeclaration( M, Intrinsic::experimental_gc_statepoint, argTypes); // Then go ahead and use the builder do actually do the inserts. We insert // immediately before the previous instruction under the assumption that all // arguments will be available here. We can't insert afterwards since we may // be replacing a terminator. Instruction *insertBefore = CS.getInstruction(); IRBuilder<> Builder(insertBefore); // First, create the statepoint (with all live ptrs as arguments). std::vector<llvm::Value *> args; // target, #args, unused, args Value *Target = CS.getCalledValue(); args.push_back(Target); int callArgSize = CS.arg_size(); args.push_back( ConstantInt::get(Type::getInt32Ty(M->getContext()), callArgSize)); // TODO: add a 'Needs GC-rewrite' later flag args.push_back(ConstantInt::get(Type::getInt32Ty(M->getContext()), 0)); // Copy all the arguments of the original call args.insert(args.end(), CS.arg_begin(), CS.arg_end()); // Create the statepoint given all the arguments Instruction *token = nullptr; AttributeSet return_attributes; if (CS.isCall()) { CallInst *toReplace = cast<CallInst>(CS.getInstruction()); CallInst *call = Builder.CreateCall(gc_statepoint_decl, args, "safepoint_token"); call->setTailCall(toReplace->isTailCall()); call->setCallingConv(toReplace->getCallingConv()); // Before we have to worry about GC semantics, all attributes are legal AttributeSet new_attrs = toReplace->getAttributes(); // In case if we can handle this set of sttributes - set up function attrs // directly on statepoint and return attrs later for gc_result intrinsic. call->setAttributes(new_attrs.getFnAttributes()); return_attributes = new_attrs.getRetAttributes(); // TODO: handle param attributes token = call; // Put the following gc_result and gc_relocate calls immediately after the // the old call (which we're about to delete) BasicBlock::iterator next(toReplace); assert(BB->end() != next && "not a terminator, must have next"); next++; Instruction *IP = &*(next); Builder.SetInsertPoint(IP); Builder.SetCurrentDebugLocation(IP->getDebugLoc()); } else if (CS.isInvoke()) { InvokeInst *toReplace = cast<InvokeInst>(CS.getInstruction()); // Insert the new invoke into the old block. We'll remove the old one in a // moment at which point this will become the new terminator for the // original block. InvokeInst *invoke = InvokeInst::Create( gc_statepoint_decl, toReplace->getNormalDest(), toReplace->getUnwindDest(), args, "", toReplace->getParent()); invoke->setCallingConv(toReplace->getCallingConv()); // Currently we will fail on parameter attributes and on certain // function attributes. AttributeSet new_attrs = toReplace->getAttributes(); // In case if we can handle this set of sttributes - set up function attrs // directly on statepoint and return attrs later for gc_result intrinsic. invoke->setAttributes(new_attrs.getFnAttributes()); return_attributes = new_attrs.getRetAttributes(); token = invoke; // We'll insert the gc.result into the normal block BasicBlock *normalDest = normalizeBBForInvokeSafepoint( toReplace->getNormalDest(), invoke->getParent()); Instruction *IP = &*(normalDest->getFirstInsertionPt()); Builder.SetInsertPoint(IP); } else { llvm_unreachable("unexpect type of CallSite"); } assert(token); // Handle the return value of the original call - update all uses to use a // gc_result hanging off the statepoint node we just inserted // Only add the gc_result iff there is actually a used result if (!CS.getType()->isVoidTy() && !CS.getInstruction()->use_empty()) { Instruction *gc_result = nullptr; std::vector<Type *> types; // one per 'any' type types.push_back(CS.getType()); // result type auto get_gc_result_id = [&](Type &Ty) { if (Ty.isIntegerTy()) { return Intrinsic::experimental_gc_result_int; } else if (Ty.isFloatingPointTy()) { return Intrinsic::experimental_gc_result_float; } else if (Ty.isPointerTy()) { return Intrinsic::experimental_gc_result_ptr; } else { llvm_unreachable("non java type encountered"); } }; Intrinsic::ID Id = get_gc_result_id(*CS.getType()); Value *gc_result_func = Intrinsic::getDeclaration(M, Id, types); std::vector<Value *> args; args.push_back(token); gc_result = Builder.CreateCall( gc_result_func, args, CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : ""); cast<CallInst>(gc_result)->setAttributes(return_attributes); return gc_result; } else { // No return value for the call. return nullptr; } }
virtual bool runOnFunction(Function &F) { DEBUG(errs() << "Running on " << F.getName() << "\n"); DEBUG(F.dump()); Changed = false; BaseMap.clear(); BoundsMap.clear(); AbrtBB = 0; valid = true; if (!rootNode) { rootNode = getAnalysis<CallGraph>().getRoot(); // No recursive functions for now. // In the future we may insert runtime checks for stack depth. for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode), E = scc_end(rootNode); SCCI != E; ++SCCI) { const std::vector<CallGraphNode*> &nextSCC = *SCCI; if (nextSCC.size() > 1 || SCCI.hasLoop()) { errs() << "INVALID: Recursion detected, callgraph SCC components: "; for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(), E = nextSCC.end(); I != E; ++I) { Function *FF = (*I)->getFunction(); if (FF) { errs() << FF->getName() << ", "; badFunctions.insert(FF); } } if (SCCI.hasLoop()) errs() << "(self-loop)"; errs() << "\n"; } // we could also have recursion via function pointers, but we don't // allow calls to unknown functions, see runOnFunction() below } } BasicBlock::iterator It = F.getEntryBlock().begin(); while (isa<AllocaInst>(It) || isa<PHINode>(It)) ++It; EP = &*It; TD = &getAnalysis<TargetData>(); SE = &getAnalysis<ScalarEvolution>(); PT = &getAnalysis<PointerTracking>(); DT = &getAnalysis<DominatorTree>(); std::vector<Instruction*> insns; BasicBlock *LastBB = 0; bool skip = false; for (inst_iterator I=inst_begin(F),E=inst_end(F); I != E;++I) { Instruction *II = &*I; if (II->getParent() != LastBB) { LastBB = II->getParent(); skip = DT->getNode(LastBB) == 0; } if (skip) continue; if (isa<LoadInst>(II) || isa<StoreInst>(II) || isa<MemIntrinsic>(II)) insns.push_back(II); if (CallInst *CI = dyn_cast<CallInst>(II)) { Value *V = CI->getCalledValue()->stripPointerCasts(); Function *F = dyn_cast<Function>(V); if (!F) { printLocation(CI, true); errs() << "Could not determine call target\n"; valid = 0; continue; } if (!F->isDeclaration()) continue; insns.push_back(CI); } } while (!insns.empty()) { Instruction *II = insns.back(); insns.pop_back(); DEBUG(dbgs() << "checking " << *II << "\n"); if (LoadInst *LI = dyn_cast<LoadInst>(II)) { const Type *Ty = LI->getType(); valid &= validateAccess(LI->getPointerOperand(), TD->getTypeAllocSize(Ty), LI); } else if (StoreInst *SI = dyn_cast<StoreInst>(II)) { const Type *Ty = SI->getOperand(0)->getType(); valid &= validateAccess(SI->getPointerOperand(), TD->getTypeAllocSize(Ty), SI); } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(II)) { valid &= validateAccess(MI->getDest(), MI->getLength(), MI); if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) { valid &= validateAccess(MTI->getSource(), MI->getLength(), MI); } } else if (CallInst *CI = dyn_cast<CallInst>(II)) { Value *V = CI->getCalledValue()->stripPointerCasts(); Function *F = cast<Function>(V); const FunctionType *FTy = F->getFunctionType(); CallSite CS(CI); if (F->getName().equals("memcmp") && FTy->getNumParams() == 3) { valid &= validateAccess(CS.getArgument(0), CS.getArgument(2), CI); valid &= validateAccess(CS.getArgument(1), CS.getArgument(2), CI); continue; } unsigned i; #ifdef CLAMBC_COMPILER i = 0; #else i = 1;// skip hidden ctx* #endif for (;i<FTy->getNumParams();i++) { if (isa<PointerType>(FTy->getParamType(i))) { Value *Ptr = CS.getArgument(i); if (i+1 >= FTy->getNumParams()) { printLocation(CI, false); errs() << "Call to external function with pointer parameter last cannot be analyzed\n"; errs() << *CI << "\n"; valid = 0; break; } Value *Size = CS.getArgument(i+1); if (!Size->getType()->isIntegerTy()) { printLocation(CI, false); errs() << "Pointer argument must be followed by integer argument representing its size\n"; errs() << *CI << "\n"; valid = 0; break; } valid &= validateAccess(Ptr, Size, CI); } } } } if (badFunctions.count(&F)) valid = 0; if (!valid) { DEBUG(F.dump()); ClamBCModule::stop("Verification found errors!", &F); // replace function with call to abort std::vector<const Type*>args; FunctionType* abrtTy = FunctionType::get( Type::getVoidTy(F.getContext()),args,false); Constant *func_abort = F.getParent()->getOrInsertFunction("abort", abrtTy); BasicBlock *BB = &F.getEntryBlock(); Instruction *I = &*BB->begin(); Instruction *UI = new UnreachableInst(F.getContext(), I); CallInst *AbrtC = CallInst::Create(func_abort, "", UI); AbrtC->setCallingConv(CallingConv::C); AbrtC->setTailCall(true); AbrtC->setDoesNotReturn(true); AbrtC->setDoesNotThrow(true); // remove all instructions from entry BasicBlock::iterator BBI = I, BBE=BB->end(); while (BBI != BBE) { if (!BBI->use_empty()) BBI->replaceAllUsesWith(UndefValue::get(BBI->getType())); BB->getInstList().erase(BBI++); } } return Changed; }
/// Replaces the given call site (Call or Invoke) with a gc.statepoint /// intrinsic with an empty deoptimization arguments list. This does /// NOT do explicit relocation for GC support. static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */ Pass *P) { assert(CS.getInstruction()->getParent()->getParent()->getParent() && "must be set"); // TODO: technically, a pass is not allowed to get functions from within a // function pass since it might trigger a new function addition. Refactor // this logic out to the initialization of the pass. Doesn't appear to // matter in practice. // Then go ahead and use the builder do actually do the inserts. We insert // immediately before the previous instruction under the assumption that all // arguments will be available here. We can't insert afterwards since we may // be replacing a terminator. IRBuilder<> Builder(CS.getInstruction()); // Note: The gc args are not filled in at this time, that's handled by // RewriteStatepointsForGC (which is currently under review). // Create the statepoint given all the arguments Instruction *Token = nullptr; AttributeSet OriginalAttrs; if (CS.isCall()) { CallInst *ToReplace = cast<CallInst>(CS.getInstruction()); CallInst *Call = Builder.CreateGCStatepointCall( CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None, "safepoint_token"); Call->setTailCall(ToReplace->isTailCall()); Call->setCallingConv(ToReplace->getCallingConv()); // Before we have to worry about GC semantics, all attributes are legal // TODO: handle param attributes OriginalAttrs = ToReplace->getAttributes(); // In case if we can handle this set of attributes - set up function // attributes directly on statepoint and return attributes later for // gc_result intrinsic. Call->setAttributes(OriginalAttrs.getFnAttributes()); Token = Call; // Put the following gc_result and gc_relocate calls immediately after the // the old call (which we're about to delete). assert(ToReplace->getNextNode() && "not a terminator, must have next"); Builder.SetInsertPoint(ToReplace->getNextNode()); Builder.SetCurrentDebugLocation(ToReplace->getNextNode()->getDebugLoc()); } else if (CS.isInvoke()) { InvokeInst *ToReplace = cast<InvokeInst>(CS.getInstruction()); // Insert the new invoke into the old block. We'll remove the old one in a // moment at which point this will become the new terminator for the // original block. Builder.SetInsertPoint(ToReplace->getParent()); InvokeInst *Invoke = Builder.CreateGCStatepointInvoke( CS.getCalledValue(), ToReplace->getNormalDest(), ToReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()), Builder.getInt32(0), None, "safepoint_token"); // Currently we will fail on parameter attributes and on certain // function attributes. OriginalAttrs = ToReplace->getAttributes(); // In case if we can handle this set of attributes - set up function // attributes directly on statepoint and return attributes later for // gc_result intrinsic. Invoke->setAttributes(OriginalAttrs.getFnAttributes()); Token = Invoke; // We'll insert the gc.result into the normal block BasicBlock *NormalDest = normalizeBBForInvokeSafepoint( ToReplace->getNormalDest(), Invoke->getParent()); Builder.SetInsertPoint(NormalDest->getFirstInsertionPt()); } else { llvm_unreachable("unexpect type of CallSite"); } assert(Token); // Handle the return value of the original call - update all uses to use a // gc_result hanging off the statepoint node we just inserted // Only add the gc_result iff there is actually a used result if (!CS.getType()->isVoidTy() && !CS.getInstruction()->use_empty()) { std::string TakenName = CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : ""; CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(), TakenName); GCResult->setAttributes(OriginalAttrs.getRetAttributes()); return GCResult; } else { // No return value for the call. return nullptr; } }
static InstTransResult doCallPCExtern(BasicBlock *&b, std::string target, bool esp_adjust = false) { Module *M = b->getParent()->getParent(); //write it into the location pointer to by ESP-4 Value *espOld = R_READ<32>(b, X86::ESP); //Value *espSub = // BinaryOperator::CreateSub(espOld, CONST_V<32>(b, 4), "", b); //M_WRITE_0<32>(b, espSub, CONST_V<32>(b, 0)); //R_WRITE<32>(b, X86::ESP, espSub); //write the local values into the context register //for now, we will stop doing this because we are not calling a wrapper //that meaningfully understands the context structure //writeLocalsToContext(b, 32); //lookup the function in the module Function *externFunction = M->getFunction(target); TASSERT(externFunction != NULL, "Coult not find external function: "+target); FunctionType *externFunctionTy = externFunction->getFunctionType(); Type *rType = externFunction->getReturnType(); int paramCount = externFunctionTy->getNumParams(); //now we need to do a series of reads off the stack, essentially //a series of POPs but without writing anything back to ESP Value *baseEspVal=NULL; std::vector<Value *> arguments; // in fastcall, the first two params are passed via register // only need to adjust stack if there are more than two args if( externFunction->getCallingConv() == CallingConv::X86_FastCall) { Function::ArgumentListType::iterator it = externFunction->getArgumentList().begin(); Function::ArgumentListType::iterator end = externFunction->getArgumentList().end(); AttrBuilder B; B.addAttribute(Attribute::InReg); if(paramCount && it != end) { Value *r_ecx = R_READ<32>(b, X86::ECX); arguments.push_back(r_ecx); --paramCount; // set argument 1's attribute: make it in a register it->addAttr(AttributeSet::get(it->getContext(), 1, B)); ++it; } if(paramCount && it != end) { Value *r_edx = R_READ<32>(b, X86::EDX); arguments.push_back(r_edx); --paramCount; // set argument 2's attribute: make it in a register it->addAttr(AttributeSet::get(it->getContext(), 2, B)); ++it; } } if( paramCount ) { baseEspVal = R_READ<32>(b, X86::ESP); if(esp_adjust) { baseEspVal = BinaryOperator::CreateAdd(baseEspVal, CONST_V<32>(b, 4), "", b); } } for( int i = 0; i < paramCount; i++ ) { Value *vFromStack = M_READ_0<32>(b, baseEspVal); arguments.push_back(vFromStack); if( i+1 != paramCount ) { baseEspVal = BinaryOperator::CreateAdd(baseEspVal, CONST_V<32>(b, 4), "", b); } } CallInst *callR = CallInst::Create(externFunction, arguments, "", b); callR->setCallingConv(externFunction->getCallingConv()); noAliasMCSemaScope(callR); if ( externFunction->doesNotReturn() ) { // noreturn functions just hit unreachable std::cout << __FUNCTION__ << ": Adding Unreachable Instruction" << std::endl; callR->setDoesNotReturn(); callR->setTailCall(); Value *unreachable = new UnreachableInst(b->getContext(), b); return EndBlock; } //then, put the registers back into the locals //see above //writeContextToLocals(b, 32); // we returned from an extern: assume it cleared the direction flag // which is standard for MS calling conventions // F_CLEAR(b, DF); //if our convention says to keep the call result alive then do it //really, we could always keep the call result alive... if( rType == Type::getInt32Ty(M->getContext()) ) { R_WRITE<32>(b, X86::EAX, callR); } // stdcall and fastcall: callee changed ESP; adjust // REG_ESP accordingly if( externFunction->getCallingConv() == CallingConv::X86_StdCall || externFunction->getCallingConv() == CallingConv::X86_FastCall) { Value *ESP_adjust = CONST_V<32>(b, 4*paramCount); Value *espFix = BinaryOperator::CreateAdd(espOld, ESP_adjust, "", b); R_WRITE<32>(b, X86::ESP, espFix); } return ContinueBlock; }
void WorklessInstrument::InstrumentWorkless0Star1(Module * pModule, Loop * pLoop) { Function * pMain = NULL; if(strMainName != "" ) { pMain = pModule->getFunction(strMainName.c_str()); } else { pMain = pModule->getFunction("main"); } LoadInst * pLoad; BinaryOperator* pAdd = NULL; StoreInst * pStore = NULL; for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { if(BB->getName().equals("entry")) { CallInst * pCall; StoreInst * pStore; Instruction * II = BB->begin(); pCall = CallInst::Create(this->InitHooks, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet emptySet; pCall->setAttributes(emptySet); pCall = CallInst::Create(this->getenv, this->SAMPLE_RATE_ptr, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet AS; { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pCall = CallInst::Create(this->function_atoi, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); B.addAttribute(Attribute::ReadOnly); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pStore = new StoreInst(pCall, this->SAMPLE_RATE, false, II); pStore->setAlignment(4); pCall = CallInst::Create(this->geo, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", II); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, II); pStore->setAlignment(8); vector<Value *> vecParam; vecParam.push_back(this->Output_Format_String); vecParam.push_back(pCall); pCall = CallInst::Create(this->printf, vecParam, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); break; } } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<ReturnInst>(Ins) || isa<ResumeInst>(Ins)) { vector<Value*> vecParams; pLoad = new LoadInst(numIterations, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); pLoad = new LoadInst(numInstances, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); CallInst* pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); } else if(isa<CallInst>(Ins) || isa<InvokeInst>(Ins)) { CallSite cs(Ins); Function * pCalled = cs.getCalledFunction(); if(pCalled == NULL) { continue; } if(pCalled->getName() == "exit" || pCalled->getName() == "_ZL9mysql_endi") { vector<Value*> vecParams; pLoad = new LoadInst(numIterations, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); pLoad = new LoadInst(numInstances, "", false, Ins); pLoad->setAlignment(8); vecParams.push_back(pLoad); CallInst* pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); } } } } BasicBlock * pHeader = pLoop->getHeader(); set<BasicBlock *> setExitBlock; CollectExitBlock(pLoop, setExitBlock); vector<BasicBlock *> vecAdded; CreateIfElseBlock(pLoop, vecAdded); ValueToValueMapTy VMap; set<BasicBlock *> setCloned; CloneInnerLoop(pLoop, vecAdded, VMap, setCloned); BasicBlock * pPreHeader = vecAdded[1]; pLoad = new LoadInst(this->numIterations, "", false, pPreHeader->getTerminator()); pLoad->setAlignment(8); BasicBlock * pClonedHeader = cast<BasicBlock>(VMap[pHeader]); set<BasicBlock *> setPredBlocks; for(pred_iterator PI = pred_begin(pClonedHeader), E = pred_end(pClonedHeader); PI != E; ++PI) { setPredBlocks.insert(*PI); } PHINode * pNew = PHINode::Create(pLoad->getType(), setPredBlocks.size(), "numIterations", pClonedHeader->getFirstInsertionPt()); pAdd = BinaryOperator::Create(Instruction::Add, pNew, this->ConstantLong1, "add", pClonedHeader->getFirstInsertionPt()); set<BasicBlock *>::iterator itSetBegin = setPredBlocks.begin(); set<BasicBlock *>::iterator itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pPreHeader) { pNew->addIncoming(pLoad, pPreHeader); } else { pNew->addIncoming(pAdd, *itSetBegin); } } itSetBegin = setExitBlock.begin(); itSetEnd = setExitBlock.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { SmallVector<BasicBlock*, 8> LoopBlocks; for(pred_iterator PI = pred_begin(*itSetBegin), E = pred_end(*itSetBegin); PI != E; ++PI) { if(setCloned.find(*PI) != setCloned.end()) { LoopBlocks.push_back(*PI); } } BasicBlock * NewExitBB = SplitBlockPredecessors(*itSetBegin, LoopBlocks, ".WL.loopexit", this); pStore = new StoreInst(pAdd, this->numIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); } pPreHeader->getParent()->dump(); }
/// compile_if - Emit code for '[' void BrainFTraceRecorder::compile_if(BrainFTraceNode *node, IRBuilder<>& builder) { BasicBlock *ZeroChild = 0; BasicBlock *NonZeroChild = 0; BasicBlock *Parent = builder.GetInsertBlock(); LLVMContext &Context = Header->getContext(); // If both directions of the branch go back to the trace-head, just // jump there directly. if (node->left == (BrainFTraceNode*)~0ULL && node->right == (BrainFTraceNode*)~0ULL) { HeaderPHI->addIncoming(DataPtr, builder.GetInsertBlock()); builder.CreateBr(Header); return; } // Otherwise, there are two cases to handle for each direction: // ~0ULL - A branch back to the trace head // 0 - A branch out of the trace // * - A branch to a node we haven't compiled yet. // Go ahead and generate code for both targets. if (node->left == (BrainFTraceNode*)~0ULL) { NonZeroChild = Header; HeaderPHI->addIncoming(DataPtr, Parent); } else if (node->left == 0) { NonZeroChild = BasicBlock::Create(Context, "exit_left_"+utostr(node->pc), Header->getParent()); builder.SetInsertPoint(NonZeroChild); // Set the extension leaf, which is a pointer to the leaf of the trace // tree from which we are side exiting. ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node); builder.CreateStore(ExtLeaf, ext_leaf); ConstantInt *NewPc = ConstantInt::get(int_type, node->pc+1); Value *BytecodeIndex = builder.CreateConstInBoundsGEP1_32(bytecode_array, node->pc+1); Value *Target = builder.CreateLoad(BytecodeIndex); CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr)); Call->setTailCall(); builder.CreateRetVoid(); } else { NonZeroChild = BasicBlock::Create(Context, utostr(node->left->pc), Header->getParent()); builder.SetInsertPoint(NonZeroChild); compile_opcode(node->left, builder); } if (node->right == (BrainFTraceNode*)~0ULL) { ZeroChild = Header; HeaderPHI->addIncoming(DataPtr, Parent); } else if (node->right == 0) { ZeroChild = BasicBlock::Create(Context, "exit_right_"+utostr(node->pc), Header->getParent()); builder.SetInsertPoint(ZeroChild); // Set the extension leaf, which is a pointer to the leaf of the trace // tree from which we are side exiting. ConstantInt *ExtLeaf = ConstantInt::get(int_type, (intptr_t)node); builder.CreateStore(ExtLeaf, ext_leaf); ConstantInt *NewPc = ConstantInt::get(int_type, JumpMap[node->pc]+1); Value *BytecodeIndex = builder.CreateConstInBoundsGEP1_32(bytecode_array, JumpMap[node->pc]+1); Value *Target = builder.CreateLoad(BytecodeIndex); CallInst *Call =cast<CallInst>(builder.CreateCall2(Target, NewPc, DataPtr)); Call->setTailCall(); builder.CreateRetVoid(); } else { ZeroChild = BasicBlock::Create(Context, utostr(node->right->pc), Header->getParent()); builder.SetInsertPoint(ZeroChild); compile_opcode(node->right, builder); } // Generate the test and branch to select between the targets. builder.SetInsertPoint(Parent); Value *Loaded = builder.CreateLoad(DataPtr); Value *Cmp = builder.CreateICmpEQ(Loaded, ConstantInt::get(Loaded->getType(), 0)); builder.CreateCondBr(Cmp, ZeroChild, NonZeroChild); }
void WorklessInstrument::InstrumentWorkless0Or1Star(Module * pModule, Loop * pLoop, set<string> & setWorkingBlocks) { LoadInst * pLoad0 = NULL; LoadInst * pLoad1 = NULL; //BinaryOperator* pAdd = NULL; StoreInst * pStore = NULL; CallInst * pCall = NULL; Function * pMain = NULL; if(strMainName != "" ) { pMain = pModule->getFunction(strMainName.c_str()); } else { pMain = pModule->getFunction("main"); } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { if(BB->getName().equals("entry")) { CallInst * pCall; StoreInst * pStore; Instruction * II = BB->begin(); pCall = CallInst::Create(this->InitHooks, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet emptySet; pCall->setAttributes(emptySet); pCall = CallInst::Create(this->getenv, this->SAMPLE_RATE_ptr, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet AS; { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pCall = CallInst::Create(this->function_atoi, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); { SmallVector<AttributeSet, 4> Attrs; AttributeSet PAS; { AttrBuilder B; B.addAttribute(Attribute::NoUnwind); B.addAttribute(Attribute::ReadOnly); PAS = AttributeSet::get(pModule->getContext(), ~0U, B); } Attrs.push_back(PAS); AS = AttributeSet::get(pModule->getContext(), Attrs); } pCall->setAttributes(AS); pStore = new StoreInst(pCall, this->SAMPLE_RATE, false, II); pStore->setAlignment(4); pCall = CallInst::Create(this->geo, pCall, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); CastInst * pCast = CastInst::CreateIntegerCast(pCall, this->LongType, true, "", II); pStore = new StoreInst(pCast, this->CURRENT_SAMPLE, false, II); pStore->setAlignment(8); vector<Value *> vecParam; vecParam.push_back(this->Output_Format_String); vecParam.push_back(pCall); pCall = CallInst::Create(this->printf, vecParam, "", II); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(emptySet); break; } } for (Function::iterator BB = pMain->begin(); BB != pMain->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<ReturnInst>(Ins) || isa<ResumeInst>(Ins)) { vector<Value*> vecParams; pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numInstances, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); vecParams.clear(); pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numWorkingIterations, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(PrintWorkingRatio, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(aSet); } else if(isa<CallInst>(Ins) || isa<InvokeInst>(Ins)) { CallSite cs(Ins); Function * pCalled = cs.getCalledFunction(); if(pCalled == NULL) { continue; } if(pCalled->getName() == "exit" || pCalled->getName() == "_ZL9mysql_endi") { vector<Value*> vecParams; pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numInstances, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(this->PrintLoopInfo, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); AttributeSet aSet; pCall->setAttributes(aSet); vecParams.clear(); pLoad0 = new LoadInst(numIterations, "", false, Ins); pLoad0->setAlignment(8); vecParams.push_back(pLoad0); pLoad1 = new LoadInst(numWorkingIterations, "", false, Ins); pLoad1->setAlignment(8); vecParams.push_back(pLoad1); pCall = CallInst::Create(PrintWorkingRatio, vecParams, "", Ins); pCall->setCallingConv(CallingConv::C); pCall->setTailCall(false); pCall->setAttributes(aSet); } } } } Function * pFunction = pLoop->getHeader()->getParent(); BasicBlock * pEntry = &(pFunction->getEntryBlock()); AllocaInst * pAlloc = new AllocaInst(this->LongType, "bWorkingIteration.local", pEntry->getFirstInsertionPt()); vector<BasicBlock *> vecWorkingBlock; for(Function::iterator BB = pFunction->begin(); BB != pFunction->end(); ++ BB) { if(setWorkingBlocks.find(BB->getName()) != setWorkingBlocks.end() ) { vecWorkingBlock.push_back(BB); } } errs() << "working block number: " << vecWorkingBlock.size() << "\n"; BasicBlock * pHeader = pLoop->getHeader(); set<BasicBlock *> setExitBlock; CollectExitBlock(pLoop, setExitBlock); vector<BasicBlock *> vecAdded; CreateIfElseBlock(pLoop, vecAdded); ValueToValueMapTy VMap; set<BasicBlock *> setCloned; CloneInnerLoop(pLoop, vecAdded, VMap, setCloned); //BasicBlock * pPreHeader = vecAdded[0]; BasicBlock * pElseBody = vecAdded[1]; vector<BasicBlock *>::iterator itVecBegin = vecWorkingBlock.begin(); vector<BasicBlock *>::iterator itVecEnd = vecWorkingBlock.end(); for(; itVecBegin != itVecEnd; itVecBegin++ ) { BasicBlock * pClonedBlock = cast<BasicBlock>(VMap[*itVecBegin]); pStore = new StoreInst(this->ConstantLong1, pAlloc, false, pClonedBlock->getFirstInsertionPt()); pStore->setAlignment(8); pClonedBlock->dump(); } pStore = new StoreInst(this->ConstantLong0, pAlloc, false, pElseBody->getTerminator()); pStore->setAlignment(8); pLoad0 = new LoadInst(this->numIterations, "", false, pElseBody->getTerminator()); pLoad0->setAlignment(8); pLoad1 = new LoadInst(this->numWorkingIterations, "", false, pElseBody->getTerminator()); pLoad1->setAlignment(8); BasicBlock * pClonedHeader = cast<BasicBlock>(VMap[pHeader]); set<BasicBlock *> setPredBlocks; for(pred_iterator PI = pred_begin(pClonedHeader), E = pred_end(pClonedHeader); PI != E; ++PI) { setPredBlocks.insert(*PI); } BasicBlock::iterator itInsert = pClonedHeader->getFirstInsertionPt(); PHINode * pNewIterations = PHINode::Create(pLoad0->getType(), setPredBlocks.size(), "numIterations.2", itInsert); PHINode * pNewWorkingIterations = PHINode::Create(pLoad1->getType(), setPredBlocks.size(), "WorkingIterations.2", itInsert); BinaryOperator * pIterationAdd = BinaryOperator::Create(Instruction::Add, pNewIterations, this->ConstantLong1, "Iterations.add.2", itInsert); set<BasicBlock *>::iterator itSetBegin = setPredBlocks.begin(); set<BasicBlock *>::iterator itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pElseBody) { pNewIterations->addIncoming(pLoad0, pElseBody); } else { pNewIterations->addIncoming(pIterationAdd, *itSetBegin); } } pLoad0 = new LoadInst(pAlloc, "", false, itInsert); BinaryOperator * pWorkingAdd = BinaryOperator::Create(Instruction::Add, pNewWorkingIterations, pLoad0, "Working.add.2", itInsert); itSetBegin = setPredBlocks.begin(); itSetEnd = setPredBlocks.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { if((*itSetBegin) == pElseBody) { pNewWorkingIterations->addIncoming(pLoad1, pElseBody); } else { pNewWorkingIterations->addIncoming(pWorkingAdd, *itSetBegin); } } pStore = new StoreInst(this->ConstantLong0, pAlloc, false, itInsert); pStore->setAlignment(8); itSetBegin = setExitBlock.begin(); itSetEnd = setExitBlock.end(); for(; itSetBegin != itSetEnd; itSetBegin ++ ) { SmallVector<BasicBlock*, 8> LoopBlocks; for(pred_iterator PI = pred_begin(*itSetBegin), E = pred_end(*itSetBegin); PI != E; ++PI) { if(setCloned.find(*PI) != setCloned.end()) { LoopBlocks.push_back(*PI); } } BasicBlock * NewExitBB = SplitBlockPredecessors(*itSetBegin, LoopBlocks, ".WL.loopexit", this); pStore = new StoreInst(pIterationAdd, this->numIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); pStore = new StoreInst(pWorkingAdd, this->numWorkingIterations, false, NewExitBB->getFirstInsertionPt()); pStore->setAlignment(8); } //pFunction->dump(); DominatorTree * DT = &(getAnalysis<DominatorTree>(*pFunction)); vector<AllocaInst *> vecAlloc; vecAlloc.push_back(pAlloc); PromoteMemToReg(vecAlloc, *DT); pFunction->dump(); }
/// HandleURoRInvokes - Handle invokes of "_Unwind_Resume_or_Rethrow" calls. The /// "unwind" part of these invokes jump to a landing pad within the current /// function. This is a candidate to merge the selector associated with the URoR /// invoke with the one from the URoR's landing pad. bool DwarfEHPrepare::HandleURoRInvokes() { if (!EHCatchAllValue) { EHCatchAllValue = F->getParent()->getNamedGlobal("llvm.eh.catch.all.value"); if (!EHCatchAllValue) return false; } if (!SelectorIntrinsic) { SelectorIntrinsic = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_selector); if (!SelectorIntrinsic) return false; } SmallPtrSet<IntrinsicInst*, 32> Sels; SmallPtrSet<IntrinsicInst*, 32> CatchAllSels; FindAllCleanupSelectors(Sels, CatchAllSels); if (!DT) // We require DominatorTree information. return CleanupSelectors(CatchAllSels); if (!URoR) { URoR = F->getParent()->getFunction("_Unwind_Resume_or_Rethrow"); if (!URoR) return CleanupSelectors(CatchAllSels); } SmallPtrSet<InvokeInst*, 32> URoRInvokes; FindAllURoRInvokes(URoRInvokes); SmallPtrSet<IntrinsicInst*, 32> SelsToConvert; for (SmallPtrSet<IntrinsicInst*, 32>::iterator SI = Sels.begin(), SE = Sels.end(); SI != SE; ++SI) { const BasicBlock *SelBB = (*SI)->getParent(); for (SmallPtrSet<InvokeInst*, 32>::iterator UI = URoRInvokes.begin(), UE = URoRInvokes.end(); UI != UE; ++UI) { const BasicBlock *URoRBB = (*UI)->getParent(); if (DT->dominates(SelBB, URoRBB)) { SelsToConvert.insert(*SI); break; } } } bool Changed = false; if (Sels.size() != SelsToConvert.size()) { // If we haven't been able to convert all of the clean-up selectors, then // loop through the slow way to see if they still need to be converted. if (!ExceptionValueIntrinsic) { ExceptionValueIntrinsic = Intrinsic::getDeclaration(F->getParent(), Intrinsic::eh_exception); if (!ExceptionValueIntrinsic) return CleanupSelectors(CatchAllSels); } for (Value::use_iterator I = ExceptionValueIntrinsic->use_begin(), E = ExceptionValueIntrinsic->use_end(); I != E; ++I) { IntrinsicInst *EHPtr = dyn_cast<IntrinsicInst>(*I); if (!EHPtr || EHPtr->getParent()->getParent() != F) continue; Changed |= PromoteEHPtrStore(EHPtr); bool URoRInvoke = false; SmallPtrSet<IntrinsicInst*, 8> SelCalls; Changed |= FindSelectorAndURoR(EHPtr, URoRInvoke, SelCalls); if (URoRInvoke) { // This EH pointer is being used by an invoke of an URoR instruction and // an eh.selector intrinsic call. If the eh.selector is a 'clean-up', we // need to convert it to a 'catch-all'. for (SmallPtrSet<IntrinsicInst*, 8>::iterator SI = SelCalls.begin(), SE = SelCalls.end(); SI != SE; ++SI) if (!HasCatchAllInSelector(*SI)) SelsToConvert.insert(*SI); } } } if (!SelsToConvert.empty()) { // Convert all clean-up eh.selectors, which are associated with "invokes" of // URoR calls, into catch-all eh.selectors. Changed = true; for (SmallPtrSet<IntrinsicInst*, 8>::iterator SI = SelsToConvert.begin(), SE = SelsToConvert.end(); SI != SE; ++SI) { IntrinsicInst *II = *SI; // Use the exception object pointer and the personality function // from the original selector. CallSite CS(II); IntrinsicInst::op_iterator I = CS.arg_begin(); IntrinsicInst::op_iterator E = CS.arg_end(); IntrinsicInst::op_iterator B = prior(E); // Exclude last argument if it is an integer. if (isa<ConstantInt>(B)) E = B; // Add exception object pointer (front). // Add personality function (next). // Add in any filter IDs (rest). SmallVector<Value*, 8> Args(I, E); Args.push_back(EHCatchAllValue->getInitializer()); // Catch-all indicator. CallInst *NewSelector = CallInst::Create(SelectorIntrinsic, Args.begin(), Args.end(), "eh.sel.catch.all", II); NewSelector->setTailCall(II->isTailCall()); NewSelector->setAttributes(II->getAttributes()); NewSelector->setCallingConv(II->getCallingConv()); II->replaceAllUsesWith(NewSelector); II->eraseFromParent(); } } Changed |= CleanupSelectors(CatchAllSels); return Changed; }
/// Replaces the given call site (Call or Invoke) with a gc.statepoint /// intrinsic with an empty deoptimization arguments list. This does /// NOT do explicit relocation for GC support. static Value *ReplaceWithStatepoint(const CallSite &CS /* to replace */) { assert(CS.getInstruction()->getModule() && "must be set"); // TODO: technically, a pass is not allowed to get functions from within a // function pass since it might trigger a new function addition. Refactor // this logic out to the initialization of the pass. Doesn't appear to // matter in practice. // Then go ahead and use the builder do actually do the inserts. We insert // immediately before the previous instruction under the assumption that all // arguments will be available here. We can't insert afterwards since we may // be replacing a terminator. IRBuilder<> Builder(CS.getInstruction()); // Note: The gc args are not filled in at this time, that's handled by // RewriteStatepointsForGC (which is currently under review). // Create the statepoint given all the arguments Instruction *Token = nullptr; uint64_t ID; uint32_t NumPatchBytes; AttributeSet OriginalAttrs = CS.getAttributes(); Attribute AttrID = OriginalAttrs.getAttribute(AttributeSet::FunctionIndex, "statepoint-id"); Attribute AttrNumPatchBytes = OriginalAttrs.getAttribute( AttributeSet::FunctionIndex, "statepoint-num-patch-bytes"); AttrBuilder AttrsToRemove; bool HasID = AttrID.isStringAttribute() && !AttrID.getValueAsString().getAsInteger(10, ID); if (HasID) AttrsToRemove.addAttribute("statepoint-id"); else ID = 0xABCDEF00; bool HasNumPatchBytes = AttrNumPatchBytes.isStringAttribute() && !AttrNumPatchBytes.getValueAsString().getAsInteger(10, NumPatchBytes); if (HasNumPatchBytes) AttrsToRemove.addAttribute("statepoint-num-patch-bytes"); else NumPatchBytes = 0; OriginalAttrs = OriginalAttrs.removeAttributes( CS.getInstruction()->getContext(), AttributeSet::FunctionIndex, AttrsToRemove); if (CS.isCall()) { CallInst *ToReplace = cast<CallInst>(CS.getInstruction()); CallInst *Call = Builder.CreateGCStatepointCall( ID, NumPatchBytes, CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None, "safepoint_token"); Call->setTailCall(ToReplace->isTailCall()); Call->setCallingConv(ToReplace->getCallingConv()); // In case if we can handle this set of attributes - set up function // attributes directly on statepoint and return attributes later for // gc_result intrinsic. Call->setAttributes(OriginalAttrs.getFnAttributes()); Token = Call; // Put the following gc_result and gc_relocate calls immediately after // the old call (which we're about to delete). assert(ToReplace->getNextNode() && "not a terminator, must have next"); Builder.SetInsertPoint(ToReplace->getNextNode()); Builder.SetCurrentDebugLocation(ToReplace->getNextNode()->getDebugLoc()); } else if (CS.isInvoke()) { InvokeInst *ToReplace = cast<InvokeInst>(CS.getInstruction()); // Insert the new invoke into the old block. We'll remove the old one in a // moment at which point this will become the new terminator for the // original block. Builder.SetInsertPoint(ToReplace->getParent()); InvokeInst *Invoke = Builder.CreateGCStatepointInvoke( ID, NumPatchBytes, CS.getCalledValue(), ToReplace->getNormalDest(), ToReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None, "safepoint_token"); Invoke->setCallingConv(ToReplace->getCallingConv()); // In case if we can handle this set of attributes - set up function // attributes directly on statepoint and return attributes later for // gc_result intrinsic. Invoke->setAttributes(OriginalAttrs.getFnAttributes()); Token = Invoke; // We'll insert the gc.result into the normal block BasicBlock *NormalDest = ToReplace->getNormalDest(); // Can not insert gc.result in case of phi nodes preset. // Should have removed this cases prior to running this function assert(!isa<PHINode>(NormalDest->begin())); Instruction *IP = &*(NormalDest->getFirstInsertionPt()); Builder.SetInsertPoint(IP); } else { llvm_unreachable("unexpect type of CallSite"); } assert(Token); // Handle the return value of the original call - update all uses to use a // gc_result hanging off the statepoint node we just inserted // Only add the gc_result iff there is actually a used result if (!CS.getType()->isVoidTy() && !CS.getInstruction()->use_empty()) { std::string TakenName = CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : ""; CallInst *GCResult = Builder.CreateGCResult(Token, CS.getType(), TakenName); GCResult->setAttributes(OriginalAttrs.getRetAttributes()); return GCResult; } else { // No return value for the call. return nullptr; } }
void FaultInjectionPass::insertInjectionFuncCall( std::map<Instruction*, std::list< int >* > *inst_regs_map, Module &M) { for (std::map<Instruction*, std::list< int >* >::iterator inst_reg_it = inst_regs_map->begin(); inst_reg_it != inst_regs_map->end(); ++inst_reg_it) { Instruction *fi_inst = inst_reg_it->first; std::list<int> *fi_reg_pos_list = inst_reg_it->second; unsigned reg_index = 0; unsigned total_reg_num = fi_reg_pos_list->size(); for (std::list<int>::iterator reg_pos_it = fi_reg_pos_list->begin(); reg_pos_it != fi_reg_pos_list->end(); ++reg_pos_it, ++reg_index) { if(isa<GetElementPtrInst>(fi_inst)){ GetElementPtrInst* gepi = dyn_cast<GetElementPtrInst>(fi_inst); gepi->setIsInBounds(false); } if(isa<CallInst>(fi_inst)){ CallInst* ci = dyn_cast<CallInst>(fi_inst); ci->setTailCall(false); } Value* fi_reg = NULL; if(*reg_pos_it == DST_REG_POS) fi_reg = fi_inst; else fi_reg = fi_inst->getOperand(*reg_pos_it); //if(isa<Constant>(fi_reg)) continue; Type *returntype = fi_reg->getType(); LLVMContext &context = M.getContext(); Type *i64type = Type::getInt64Ty(context); Type *i32type = Type::getInt32Ty(context); // function declaration std::vector<Type*> paramtypes(7); paramtypes[0] = i64type; // llfi index paramtypes[1] = returntype; // the instruction to be injected paramtypes[2] = i32type; // opcode paramtypes[3] = i32type; // current fi reg index paramtypes[4] = i32type; // total fi reg number //======== Add reg_pos QINING @DEC 23rd ========== paramtypes[5] = i32type; //================================================ //======== Add opcode_str QINING @MAR 11th======== paramtypes[6] = PointerType::get(Type::getInt8Ty(context), 0); //================================================ //LLVM 3.3 Upgrade ArrayRef<Type*> paramtypes_array_ref(paramtypes); FunctionType* injectfunctype = FunctionType::get(returntype, paramtypes_array_ref, false); std::string funcname = getFIFuncNameforType(returntype); Constant *injectfunc = M.getOrInsertFunction(funcname, injectfunctype); // argument preparation for calling function // since the source register is another way of simulating fault // injection into "the instruction", use instruction's index instead Value *indexval = ConstantInt::get(i64type, getLLFIIndexofInst(fi_inst)); std::vector<Value*> args(7); args[0] = indexval; //llfi index args[1] = fi_reg; // target register args[2] = ConstantInt::get(i32type, fi_inst->getOpcode()); // opcode in i32 args[3] = ConstantInt::get(i32type, reg_index); // reg_index not reg_pos args[4] = ConstantInt::get(i32type, total_reg_num); // total_reg_num //======== Add reg_pos QINING @DEC 23rd ========== args[5] = ConstantInt::get(i32type, *reg_pos_it+1); // dstreg->0, operand0->1, operand1->2 ... //================================================ //======== Add opcode_str QINING @MAR 11th======== std::string opcode_str = fi_inst->getOpcodeName(); GlobalVariable* opcode_str_gv = findOrCreateGlobalNameString(M, opcode_str); std::vector<Constant*> indices_for_gep(2); indices_for_gep[0] = ConstantInt::get(Type::getInt32Ty(context),0); indices_for_gep[1] = ConstantInt::get(Type::getInt32Ty(context),0); ArrayRef<Constant*> indices_for_gep_array_ref(indices_for_gep); Constant* gep_expr = ConstantExpr::getGetElementPtr(opcode_str_gv, indices_for_gep_array_ref, true); args[6] = gep_expr; // opcode in string //================================================ // LLVM 3.3 Upgrade ArrayRef<Value*> args_array_ref(args); Instruction *insertptr = getInsertPtrforRegsofInst(fi_reg, fi_inst); Instruction* ficall = CallInst::Create( injectfunc, args_array_ref, "fi", insertptr); setInjectFaultInst(fi_reg, fi_inst, ficall); // sets the instruction metadata // redirect the data dependencies if (fi_reg == fi_inst) { // inject into destination std::list<User*> inst_uses; for (Value::use_iterator use_it = fi_inst->use_begin(); use_it != fi_inst->use_end(); ++use_it) { User *user = *use_it; if (user != ficall) { inst_uses.push_back(user); } } for (std::list<User*>::iterator use_it = inst_uses.begin(); use_it != inst_uses.end(); ++use_it) { User *user = *use_it; user->replaceUsesOfWith(fi_inst, ficall); // update the selected inst pool /*if (Instruction *use_inst = dyn_cast<Instruction>(user)) { if (inst_regs_map->find(use_inst) != inst_regs_map->end()) { std::list<int> *reg_pos_list = (*inst_regs_map)[use_inst]; for (std::list<int>::iterator reg_pos_it = reg_pos_list->begin(); reg_pos_it != reg_pos_list->end(); ++reg_pos_it) { if (use_inst->getOperand(*reg_pos_it) == fi_inst) { use_inst->setOperand(*reg_pos_it, ficall); } } } }*/ } } else { // inject into source //fi_inst->replaceUsesOfWith(fi_reg, ficall); fi_inst->setOperand(*reg_pos_it, ficall); } } } }
/// DoPromotion - This method actually performs the promotion of the specified /// arguments, and returns the new function. At this point, we know that it's /// safe to do so. static Function * doPromotion(Function *F, SmallPtrSetImpl<Argument *> &ArgsToPromote, SmallPtrSetImpl<Argument *> &ByValArgsToTransform, Optional<function_ref<void(CallSite OldCS, CallSite NewCS)>> ReplaceCallSite) { // Start by computing a new prototype for the function, which is the same as // the old function, but has modified arguments. FunctionType *FTy = F->getFunctionType(); std::vector<Type *> Params; using ScalarizeTable = std::set<std::pair<Type *, IndicesVector>>; // ScalarizedElements - If we are promoting a pointer that has elements // accessed out of it, keep track of which elements are accessed so that we // can add one argument for each. // // Arguments that are directly loaded will have a zero element value here, to // handle cases where there are both a direct load and GEP accesses. std::map<Argument *, ScalarizeTable> ScalarizedElements; // OriginalLoads - Keep track of a representative load instruction from the // original function so that we can tell the alias analysis implementation // what the new GEP/Load instructions we are inserting look like. // We need to keep the original loads for each argument and the elements // of the argument that are accessed. std::map<std::pair<Argument *, IndicesVector>, LoadInst *> OriginalLoads; // Attribute - Keep track of the parameter attributes for the arguments // that we are *not* promoting. For the ones that we do promote, the parameter // attributes are lost SmallVector<AttributeSet, 8> ArgAttrVec; AttributeList PAL = F->getAttributes(); // First, determine the new argument list unsigned ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgNo) { if (ByValArgsToTransform.count(&*I)) { // Simple byval argument? Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); Params.insert(Params.end(), STy->element_begin(), STy->element_end()); ArgAttrVec.insert(ArgAttrVec.end(), STy->getNumElements(), AttributeSet()); ++NumByValArgsPromoted; } else if (!ArgsToPromote.count(&*I)) { // Unchanged argument Params.push_back(I->getType()); ArgAttrVec.push_back(PAL.getParamAttributes(ArgNo)); } else if (I->use_empty()) { // Dead argument (which are always marked as promotable) ++NumArgumentsDead; // There may be remaining metadata uses of the argument for things like // llvm.dbg.value. Replace them with undef. I->replaceAllUsesWith(UndefValue::get(I->getType())); } else { // Okay, this is being promoted. This means that the only uses are loads // or GEPs which are only used by loads // In this table, we will track which indices are loaded from the argument // (where direct loads are tracked as no indices). ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; for (User *U : I->users()) { Instruction *UI = cast<Instruction>(U); Type *SrcTy; if (LoadInst *L = dyn_cast<LoadInst>(UI)) SrcTy = L->getType(); else SrcTy = cast<GetElementPtrInst>(UI)->getSourceElementType(); IndicesVector Indices; Indices.reserve(UI->getNumOperands() - 1); // Since loads will only have a single operand, and GEPs only a single // non-index operand, this will record direct loads without any indices, // and gep+loads with the GEP indices. for (User::op_iterator II = UI->op_begin() + 1, IE = UI->op_end(); II != IE; ++II) Indices.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Indices.size() == 1 && Indices.front() == 0) Indices.clear(); ArgIndices.insert(std::make_pair(SrcTy, Indices)); LoadInst *OrigLoad; if (LoadInst *L = dyn_cast<LoadInst>(UI)) OrigLoad = L; else // Take any load, we will use it only to update Alias Analysis OrigLoad = cast<LoadInst>(UI->user_back()); OriginalLoads[std::make_pair(&*I, Indices)] = OrigLoad; } // Add a parameter to the function for each element passed in. for (const auto &ArgIndex : ArgIndices) { // not allowed to dereference ->begin() if size() is 0 Params.push_back(GetElementPtrInst::getIndexedType( cast<PointerType>(I->getType()->getScalarType())->getElementType(), ArgIndex.second)); ArgAttrVec.push_back(AttributeSet()); assert(Params.back()); } if (ArgIndices.size() == 1 && ArgIndices.begin()->second.empty()) ++NumArgumentsPromoted; else ++NumAggregatesPromoted; } } Type *RetTy = FTy->getReturnType(); // Construct the new function type using the new arguments. FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName()); NF->copyAttributesFrom(F); // Patch the pointer to LLVM function in debug info descriptor. NF->setSubprogram(F->getSubprogram()); F->setSubprogram(nullptr); DEBUG(dbgs() << "ARG PROMOTION: Promoting to:" << *NF << "\n" << "From: " << *F); // Recompute the parameter attributes list based on the new arguments for // the function. NF->setAttributes(AttributeList::get(F->getContext(), PAL.getFnAttributes(), PAL.getRetAttributes(), ArgAttrVec)); ArgAttrVec.clear(); F->getParent()->getFunctionList().insert(F->getIterator(), NF); NF->takeName(F); // Loop over all of the callers of the function, transforming the call sites // to pass in the loaded pointers. // SmallVector<Value *, 16> Args; while (!F->use_empty()) { CallSite CS(F->user_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttributeList &CallPAL = CS.getAttributes(); // Loop over the operands, inserting GEP and loads in the caller as // appropriate. CallSite::arg_iterator AI = CS.arg_begin(); ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++AI, ++ArgNo) if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I)) { Args.push_back(*AI); // Unmodified argument ArgAttrVec.push_back(CallPAL.getParamAttributes(ArgNo)); } else if (ByValArgsToTransform.count(&*I)) { // Emit a GEP and load for each element of the struct. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create( STy, *AI, Idxs, (*AI)->getName() + "." + Twine(i), Call); // TODO: Tell AA about the new values? Args.push_back(new LoadInst(Idx, Idx->getName() + ".val", Call)); ArgAttrVec.push_back(AttributeSet()); } } else if (!I->use_empty()) { // Non-dead argument: insert GEPs and loads as appropriate. ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; // Store the Value* version of the indices in here, but declare it now // for reuse. std::vector<Value *> Ops; for (const auto &ArgIndex : ArgIndices) { Value *V = *AI; LoadInst *OrigLoad = OriginalLoads[std::make_pair(&*I, ArgIndex.second)]; if (!ArgIndex.second.empty()) { Ops.reserve(ArgIndex.second.size()); Type *ElTy = V->getType(); for (auto II : ArgIndex.second) { // Use i32 to index structs, and i64 for others (pointers/arrays). // This satisfies GEP constraints. Type *IdxTy = (ElTy->isStructTy() ? Type::getInt32Ty(F->getContext()) : Type::getInt64Ty(F->getContext())); Ops.push_back(ConstantInt::get(IdxTy, II)); // Keep track of the type we're currently indexing. if (auto *ElPTy = dyn_cast<PointerType>(ElTy)) ElTy = ElPTy->getElementType(); else ElTy = cast<CompositeType>(ElTy)->getTypeAtIndex(II); } // And create a GEP to extract those indices. V = GetElementPtrInst::Create(ArgIndex.first, V, Ops, V->getName() + ".idx", Call); Ops.clear(); } // Since we're replacing a load make sure we take the alignment // of the previous load. LoadInst *newLoad = new LoadInst(V, V->getName() + ".val", Call); newLoad->setAlignment(OrigLoad->getAlignment()); // Transfer the AA info too. AAMDNodes AAInfo; OrigLoad->getAAMetadata(AAInfo); newLoad->setAAMetadata(AAInfo); Args.push_back(newLoad); ArgAttrVec.push_back(AttributeSet()); } } // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgNo) { Args.push_back(*AI); ArgAttrVec.push_back(CallPAL.getParamAttributes(ArgNo)); } SmallVector<OperandBundleDef, 1> OpBundles; CS.getOperandBundlesAsDefs(OpBundles); CallSite NewCS; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { NewCS = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args, OpBundles, "", Call); } else { auto *NewCall = CallInst::Create(NF, Args, OpBundles, "", Call); NewCall->setTailCallKind(cast<CallInst>(Call)->getTailCallKind()); NewCS = NewCall; } NewCS.setCallingConv(CS.getCallingConv()); NewCS.setAttributes( AttributeList::get(F->getContext(), CallPAL.getFnAttributes(), CallPAL.getRetAttributes(), ArgAttrVec)); NewCS->setDebugLoc(Call->getDebugLoc()); uint64_t W; if (Call->extractProfTotalWeight(W)) NewCS->setProfWeight(W); Args.clear(); ArgAttrVec.clear(); // Update the callgraph to know that the callsite has been transformed. if (ReplaceCallSite) (*ReplaceCallSite)(CS, NewCS); if (!Call->use_empty()) { Call->replaceAllUsesWith(NewCS.getInstruction()); NewCS->takeName(Call); } // Finally, remove the old call from the program, reducing the use-count of // F. Call->eraseFromParent(); } const DataLayout &DL = F->getParent()->getDataLayout(); // 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(), F->getBasicBlockList()); // Loop over the argument list, transferring uses of the old arguments over to // the new arguments, also transferring over the names as well. for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin(); I != E; ++I) { if (!ArgsToPromote.count(&*I) && !ByValArgsToTransform.count(&*I)) { // If this is an unmodified argument, move the name and users over to the // new version. I->replaceAllUsesWith(&*I2); I2->takeName(&*I); ++I2; continue; } if (ByValArgsToTransform.count(&*I)) { // In the callee, we create an alloca, and store each of the new incoming // arguments into the alloca. Instruction *InsertPt = &NF->begin()->front(); // Just add all the struct element types. Type *AgTy = cast<PointerType>(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, DL.getAllocaAddrSpace(), nullptr, I->getParamAlignment(), "", InsertPt); StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = {ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), nullptr}; for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { Idxs[1] = ConstantInt::get(Type::getInt32Ty(F->getContext()), i); Value *Idx = GetElementPtrInst::Create( AgTy, TheAlloca, Idxs, TheAlloca->getName() + "." + Twine(i), InsertPt); I2->setName(I->getName() + "." + Twine(i)); new StoreInst(&*I2++, Idx, InsertPt); } // Anything that used the arg should now use the alloca. I->replaceAllUsesWith(TheAlloca); TheAlloca->takeName(&*I); // If the alloca is used in a call, we must clear the tail flag since // the callee now uses an alloca from the caller. for (User *U : TheAlloca->users()) { CallInst *Call = dyn_cast<CallInst>(U); if (!Call) continue; Call->setTailCall(false); } continue; } if (I->use_empty()) continue; // Otherwise, if we promoted this argument, then all users are load // instructions (or GEPs with only load users), and all loads should be // using the new argument that we added. ScalarizeTable &ArgIndices = ScalarizedElements[&*I]; while (!I->use_empty()) { if (LoadInst *LI = dyn_cast<LoadInst>(I->user_back())) { assert(ArgIndices.begin()->second.empty() && "Load element should sort to front!"); I2->setName(I->getName() + ".val"); LI->replaceAllUsesWith(&*I2); LI->eraseFromParent(); DEBUG(dbgs() << "*** Promoted load of argument '" << I->getName() << "' in function '" << F->getName() << "'\n"); } else { GetElementPtrInst *GEP = cast<GetElementPtrInst>(I->user_back()); IndicesVector Operands; Operands.reserve(GEP->getNumIndices()); for (User::op_iterator II = GEP->idx_begin(), IE = GEP->idx_end(); II != IE; ++II) Operands.push_back(cast<ConstantInt>(*II)->getSExtValue()); // GEPs with a single 0 index can be merged with direct loads if (Operands.size() == 1 && Operands.front() == 0) Operands.clear(); Function::arg_iterator TheArg = I2; for (ScalarizeTable::iterator It = ArgIndices.begin(); It->second != Operands; ++It, ++TheArg) { assert(It != ArgIndices.end() && "GEP not handled??"); } std::string NewName = I->getName(); for (unsigned i = 0, e = Operands.size(); i != e; ++i) { NewName += "." + utostr(Operands[i]); } NewName += ".val"; TheArg->setName(NewName); DEBUG(dbgs() << "*** Promoted agg argument '" << TheArg->getName() << "' of function '" << NF->getName() << "'\n"); // All of the uses must be load instructions. Replace them all with // the argument specified by ArgNo. while (!GEP->use_empty()) { LoadInst *L = cast<LoadInst>(GEP->user_back()); L->replaceAllUsesWith(&*TheArg); L->eraseFromParent(); } GEP->eraseFromParent(); } } // Increment I2 past all of the arguments added for this promoted pointer. std::advance(I2, ArgIndices.size()); } return NF; }
/// run - Start execution with the specified function and arguments. /// GenericValue JIT::runFunction(Function *F, const std::vector<GenericValue> &ArgValues) { assert(F && "Function *F was null at entry to run()"); void *FPtr = getPointerToFunction(F); assert(FPtr && "Pointer to fn's code was null after getPointerToFunction"); const FunctionType *FTy = F->getFunctionType(); const Type *RetTy = FTy->getReturnType(); assert((FTy->getNumParams() <= ArgValues.size() || FTy->isVarArg()) && "Too many arguments passed into function!"); assert(FTy->getNumParams() == ArgValues.size() && "This doesn't support passing arguments through varargs (yet)!"); //// Brooks //// X86 Opcode 0x0f39 called here cout<<"****** SWITCHING TO SIMULATION MODE FROM NATIVE MODE ***** \n"; ptlcall_switch_to_sim(); cout<<"____ SIWTCH DONE ____ \n"; int * a=(int*)0x85df65d; cout<<"Value: "<<std::hex<<*(a)<<" "<<*(a+1)<<"\n"; asm(".byte 0x0f; .byte 0x39;"); // Handle some common cases first. These cases correspond to common `main' // prototypes. if (RetTy == Type::Int32Ty || RetTy == Type::VoidTy) { switch (ArgValues.size()) { case 3: if (FTy->getParamType(0) == Type::Int32Ty && isa<PointerType>(FTy->getParamType(1)) && isa<PointerType>(FTy->getParamType(2))) { int (*PF)(int, char **, const char **) = (int(*)(int, char **, const char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]), (const char **)GVTOP(ArgValues[2]))); return rv; } break; case 2: if (FTy->getParamType(0) == Type::Int32Ty && isa<PointerType>(FTy->getParamType(1))) { int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; // Call the function. GenericValue rv; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), (char **)GVTOP(ArgValues[1]))); return rv; } break; case 1: if (FTy->getNumParams() == 1 && FTy->getParamType(0) == Type::Int32Ty) { GenericValue rv; int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); return rv; } break; } } // Handle cases where no arguments are passed first. if (ArgValues.empty()) { GenericValue rv; switch (RetTy->getTypeID()) { default: assert(0 && "Unknown return type for function call!"); case Type::IntegerTyID: { unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); if (BitWidth == 1) rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)()); else if (BitWidth <= 8) rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)()); else if (BitWidth <= 16) rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)()); else if (BitWidth <= 32) rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)()); else if (BitWidth <= 64) rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)()); else assert(0 && "Integer types > 64 bits not supported"); return rv; } case Type::VoidTyID: rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)()); return rv; case Type::FloatTyID: rv.FloatVal = ((float(*)())(intptr_t)FPtr)(); return rv; case Type::DoubleTyID: rv.DoubleVal = ((double(*)())(intptr_t)FPtr)(); return rv; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: assert(0 && "long double not supported yet"); return rv; case Type::PointerTyID: return PTOGV(((void*(*)())(intptr_t)FPtr)()); } } // Okay, this is not one of our quick and easy cases. Because we don't have a // full FFI, we have to codegen a nullary stub function that just calls the // function we are interested in, passing in constants for all of the // arguments. Make this function and return. // First, create the function. FunctionType *STy=FunctionType::get(RetTy, std::vector<const Type*>(), false); Function *Stub = Function::Create(STy, Function::InternalLinkage, "", F->getParent()); // Insert a basic block. BasicBlock *StubBB = BasicBlock::Create("", Stub); // Convert all of the GenericValue arguments over to constants. Note that we // currently don't support varargs. SmallVector<Value*, 8> Args; for (unsigned i = 0, e = ArgValues.size(); i != e; ++i) { Constant *C = 0; const Type *ArgTy = FTy->getParamType(i); const GenericValue &AV = ArgValues[i]; switch (ArgTy->getTypeID()) { default: assert(0 && "Unknown argument type for function call!"); case Type::IntegerTyID: C = ConstantInt::get(AV.IntVal); break; case Type::FloatTyID: C = ConstantFP::get(APFloat(AV.FloatVal)); break; case Type::DoubleTyID: C = ConstantFP::get(APFloat(AV.DoubleVal)); break; case Type::PPC_FP128TyID: case Type::X86_FP80TyID: case Type::FP128TyID: C = ConstantFP::get(APFloat(AV.IntVal)); break; case Type::PointerTyID: void *ArgPtr = GVTOP(AV); if (sizeof(void*) == 4) C = ConstantInt::get(Type::Int32Ty, (int)(intptr_t)ArgPtr); else C = ConstantInt::get(Type::Int64Ty, (intptr_t)ArgPtr); C = ConstantExpr::getIntToPtr(C, ArgTy); // Cast the integer to pointer break; } Args.push_back(C); } CallInst *TheCall = CallInst::Create(F, Args.begin(), Args.end(), "", StubBB); TheCall->setTailCall(); if (TheCall->getType() != Type::VoidTy) ReturnInst::Create(TheCall, StubBB); // Return result of the call. else ReturnInst::Create(StubBB); // Just return void. // Finally, return the value returned by our nullary stub function. return runFunction(Stub, std::vector<GenericValue>()); }