ejsval Module_prototype_getOrInsertFunction(ejsval env, ejsval _this, int argc, ejsval *args) { Module *module = ((Module*)EJSVAL_TO_OBJECT(_this)); REQ_UTF8_ARG(0, name); REQ_LLVM_TYPE_ARG(1, returnType); REQ_ARRAY_ARG(2, paramTypes); std::vector< llvm::Type*> param_types; for (int i = 0; i < EJSARRAY_LEN(paramTypes); i ++) { param_types.push_back (Type_GetLLVMObj(EJSDENSEARRAY_ELEMENTS(paramTypes)[i])); } llvm::FunctionType *FT = llvm::FunctionType::get(returnType, param_types, false); llvm::Function* f = static_cast< llvm::Function*>(module->llvm_module->getOrInsertFunction(name, FT)); // XXX this needs to come from the js call, since when we hoist anonymous methods we'll need to give them a private linkage. f->setLinkage (llvm::Function::ExternalLinkage); // XXX the args might not be identifiers but might instead be destructuring expressions. punt for now. #if notyet // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); #endif return Function_new (f); }
Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); return F; }
Function* Codegen_Function_Declaration(project473::AstNodePtr declaration_node) { char* fname = strdup(declaration_node->nSymbolPtr->id); std::string Name(fname); std::vector<Type*> formalvars; project473::AstNodePtr formalVar = declaration_node->children[0]; while(formalVar) { if(formalVar->nSymbolPtr->stype->kind == project473::INT) { formalvars.push_back(Type::getInt32Ty(getGlobalContext())); formalVar=formalVar->sibling; } else { printf("Error, formal variable is not an int, in line: %d", formalVar->nLinenumber); } } project473::Type* functionTypeList = declaration_node->nSymbolPtr->stype->function; FunctionType *FT; if(functionTypeList->kind==project473::INT) { FT = FunctionType::get(Type::getInt32Ty(getGlobalContext()), formalvars, false); } else if(functionTypeList->kind==project473::VOID) { FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), formalvars, false); } Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // Set names for all arguments. Reuse formalVar formalVar = declaration_node->children[0]; for (Function::arg_iterator AI = F->arg_begin(); formalVar != NULL; ++AI, formalVar=formalVar->sibling) { std::string argName(formalVar->nSymbolPtr->id); AI->setName(argName); } Functions[Name] = F; //add the Function to the map of functions return F; }
Function *Codegen::Generate(PrototypeAST *proto) { string funcName = proto->GetName(); vector<string> args = proto->GetArgs(); vector<Type*> Doubles(args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *funcType = FunctionType::get( Type::getDoubleTy(getGlobalContext()), Doubles, false); Function* func = Function::Create(funcType, Function::ExternalLinkage, funcName, TheModule); if (func->getName() != funcName) { func->eraseFromParent(); func = TheModule->getFunction(funcName); if ( !func->empty()) { BaseError::Throw<Function*>("Redefinition of function"); return 0; } if (func->arg_size() != args.size()) { BaseError::Throw<Function*>("Redefinition of function with wrong number of arguments"); return 0; } } unsigned idx = 0; for (Function::arg_iterator iterItem = func->arg_begin(); idx != args.size(); ++iterItem, ++idx) { iterItem->setName(args[idx]); } return func; }
/// CloneFunction - Return a copy of the specified function, but without /// embedding the function into another module. Also, any references specified /// in the VMap are changed to refer to their mapped value instead of the /// original one. If any of the arguments to the function are in the VMap, /// the arguments are deleted from the resultant function. The VMap is /// updated to include mappings from all of the instructions and basicblocks in /// the function from their old to new values. /// Function *llvm::CloneFunction(const Function *F, ValueToValueMapTy &VMap, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo) { std::vector<Type*> ArgTypes; // The user might be deleting arguments to the function by specifying them in // the VMap. If so, we need to not add the arguments to the arg ty vector // for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) if (VMap.count(I) == 0) // Haven't mapped the argument to anything yet? ArgTypes.push_back(I->getType()); // Create a new function type... FunctionType *FTy = FunctionType::get(F->getFunctionType()->getReturnType(), ArgTypes, F->getFunctionType()->isVarArg()); // Create the new function... Function *NewF = Function::Create(FTy, F->getLinkage(), F->getName()); // Loop over the arguments, copying the names of the mapped arguments over... Function::arg_iterator DestI = NewF->arg_begin(); for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) if (VMap.count(I) == 0) { // Is this argument preserved? DestI->setName(I->getName()); // Copy the name over... VMap[I] = DestI++; // Add mapping to VMap } SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. CloneFunctionInto(NewF, F, VMap, ModuleLevelChanges, Returns, "", CodeInfo); return NewF; }
void IrGen::visit(AstFunDef& funDef) { const auto functionIr = static_cast<llvm::Function*>(funDef.ir().irAddrOfIrObject()); assert(functionIr); if (m_builder.GetInsertBlock()) { m_BasicBlockStack.push(m_builder.GetInsertBlock()); } m_builder.SetInsertPoint( BasicBlock::Create(llvmContext, "entry", functionIr)); // Add all arguments to the symbol table and create their allocas. Also tell // llvm the name of each arg. Function::arg_iterator llvmArgIter = functionIr->arg_begin(); auto astArgIter = funDef.declaredArgs().cbegin(); for (/*nop*/; llvmArgIter != functionIr->arg_end(); ++llvmArgIter, ++astArgIter) { allocateAndInitLocalIrObjectFor( **astArgIter, llvmArgIter, (*astArgIter)->name()); llvmArgIter->setName((*astArgIter)->name()); } Value* bodyVal = callAcceptOn(funDef.body()); assert(bodyVal); if (funDef.body().objType().isVoid()) { m_builder.CreateRetVoid(); } else if (!funDef.body().objType().isNoreturn()) { m_builder.CreateRet(bodyVal); } if (!m_BasicBlockStack.empty()) { m_builder.SetInsertPoint(m_BasicBlockStack.top()); m_BasicBlockStack.pop(); } }
// Maybe make a clone, if a clone is made, return a pointer to it, if a clone // was not made return nullptr. Function *CSDataRando::makeFunctionClone(Function *F) { // Now we know how many arguments need to be passed, so we make the clones FuncInfo &FI = FunctionInfo[F]; if (FI.ArgNodes.size() == 0) { // No additional args to pass, no need to clone. return nullptr; } // Determine the type of the new function, we insert the new parameters for // the masks after the normal arguments, but before any va_args Type *MaskTy = TypeBuilder<mask_t, false>::get(F->getContext()); FunctionType *OldFuncTy = F->getFunctionType(); std::vector<Type*> ArgTys; ArgTys.insert(ArgTys.end(), OldFuncTy->param_begin(), OldFuncTy->param_end()); ArgTys.insert(ArgTys.end(), FI.ArgNodes.size(), MaskTy); FunctionType *CloneFuncTy = FunctionType::get(OldFuncTy->getReturnType(), ArgTys, OldFuncTy->isVarArg()); Function *Clone = Function::Create(CloneFuncTy, Function::InternalLinkage, F->getName() + "_CONTEXT_SENSITIVE"); F->getParent()->getFunctionList().insert(F->getIterator(), Clone); Function::arg_iterator CI = Clone->arg_begin(), CE = Clone->arg_end(); // Map the old arguments to the clone arguments and set the name of the // clone arguments the same as the original. for (Function::arg_iterator i = F->arg_begin(), e = F->arg_end(); i != e && CI != CE; i++, CI++) { FI.OldToNewMap[&*i] = &*CI; CI->setName(i->getName()); } // Set the name of the arg masks and associate them with the nodes they are // the masks for. for (unsigned i = 0, e = FI.ArgNodes.size(); i != e; ++i, ++CI) { CI->setName("arg_mask"); FI.ArgMaskMap[FI.ArgNodes[i]] = &*CI; } SmallVector<ReturnInst*, 8> Returns; CloneFunctionInto(Clone, F, FI.OldToNewMap, false, Returns); Clone->setCallingConv(F->getCallingConv()); // Invert OldToNewMap for (auto I : FI.OldToNewMap) { FI.NewToOldMap[I.second] = I.first; } NumClones++; return Clone; }
virtual Value * materializeValueFor(Value * V) { if(Function * fn = dyn_cast<Function>(V)) { assert(fn->getParent() == src); Function * newfn = dest->getFunction(fn->getName()); if(!newfn) { newfn = Function::Create(fn->getFunctionType(),fn->getLinkage(), fn->getName(),dest); newfn->copyAttributesFrom(fn); } if(!fn->isDeclaration() && newfn->isDeclaration() && copyGlobal(fn,data)) { for(Function::arg_iterator II = newfn->arg_begin(), I = fn->arg_begin(), E = fn->arg_end(); I != E; ++I, ++II) { II->setName(I->getName()); VMap[I] = II; } VMap[fn] = newfn; SmallVector<ReturnInst*,8> Returns; CloneFunctionInto(newfn, fn, VMap, true, Returns, "", NULL, NULL, this); } return newfn; } else if(GlobalVariable * GV = dyn_cast<GlobalVariable>(V)) { GlobalVariable * newGV = dest->getGlobalVariable(GV->getName(),true); if(!newGV) { newGV = new GlobalVariable(*dest,GV->getType()->getElementType(),GV->isConstant(),GV->getLinkage(),NULL,GV->getName(),NULL,GlobalVariable::NotThreadLocal,GV->getType()->getAddressSpace()); newGV->copyAttributesFrom(GV); if(!GV->isDeclaration()) { if(!copyGlobal(GV,data)) { newGV->setExternallyInitialized(true); } else if(GV->hasInitializer()) { Value * C = MapValue(GV->getInitializer(),VMap,RF_None,NULL,this); newGV->setInitializer(cast<Constant>(C)); } } } return newGV; } else if(MDNode * MD = dyn_cast<MDNode>(V)) { DISubprogram SP(MD); if(DI != NULL && SP.isSubprogram()) { if(Function * OF = SP.getFunction()) { Function * F = cast<Function>(MapValue(OF,VMap,RF_None,NULL,this)); DISubprogram NSP = DI->createFunction(SP.getContext(), SP.getName(), SP.getLinkageName(), DI->createFile(SP.getFilename(),SP.getDirectory()), SP.getLineNumber(), SP.getType(), SP.isLocalToUnit(), SP.isDefinition(), SP.getScopeLineNumber(),SP.getFlags(),SP.isOptimized(), F); return NSP; } /* fallthrough */ } /* fallthrough */ } return NULL; }
Function *PrototypeAST::Codegen(Function*& preexistingPrototype /*out*/) { preexistingPrototype = NULL; // Make the function type: double(double,double) etc. std::vector<const Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } // if there is a preexisting prototype only -- without a body -- and with matching args // then inform caller of this, so that the FunctionAST::Codegen can not accidentally // delete it on body compilation failure. preexistingPrototype = F; // printf("There was a pre-existing prototype for this function-- noting this fact: %p\n",preexistingPrototype); } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } return F; }
void llvm::copyFunctionBody(Function &New, const Function &Orig, ValueToValueMapTy &VMap) { if (!Orig.isDeclaration()) { Function::arg_iterator DestI = New.arg_begin(); for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end(); ++J) { DestI->setName(J->getName()); VMap[J] = DestI++; } SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned. CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns); } }
Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); // Create a subprogram DIE for this function. DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), KSDbgInfo.TheCU->getDirectory()); MDScope *FContext = Unit; unsigned LineNo = Line; unsigned ScopeLine = Line; DISubprogram SP = DBuilder->createFunction( FContext, Name, StringRef(), Unit, LineNo, CreateFunctionType(Args.size(), Unit), false /* internal linkage */, true /* definition */, ScopeLine, DebugNode::FlagPrototyped, false, F); KSDbgInfo.FnScopeMap[this] = SP; return F; }
Value* NFunction::codeGen(CodeGenContext& context) { vector<Type*> argTypes; for (ArgumentList::const_iterator it = arguments.begin(); it != arguments.end(); it++) { argTypes.push_back(typeOf((*it)->type)); } /* Create the top level interpreter function to call as entry */ FunctionType *ftype = FunctionType::get(typeOf(returnType), argTypes, false); auto name = id.name; Function *function = Function::Create(ftype, GlobalValue::InternalLinkage, name.c_str(), context.module); if (name == "main") context.mainFunction = function; // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (function->getName() != name) { // Delete the one we just made and get the existing one. function->eraseFromParent(); function = context.module->getFunction(name); } /* Push a new variable/block context */ BasicBlock *bblock = BasicBlock::Create(getGlobalContext(), "entry", function, 0); context.pushBlock(bblock); // Create arguments into symbol table unsigned index = 0; for (Function::arg_iterator iter = function->arg_begin(); index != arguments.size(); ++iter, ++index) { auto name = arguments[index]->identifier.name; std::cout << name << std::endl; iter->setName(name); context.locals()[name] = iter; } // Create function body Value *last = nullptr; for (StatementList::const_iterator it = block.begin(); it != block.end(); it++) { std::cout << "Generating code for " << typeid(**it).name() << ' ' << std::endl; last = (**it).codeGen(context); } context.popBlock(); return last; }
Function *ParallelLoopGenerator::createSubFnDefinition() { Function *F = Builder.GetInsertBlock()->getParent(); std::vector<Type *> Arguments(1, Builder.getInt8PtrTy()); FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false); Function *SubFn = Function::Create(FT, Function::InternalLinkage, F->getName() + ".polly.subfn", M); // Do not run any polly pass on the new function. SubFn->addFnAttr(PollySkipFnAttr); Function::arg_iterator AI = SubFn->arg_begin(); AI->setName("polly.par.userContext"); return SubFn; }
Function *OMPGenerator::createSubfunctionDefinition() { Module *M = getModule(); Function *F = Builder.GetInsertBlock()->getParent(); std::vector<Type *> Arguments(1, Builder.getInt8PtrTy()); FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false); Function *FN = Function::Create(FT, Function::InternalLinkage, F->getName() + ".omp_subfn", M); // Do not run any polly pass on the new function. FN->addFnAttr(PollySkipFnAttr); Function::arg_iterator AI = FN->arg_begin(); AI->setName("omp.userContext"); return FN; }
Function *Codegen::Generate(OperatorAST *opr) { NamedValues.clear(); string opName = (opr->IsBinary() ? "binary" : "unary") + opr->GetOp(); vector<string> args = opr->GetArgs(); vector<Type*> Doubles(args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *funcType = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function* func = Function::Create(funcType, Function::ExternalLinkage, opName, TheModule); if (func->getName() != opName) { func->eraseFromParent(); func = TheModule->getFunction(opName); if ( !func->empty()) { BaseError::Throw<Function*>("Redefinition of operator"); return 0; } if (func->arg_size() != args.size()) { BaseError::Throw<Function*>("Redefinition of operator with wrong number of arguments"); return 0; } } unsigned Idx = 0; for (Function::arg_iterator AI = func->arg_begin(); Idx != args.size(); ++AI, ++Idx) { AI->setName(args[Idx]); } // add the body BasicBlock *block = BasicBlock::Create(getGlobalContext(), "opfunc", func); Builder.SetInsertPoint(block); this->CreateArgumentAllocas(args, func); Value *retVal = this->Generate(opr->GetBody()); if (retVal) { Builder.CreateRet(retVal); verifyFunction( *func); TheFPM->run( *func); return func; } func->eraseFromParent(); return 0; }
static GlobalObject *makeInternalReplacement(GlobalObject *GO) { Module *M = GO->getParent(); GlobalObject *Ret; if (auto *F = dyn_cast<Function>(GO)) { if (F->isMaterializable()) { if (F->materialize()) message(LDPL_FATAL, "LLVM gold plugin has failed to read a function"); } auto *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), F->getName(), M); ValueToValueMapTy VM; Function::arg_iterator NewI = NewF->arg_begin(); for (auto &Arg : F->args()) { NewI->setName(Arg.getName()); VM[&Arg] = NewI; ++NewI; } NewF->getBasicBlockList().splice(NewF->end(), F->getBasicBlockList()); for (auto &BB : *NewF) { for (auto &Inst : BB) RemapInstruction(&Inst, VM, RF_IgnoreMissingEntries); } Ret = NewF; F->deleteBody(); } else { auto *Var = cast<GlobalVariable>(GO); Ret = new GlobalVariable( *M, Var->getType()->getElementType(), Var->isConstant(), Var->getLinkage(), Var->getInitializer(), Var->getName(), nullptr, Var->getThreadLocalMode(), Var->getType()->getAddressSpace(), Var->isExternallyInitialized()); Var->setInitializer(nullptr); } Ret->copyAttributesFrom(GO); Ret->setLinkage(GlobalValue::InternalLinkage); Ret->setComdat(GO->getComdat()); return Ret; }
Function* PrototypeAST::Codegen(){ std::vector<Type*> array_type(this->func_args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *Func_type = FunctionType::get(Type::getDoubleTy(getGlobalContext()), array_type, false); //std::cout << "Current register function name is " << func_name << std::endl; Module *current_module = theHelper->getModuleForNewFunction(); Function* func = Function::Create(Func_type, Function::ExternalLinkage, func_name, current_module); if (func == nullptr){ Error("Fail to construct a function proto"); return nullptr; } if (func->getName() != func_name){ func->eraseFromParent(); //在theHelper所有被JIT(Modules vector)或是没有JIT(openModule)的Modules中查找func; func = theHelper->getFunction(func_name); if (!func->empty()){ ErrorF("redefinition of function"); return nullptr; } if (func->arg_size() != func_args.size()){ ErrorF("Differenct arguments given"); return nullptr; } } unsigned Idx = 0; for (Function::arg_iterator AI = func->arg_begin(); Idx != this->func_args.size(); ++AI, ++Idx) AI->setName(this->func_args[Idx]); return func; }
Function *PrototypeAST::Codegen() { std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); // conflicted, redefinition or reextern if (F->getName() != Name) { F->eraseFromParent(); F = TheModule->getFunction(Name); if (!F->empty()) { ErrorF("redefinition of function"); return 0; } if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), KSDbgInfo.TheCU.getDirectory()); DIDescriptor FContext(Unit); unsigned LineNo = Line; unsigned ScopeLine = Line; DISubprogram SP = DBuilder->createFunction(FContext, Name, StringRef(), Unit, LineNo, CreateFunctionType(Args.size(), Unit), false, true, ScopeLine, DIDescriptor::FlagPrototyped, false, F); KSDbgInfo.FnScopeMap[this] = SP; return F; }
Function *PTXGenerator::createSubfunctionDefinition(int NumArgs) { assert(NumArgs == 1 && "we support only one array access now."); Module *M = getModule(); Function *F = Builder.GetInsertBlock()->getParent(); std::vector<Type *> Arguments; for (int i = 0; i < NumArgs; i++) Arguments.push_back(Builder.getInt8PtrTy()); FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false); Function *FN = Function::Create(FT, Function::InternalLinkage, F->getName() + "_ptx_subfn", M); FN->setCallingConv(CallingConv::PTX_Kernel); // Do not run any optimization pass on the new function. P->getAnalysis<polly::ScopDetection>().markFunctionAsInvalid(FN); for (Function::arg_iterator AI = FN->arg_begin(); AI != FN->arg_end(); ++AI) AI->setName("ptx.Array"); return FN; }
Function *ParallelLoopGenerator::createSubFnDefinition() { Function *F = Builder.GetInsertBlock()->getParent(); std::vector<Type *> Arguments(1, Builder.getInt8PtrTy()); FunctionType *FT = FunctionType::get(Builder.getVoidTy(), Arguments, false); Function *SubFn = Function::Create(FT, Function::InternalLinkage, F->getName() + "_polly_subfn", M); // Certain backends (e.g., NVPTX) do not support '.'s in function names. // Hence, we ensure that all '.'s are replaced by '_'s. std::string FunctionName = SubFn->getName(); std::replace(FunctionName.begin(), FunctionName.end(), '.', '_'); SubFn->setName(FunctionName); // Do not run any polly pass on the new function. SubFn->addFnAttr(PollySkipFnAttr); Function::arg_iterator AI = SubFn->arg_begin(); AI->setName("polly.par.userContext"); return SubFn; }
Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. std::vector<Type *> Doubles(Args.size(), Type::getDoubleTy(TheContext)); FunctionType *FT = FunctionType::get(Type::getDoubleTy(TheContext), Doubles, false); std::string FnName; FnName = MakeLegalFunctionName(Name); Module* M = TheHelper->getModuleForNewFunction(); Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); // FIXME: Implement duplicate function detection. // The check below will only work if the duplicate is in the open module. // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != FnName) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = M->getFunction(FnName); // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); return F; }
Function *PrototypeAST::IRGen(IRGenContext &C) const { std::string FnName = MakeLegalFunctionName(Name); // Make the function type: double(double,double) etc. std::vector<Type*> Doubles(Args.size(), Type::getDoubleTy(getGlobalContext())); FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, &C.getM()); // If F conflicted, there was already something named 'FnName'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != FnName) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = C.getM().getFunction(Name); // If F already has a body, reject this. if (!F->empty()) { ErrorP<Function>("redefinition of function"); return nullptr; } // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorP<Function>("redefinition of function with different # args"); return nullptr; } } // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); return F; }
// linkFunctionBody - Copy the source function over into the dest function and // fix up references to values. At this point we know that Dest is an external // function, and that Src is not. void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) { assert(Src && Dst && Dst->isDeclaration() && !Src->isDeclaration()); // Go through and convert function arguments over, remembering the mapping. Function::arg_iterator DI = Dst->arg_begin(); for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); I != E; ++I, ++DI) { DI->setName(I->getName()); // Copy the name over. // Add a mapping to our mapping. ValueMap[I] = DI; } if (Mode == Linker::DestroySource) { // Splice the body of the source function into the dest function. Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); // At this point, all of the instructions and values of the function are now // copied over. The only problem is that they are still referencing values in // the Source function as operands. Loop through all of the operands of the // functions and patch them up to point to the local versions. for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, &TypeMap); } else { // Clone the body of the function into the dest function. SmallVector<ReturnInst*, 8> Returns; // Ignore returns. CloneFunctionInto(Dst, Src, ValueMap, false, Returns, "", NULL, &TypeMap); } // There is no need to map the arguments anymore. for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); I != E; ++I) ValueMap.erase(I); }
void function::Codegen(Module *TheModule, IRBuilder<> *Builder, std::map<std::string, Value*> &NamedValues){ std::map<std::string, Value*> Values; //Neue Map Damit die Nodes innerhalb der Funktion nicht in die NamedValues kommen Values.insert(NamedValues.begin(), NamedValues.end()); vector<Type*> params = vector<Type*>(); for(map<string,string>::iterator it = parameters.begin(); it != parameters.end(); ++it){ params.push_back(getTypeFor(it->second)); } FunctionType* FT = FunctionType::get(getTypeFor(returnType), params, false); Function* F = Function::Create(FT, Function::ExternalLinkage, name, TheModule); //übergabe der parameter Function::arg_iterator AI = F->arg_begin(); for(std::map<std::string, std::string>::iterator it = parameters.begin(); it != parameters.end(); ++AI, ++it){ AI->setName(it->first); Values[it->first] = AI; } BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", F); Builder->SetInsertPoint(BB); for(map<string, node*>::iterator it = variables.begin(); it != variables.end(); ++it){ it->second->Codegen(TheModule, Builder, Values); } Builder->CreateRet(returnExp->Codegen(TheModule, Builder, Values)); //übergabe der kopierten Map }
Value *UserFunctionSexp::codegen(SexpCompilerContext& ctx) { vector<const Type*> doubles(args ? args->length(): 0, ctx.getDoubleTy()); FunctionType *type = FunctionType::get(ctx.getDoubleTy(), doubles, false); Function *func = Function::Create(type, Function::ExternalLinkage, name, &ctx.getToplevelModule()); if (args) { Function::arg_iterator it = func->arg_begin(); ConsSexp *cons = args; SymbolSexp *sym; while (cons && (sym = dynamic_cast<SymbolSexp*>(cons->car))) { it->setName(sym->getName()); cons = dynamic_cast<ConsSexp*>(cons->cdr); ++it; } } if (body) { BasicBlock *block = BasicBlock::Create(ctx.getLLVMContext(), "entry", func); Value *val = NULL; IRBuilder<> *builder = ctx.pushBuilder(block); for (ConsSexp *cons = body; cons; cons = dynamic_cast<ConsSexp*>(cons->cdr)) { if (cons->car) val = cons->car->codegen(ctx); } if (val) builder->CreateRet(val); ctx.popBuilder(); } return func; }
Function* ASTPrototype::Funcgen(CEnv& cenv) { // Make the function type, e.g. double(double,double) vector<const Type*> Doubles(_args.size(), Type::DoubleTy); FunctionType* FT = FunctionType::get(Type::DoubleTy, Doubles, false); Function* f = Function::Create( FT, Function::ExternalLinkage, _name, cenv.module); // If F conflicted, there was already something named 'Name'. // If it has a body, don't allow redefinition. if (f->getName() != _name) { // Delete the one we just made and get the existing one. f->eraseFromParent(); f = cenv.module->getFunction(_name); // If F already has a body, reject this. if (!f->empty()) throw SyntaxError("Function redefined"); // If F took a different number of args, reject. if (f->arg_size() != _args.size()) throw SyntaxError("Function redefined with mismatched arguments"); } // Set names for all arguments. size_t i = 0; for (Function::arg_iterator a = f->arg_begin(); i != _args.size(); ++a, ++i) { a->setName(_args[i]); // Add arguments to variable symbol table. cenv.env[_args[i]] = a; } return f; }
// // Method: buildBounce() // // Description: // Replaces the given call site with a call to a bounce function. The // bounce function compares the function pointer to one of the given // target functions and calls the function directly if the pointer // matches. // Function* Devirtualize::buildBounce (CallSite CS, std::vector<const Function*>& Targets) { // // Update the statistics on the number of bounce functions added to the // module. // ++FuncAdded; // // Create a bounce function that has a function signature almost identical // to the function being called. The only difference is that it will have // an additional pointer argument at the beginning of its argument list that // will be the function to call. // Value* ptr = CS.getCalledValue(); std::vector<Type *> TP; TP.insert (TP.begin(), ptr->getType()); for (CallSite::arg_iterator i = CS.arg_begin(); i != CS.arg_end(); ++i) { TP.push_back ((*i)->getType()); } FunctionType* NewTy = FunctionType::get(CS.getType(), TP, false); Module * M = CS.getInstruction()->getParent()->getParent()->getParent(); Function* F = Function::Create (NewTy, GlobalValue::InternalLinkage, "devirtbounce", M); // // Set the names of the arguments. Also, record the arguments in a vector // for subsequence access. // F->arg_begin()->setName("funcPtr"); std::vector<Value*> fargs; for(Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); ai != ae; ++ai) if (ai != F->arg_begin()) { fargs.push_back(ai); ai->setName("arg"); } // // Create an entry basic block for the function. All it should do is perform // some cast instructions and branch to the first comparison basic block. // BasicBlock* entryBB = BasicBlock::Create (M->getContext(), "entry", F); // // For each function target, create a basic block that will call that // function directly. // std::map<const Function*, BasicBlock*> targets; for (unsigned index = 0; index < Targets.size(); ++index) { const Function* FL = Targets[index]; // Create the basic block for doing the direct call BasicBlock* BL = BasicBlock::Create (M->getContext(), FL->getName(), F); targets[FL] = BL; // Create the direct function call Value* directCall = CallInst::Create ((Value *)FL, fargs, "", BL); // Add the return instruction for the basic block if (CS.getType()->isVoidTy()) ReturnInst::Create (M->getContext(), BL); else ReturnInst::Create (M->getContext(), directCall, BL); } // // Create a failure basic block. This basic block should simply be an // unreachable instruction. // BasicBlock * failBB = BasicBlock::Create (M->getContext(), "fail", F); new UnreachableInst (M->getContext(), failBB); // // Setup the entry basic block. For now, just have it call the failure // basic block. We'll change the basic block to which it branches later. // BranchInst * InsertPt = BranchInst::Create (failBB, entryBB); // // Create basic blocks which will test the value of the incoming function // pointer and branch to the appropriate basic block to call the function. // Type * VoidPtrType = getVoidPtrType (M->getContext()); Value * FArg = castTo (F->arg_begin(), VoidPtrType, "", InsertPt); BasicBlock * tailBB = failBB; for (unsigned index = 0; index < Targets.size(); ++index) { // // Cast the function pointer to an integer. This can go in the entry // block. // Value * TargetInt = castTo ((Value *)(Targets[index]), VoidPtrType, "", InsertPt); // // Create a new basic block that compares the function pointer to the // function target. If the function pointer matches, we'll branch to the // basic block performing the direct call for that function; otherwise, // we'll branch to the next function call target. // BasicBlock* TB = targets[Targets[index]]; BasicBlock* newB = BasicBlock::Create (M->getContext(), "test." + Targets[index]->getName(), F); CmpInst * setcc = CmpInst::Create (Instruction::ICmp, CmpInst::ICMP_EQ, TargetInt, FArg, "sc", newB); BranchInst::Create (TB, tailBB, setcc, newB); // // Make this newly created basic block the next block that will be reached // when the next comparison will need to be done. // tailBB = newB; } // // Make the entry basic block branch to the first comparison basic block. // //InsertPt->setUnconditionalDest (tailBB); InsertPt->setSuccessor(0, tailBB); InsertPt->setSuccessor(1, tailBB); // // Return the newly created bounce function. // return F; }
std::unique_ptr<Module> llvm::CloneModule( const Module *M, ValueToValueMapTy &VMap, std::function<bool(const GlobalValue *)> ShouldCloneDefinition) { // First off, we need to create the new module. std::unique_ptr<Module> New = llvm::make_unique<Module>(M->getModuleIdentifier(), M->getContext()); New->setDataLayout(M->getDataLayout()); New->setTargetTriple(M->getTargetTriple()); New->setModuleInlineAsm(M->getModuleInlineAsm()); // Loop over all of the global variables, making corresponding globals in the // new module. Here we add them to the VMap and to the new Module. We // don't worry about attributes or initializers, they will come later. // for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { GlobalVariable *GV = new GlobalVariable(*New, I->getValueType(), I->isConstant(), I->getLinkage(), (Constant*) nullptr, I->getName(), (GlobalVariable*) nullptr, I->getThreadLocalMode(), I->getType()->getAddressSpace()); GV->copyAttributesFrom(&*I); VMap[&*I] = GV; } // Loop over the functions in the module, making external functions as before for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { Function *NF = Function::Create(cast<FunctionType>(I->getValueType()), I->getLinkage(), I->getName(), New.get()); NF->copyAttributesFrom(&*I); VMap[&*I] = NF; } // Loop over the aliases in the module for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) { if (!ShouldCloneDefinition(&*I)) { // An alias cannot act as an external reference, so we need to create // either a function or a global variable depending on the value type. // FIXME: Once pointee types are gone we can probably pick one or the // other. GlobalValue *GV; if (I->getValueType()->isFunctionTy()) GV = Function::Create(cast<FunctionType>(I->getValueType()), GlobalValue::ExternalLinkage, I->getName(), New.get()); else GV = new GlobalVariable( *New, I->getValueType(), false, GlobalValue::ExternalLinkage, (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr, I->getThreadLocalMode(), I->getType()->getAddressSpace()); VMap[&*I] = GV; // We do not copy attributes (mainly because copying between different // kinds of globals is forbidden), but this is generally not required for // correctness. continue; } auto *GA = GlobalAlias::create(I->getValueType(), I->getType()->getPointerAddressSpace(), I->getLinkage(), I->getName(), New.get()); GA->copyAttributesFrom(&*I); VMap[&*I] = GA; } // Now that all of the things that global variable initializer can refer to // have been created, loop through and copy the global variable referrers // over... We also set the attributes on the global now. // for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { GlobalVariable *GV = cast<GlobalVariable>(VMap[&*I]); if (!ShouldCloneDefinition(&*I)) { // Skip after setting the correct linkage for an external reference. GV->setLinkage(GlobalValue::ExternalLinkage); continue; } if (I->hasInitializer()) GV->setInitializer(MapValue(I->getInitializer(), VMap)); } // Similarly, copy over function bodies now... // for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { Function *F = cast<Function>(VMap[&*I]); if (!ShouldCloneDefinition(&*I)) { // Skip after setting the correct linkage for an external reference. F->setLinkage(GlobalValue::ExternalLinkage); // Personality function is not valid on a declaration. F->setPersonalityFn(nullptr); continue; } if (!I->isDeclaration()) { Function::arg_iterator DestI = F->arg_begin(); for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end(); ++J) { DestI->setName(J->getName()); VMap[&*J] = &*DestI++; } SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns); } if (I->hasPersonalityFn()) F->setPersonalityFn(MapValue(I->getPersonalityFn(), VMap)); } // And aliases for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) { // We already dealt with undefined aliases above. if (!ShouldCloneDefinition(&*I)) continue; GlobalAlias *GA = cast<GlobalAlias>(VMap[&*I]); if (const Constant *C = I->getAliasee()) GA->setAliasee(MapValue(C, VMap)); } // And named metadata.... for (Module::const_named_metadata_iterator I = M->named_metadata_begin(), E = M->named_metadata_end(); I != E; ++I) { const NamedMDNode &NMD = *I; NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName()); for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap)); } return New; }
/// 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, SmallPtrSet<Argument*, 8> &ArgsToPromote, SmallPtrSet<Argument*, 8> &ByValArgsToTransform) { // Start by computing a new prototype for the function, which is the same as // the old function, but has modified arguments. const FunctionType *FTy = F->getFunctionType(); std::vector<const 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. std::map<IndicesVector, LoadInst*> OriginalLoads; // Attributes - 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<AttributeWithIndex, 8> AttributesVec; const AttrListPtr &PAL = F->getAttributes(); // Add any return attributes. if (Attributes attrs = PAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // 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. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); const 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()); if (Attributes attrs = PAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Params.size(), attrs)); } 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 (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) { Instruction *User = cast<Instruction>(*UI); assert(isa<LoadInst>(User) || isa<GetElementPtrInst>(User)); IndicesVector Indices; Indices.reserve(User->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 = User->op_begin() + 1, IE = User->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>(User)) OrigLoad = L; else // Take any load, we will use it only to update Alias Analysis OrigLoad = cast<LoadInst>(User->use_back()); OriginalLoads[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->begin(), SI->end())); assert(Params.back()); } if (ArgIndices.size() == 1 && ArgIndices.begin()->empty()) ++NumArgumentsPromoted; else ++NumAggregatesPromoted; } } // Add any function attributes. if (Attributes attrs = PAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); const Type *RetTy = FTy->getReturnType(); // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which // have zero fixed arguments. bool ExtraArgHack = false; if (Params.empty() && FTy->isVarArg()) { ExtraArgHack = true; Params.push_back(Type::getInt32Ty(F->getContext())); } // 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); 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(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); 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<CallGraph>(); // 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 = CallSite::get(F->use_back()); assert(CS.getCalledFunction() == F); Instruction *Call = CS.getInstruction(); const AttrListPtr &CallPAL = CS.getAttributes(); // Add any return attributes. if (Attributes attrs = CallPAL.getRetAttributes()) AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); // 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 (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } else if (ByValArgsToTransform.count(I)) { // Emit a GEP and load for each element of the struct. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); const StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; 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, Idxs+2, (*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[*SI]; if (!SI->empty()) { Ops.reserve(SI->size()); const 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. const 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.begin(), Ops.end(), 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()); Args.push_back(newLoad); AA.copyValue(OrigLoad, Args.back()); } } if (ExtraArgHack) Args.push_back(Constant::getNullValue(Type::getInt32Ty(F->getContext()))); // Push any varargs arguments on the list. for (; AI != CS.arg_end(); ++AI, ++ArgIndex) { Args.push_back(*AI); if (Attributes Attrs = CallPAL.getParamAttributes(ArgIndex)) AttributesVec.push_back(AttributeWithIndex::get(Args.size(), Attrs)); } // Add any function attributes. if (Attributes attrs = CallPAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); Instruction *New; if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), Args.begin(), Args.end(), "", Call); cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); cast<InvokeInst>(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); } else { New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); cast<CallInst>(New)->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); if (cast<CallInst>(Call)->isTailCall()) cast<CallInst>(New)->setTailCall(); } 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, transfering uses of the old arguments over to // the new arguments, also transfering 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. const Type *AgTy = cast<PointerType>(I->getType())->getElementType(); Value *TheAlloca = new AllocaInst(AgTy, 0, "", InsertPt); const StructType *STy = cast<StructType>(AgTy); Value *Idxs[2] = { ConstantInt::get(Type::getInt32Ty(F->getContext()), 0), 0 }; 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, Idxs+2, 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); 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->use_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->use_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->use_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. for (unsigned i = 0, e = ArgIndices.size(); i != e; ++i) ++I2; } // Notify the alias analysis implementation that we inserted a new argument. if (ExtraArgHack) AA.copyValue(Constant::getNullValue(Type::getInt32Ty(F->getContext())), NF->arg_begin()); // 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; }
Function *ABIMethodSignature::createFunction(GenIR &Reader, Module &M) { // Compute the function type LLVMContext &Context = M.getContext(); bool HasIndirectResult = Result.getKind() == ABIArgInfo::Indirect; uint32_t NumExtraArgs = HasIndirectResult ? 1 : 0; const uint32_t NumArgs = Args.size() + NumExtraArgs; int32_t ResultIndex = -1; SmallVector<Type *, 16> ArgumentTypes(NumArgs); SmallVector<AttributeSet, 16> Attrs(NumArgs + 1); if (HasIndirectResult) { ResultIndex = Signature->hasThis() ? 1 : 0; Result.setIndex((uint32_t)ResultIndex); ArgumentTypes[ResultIndex] = Reader.getManagedPointerType(Result.getType()); } else { AttrBuilder RetAttrs; if (Result.getKind() == ABIArgInfo::ZeroExtend) { RetAttrs.addAttribute(Attribute::ZExt); } else if (Result.getKind() == ABIArgInfo::SignExtend) { RetAttrs.addAttribute(Attribute::SExt); } if (RetAttrs.hasAttributes()) { Attrs.push_back( AttributeSet::get(Context, AttributeSet::ReturnIndex, RetAttrs)); } } uint32_t I = 0; for (auto &Arg : Args) { AttrBuilder ArgAttrs; if (ResultIndex >= 0 && I == (uint32_t)ResultIndex) { I++; } if (Arg.getKind() == ABIArgInfo::Indirect) { // TODO: byval attribute support ArgumentTypes[I] = Reader.getManagedPointerType(Arg.getType()); } else { ArgumentTypes[I] = Arg.getType(); if (Arg.getKind() == ABIArgInfo::ZeroExtend) { ArgAttrs.addAttribute(Attribute::ZExt); } else if (Arg.getKind() == ABIArgInfo::SignExtend) { ArgAttrs.addAttribute(Attribute::SExt); } if (ArgAttrs.hasAttributes()) { const unsigned Idx = I + 1; // Add one to accomodate the return attrs. Attrs.push_back(AttributeSet::get(Context, Idx, ArgAttrs)); } } Arg.setIndex(I); I++; } const bool IsVarArg = false; FunctionType *FunctionTy = FunctionType::get(FuncResultType, ArgumentTypes, IsVarArg); Function *F = Function::Create(FunctionTy, Function::ExternalLinkage, M.getModuleIdentifier(), &M); // Use "param" for these initial parameter values. Numbering here // is strictly positional (hence includes implicit parameters). uint32_t N = 0; for (Function::arg_iterator Args = F->arg_begin(); Args != F->arg_end(); Args++) { Args->setName(Twine("param") + Twine(N++)); } CallingConv::ID CC; if (Signature->hasSecretParameter()) { assert((--F->arg_end())->getType()->isIntegerTy()); AttrBuilder SecretParamAttrs; SecretParamAttrs.addAttribute("CLR_SecretParameter"); Attrs.push_back( AttributeSet::get(Context, F->arg_size(), SecretParamAttrs)); CC = CallingConv::CLR_SecretParameter; } else { CC = CallingConv::C; } F->setCallingConv(CC); if (Attrs.size() > 0) { F->setAttributes(AttributeSet::get(Context, Attrs)); } if (Reader.JitContext->Options->DoInsertStatepoints) { F->setGC("coreclr"); } return F; }