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(); } }
/// 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; }
/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC. bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) { bool Changed = false; // Check each function in turn, determining which pointer arguments are not // captured. for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) { Function *F = (*I)->getFunction(); if (F == 0) // External node - skip it; continue; // Definitions with weak linkage may be overridden at linktime with // something that writes memory, so treat them like declarations. if (F->isDeclaration() || F->mayBeOverridden()) continue; for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A) if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr() && !PointerMayBeCaptured(A, true, /*StoreCaptures=*/false)) { A->addAttr(Attribute::NoCapture); ++NumNoCapture; Changed = true; } } return Changed; }
bool LLPE::runOnModule(Module &M) { vector<int> argv = readInputFile(); for (Module::iterator F = M.begin(), F_end = M.end(); F != F_end; ++F) { for (Function::arg_iterator A = F->arg_begin(), A_end = F->arg_end(); A != A_end; ++A) { //Search for variables referencing argv if (A->getName() == "argv") { //Iterate through uses of argv for (Value::use_iterator U = A->use_begin(), U_end = A->use_end(); U != U_end; ++U) { Instruction *User = dyn_cast<Instruction>(*U); StoreInst *SI = dyn_cast<StoreInst>(User); AllocaInst *OrigAlloca = dyn_cast<AllocaInst>(SI->getOperand(1)); for (Value::use_iterator U2 = OrigAlloca->use_begin(), U2_end = OrigAlloca->use_end(); U2 != U2_end; ++U2) { Instruction *User2 = dyn_cast<Instruction>(*U2); for (Value::use_iterator U3 = User2->use_begin(), U3_end = OrigAlloca->use_end(); U3 != U3_end; ++U3) { searchForStoreInstruction(dyn_cast<Instruction>(*U3)->getParent(), argv); } } } } } } return true; }
bool StructuredModuleEditor::signaturesMatch(Function *First, Function *Second) { if (First == NULL || Second == NULL) return false; unsigned FirstNumArgs = First->arg_size(); unsigned SecondNumArgs = Second->arg_size(); // The number of arguments passed to the old function must match the number of // arguments passed to the new function if (FirstNumArgs != SecondNumArgs) return false; // Both functions must abide by the same calling convention if (First->getCallingConv() != Second->getCallingConv()) return false; // Both functions must have the same return type if (First->getReturnType() != Second->getReturnType()) return false; // Checks that the arguments to the old function are of the same type as those of // the new function, and also that they are in the same order for (Function::arg_iterator I = Second->arg_begin(), J = First->arg_begin(), IE = Second->arg_end(); I != IE; ++I, ++J) { if (I->getType() != J->getType()) return false; } return true; }
void ExecutionState::dumpStack(llvm::raw_ostream &out) const { unsigned idx = 0; const KInstruction *target = prevPC; for (ExecutionState::stack_ty::const_reverse_iterator it = stack.rbegin(), ie = stack.rend(); it != ie; ++it) { const StackFrame &sf = *it; Function *f = sf.kf->function; const InstructionInfo &ii = *target->info; out << "\t#" << idx++; std::stringstream AssStream; AssStream << std::setw(8) << std::setfill('0') << ii.assemblyLine; out << AssStream.str(); out << " in " << f->getName().str() << " ("; // Yawn, we could go up and print varargs if we wanted to. unsigned index = 0; for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai) { if (ai!=f->arg_begin()) out << ", "; out << ai->getName().str(); // XXX should go through function ref<Expr> value = sf.locals[sf.kf->getArgRegister(index++)].value; if (value.get() && isa<ConstantExpr>(value)) out << "=" << value; } out << ")"; if (ii.file != "") out << " at " << ii.file << ":" << ii.line; out << "\n"; target = sf.caller; } }
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 *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; }
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; }
void StackTrace::dump(std::ostream &out) const { unsigned idx = 0; for (stack_t::const_iterator it = contents.begin(); it != contents.end(); it++) { Function *f = it->first.first->function; const InstructionInfo &ii = *it->first.second->info; out << "\t#" << idx++ << " " << std::setw(8) << std::setfill('0') << ii.assemblyLine << " in " << f->getName().str() << " ("; unsigned index = 0; for (Function::arg_iterator ai = f->arg_begin(), ae = f->arg_end(); ai != ae; ++ai) { if (ai!=f->arg_begin()) out << ", "; out << ai->getName().str(); // XXX should go through function ref<Expr> value = it->second[index++]; if (isa<ConstantExpr>(value)) out << "=" << value; } out << ")"; if (ii.file != "") out << " at " << ii.file << ":" << ii.line; out << "\n"; } }
/// analyzeFunction - Fill in the current structure with information gleaned /// from the specified function. void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F, const TargetData *TD) { Metrics.analyzeFunction(F, TD); // A function with exactly one return has it removed during the inlining // process (see InlineFunction), so don't count it. // FIXME: This knowledge should really be encoded outside of FunctionInfo. if (Metrics.NumRets==1) --Metrics.NumInsts; ArgumentWeights.reserve(F->arg_size()); DenseMap<Value *, unsigned> PointerArgs; unsigned ArgIdx = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgIdx) { // Count how much code can be eliminated if one of the arguments is // a constant or an alloca. ArgumentWeights.push_back(ArgInfo(countCodeReductionForConstant(Metrics, I), countCodeReductionForAlloca(Metrics, I))); // If the argument is a pointer, also check for pairs of pointers where // knowing a fixed offset between them allows simplification. This pattern // arises mostly due to STL algorithm patterns where pointers are used as // random access iterators. if (!I->getType()->isPointerTy()) continue; PointerArgs[I] = ArgIdx; countCodeReductionForPointerPair(Metrics, PointerArgs, I, ArgIdx); } }
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; }
void MemoryInstrumenter::instrumentPointerParameters(Function *F) { assert(F && !F->isDeclaration()); Instruction *Entry = F->begin()->getFirstNonPHI(); for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (AI->getType()->isPointerTy()) instrumentPointer(AI, NULL, Entry); } }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Global variables shouldn't be of the array type. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { assert(!GI->getType()->isArrayTy()); } // A function parameter or an instruction can be an array, but we don't // instrument such constructs for now. Issue a warning on such cases. for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (AI->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *AI << " is an array\n"; errs().resetColor(); } } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (Ins->getType()->isArrayTy()) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << ":" << *Ins << " is an array\n"; errs().resetColor(); } } } } }
/// cloneFunctionBody - Create a new function based on F and /// insert it into module. Remove first argument. Use STy as /// the return type for new function. Function *SRETPromotion::cloneFunctionBody(Function *F, const StructType *STy) { const FunctionType *FTy = F->getFunctionType(); std::vector<const Type*> Params; // Attributes - Keep track of the parameter attributes for the arguments. 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)); // Skip first argument. Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); ++I; // 0th parameter attribute is reserved for return type. // 1th parameter attribute is for first 1st sret argument. unsigned ParamIndex = 2; while (I != E) { Params.push_back(I->getType()); if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); ++I; ++ParamIndex; } // Add any fn attributes. if (Attributes attrs = PAL.getFnAttributes()) AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); Function *NF = Function::Create(NFTy, F->getLinkage()); NF->takeName(F); NF->copyAttributesFrom(F); NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); F->getParent()->getFunctionList().insert(F, NF); NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); // Replace arguments I = F->arg_begin(); E = F->arg_end(); Function::arg_iterator NI = NF->arg_begin(); ++I; while (I != E) { I->replaceAllUsesWith(NI); NI->takeName(I); ++I; ++NI; } return NF; }
int get_arg_count(const char *name, Function *op) { uint8_t args_present[MAX_ARGS]; int nb_args, i, n; const char *p; for(i = 0;i < MAX_ARGS; i++) args_present[i] = 0; // compute the number of arguments by looking at // the uses of the op parameters for (Function::arg_iterator i = op->arg_begin(), e = op->arg_end(); i != e; ++i) { const char *tmpArgName = i->getName().c_str(); char *argName = (char *) malloc(strlen(tmpArgName + 1)); strcpy(argName, tmpArgName); if (strstart(argName, "__op_param", &p)) { if (i->hasNUsesOrMore(1)) { n = strtoul(p, NULL, 10); if (n > MAX_ARGS) error("too many arguments in %s", name); args_present[n - 1] = 1; } } } for (i = 1; i <= MAX_ARGS; i++) { char *funcName = (char *) malloc(20); sprintf(funcName, "__op_gen_label%d", i); Function *f = ops->getFunction(std::string(funcName)); if (f != NULL) { for (Function::use_iterator j = f->use_begin(), e = f->use_end(); j != e; ++j) { if (Instruction *inst = dyn_cast<Instruction>(*j)) { if (inst->getParent()->getParent() == op) { args_present[i - 1] = 1; } } } } else { std::cout << "symbol not found\n"; } } nb_args = 0; while (nb_args < MAX_ARGS && args_present[nb_args]) nb_args++; for(i = nb_args; i < MAX_ARGS; i++) { if (args_present[i]) error("inconsistent argument numbering in %s", name); } return nb_args; }
bool RegisterStackPools::runOnFunction(Function &F) { TargetData *TD = &getAnalysis<TargetData>(); SmallVector<Value*, 16> Objects; Module &M = *F.getParent(); Function *RegisterStackPoolFunction = M.getFunction("__pool_register_stack"); assert(RegisterStackPoolFunction && "__pool_register_stack function has disappeared!\n"); // Collect alloca instructions for (Function::iterator BB = F.begin(), BBE = F.end(); BB != BBE; ++BB) for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) if (isa<AllocaInst>(I)) Objects.push_back(I); // Collect ByVal arguments if (RegByval) { for (Function::arg_iterator Arg = F.arg_begin(), E = F.arg_end(); Arg != E; ++Arg) { if (Arg->hasByValAttr()) Objects.push_back(Arg); } } IRBuilder<> Builder(F.getContext()); ObjectSizeOffsetEvaluator ObjSizeEval(TD, F.getContext()); // Add the registration calls. for (size_t i = 0, N = Objects.size(); i < N; i++) { Value *V = Objects[i]; if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) { Builder.SetInsertPoint(++BasicBlock::iterator(AI)); } else { Builder.SetInsertPoint(&F.getEntryBlock().front()); } SizeOffsetEvalType SizeOffset = ObjSizeEval.compute(V); assert(ObjSizeEval.bothKnown(SizeOffset)); assert(dyn_cast<ConstantInt>(SizeOffset.second)->isZero()); Value *Size = SizeOffset.first; Size = Builder.CreateIntCast(Size, SizeTy, false, Size->getName() + ".casted"); Value *VoidPtr = Builder.CreatePointerCast(V, VoidPtrTy, V->getName() + ".casted"); Builder.CreateCall2(RegisterStackPoolFunction, VoidPtr, Size); ++StackPoolsRegistered; } return !Objects.empty(); }
void MemoryInstrumenter::checkFeatures(Module &M) { // Check whether any memory allocation function can // potentially be pointed by function pointers. // Also, all intrinsic functions will be called directly, // i.e. not via function pointers. for (Module::iterator F = M.begin(); F != M.end(); ++F) { if (DynAAUtils::IsMalloc(F) || F->isIntrinsic()) { for (Value::use_iterator UI = F->use_begin(); UI != F->use_end(); ++UI) { User *Usr = *UI; assert(isa<CallInst>(Usr) || isa<InvokeInst>(Usr)); CallSite CS(cast<Instruction>(Usr)); for (unsigned i = 0; i < CS.arg_size(); ++i) assert(CS.getArgument(i) != F); } } } // Check whether memory allocation functions are captured. for (Module::iterator F = M.begin(); F != M.end(); ++F) { // 0 is the return, 1 is the first parameter. if (F->isDeclaration() && F->doesNotAlias(0) && !DynAAUtils::IsMalloc(F)) { errs().changeColor(raw_ostream::RED); errs() << F->getName() << "'s return value is marked noalias, "; errs() << "but the function is not treated as malloc.\n"; errs().resetColor(); } } // Sequential types except pointer types shouldn't be used as the type of // an instruction, a function parameter, or a global variable. for (Module::global_iterator GI = M.global_begin(), E = M.global_end(); GI != E; ++GI) { if (isa<SequentialType>(GI->getType())) assert(GI->getType()->isPointerTy()); } for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for (Function::arg_iterator AI = F->arg_begin(); AI != F->arg_end(); ++AI) { if (isa<SequentialType>(AI->getType())) assert(AI->getType()->isPointerTy()); } } for (Module::iterator F = M.begin(); F != M.end(); ++F) { for (Function::iterator BB = F->begin(); BB != F->end(); ++BB) { for (BasicBlock::iterator Ins = BB->begin(); Ins != BB->end(); ++Ins) { if (isa<SequentialType>(Ins->getType())) assert(Ins->getType()->isPointerTy()); } } } // We don't support multi-process programs for now. if (!HookFork) assert(M.getFunction("fork") == NULL); }
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); } }
/* for the vi and lsup, find their corresponding argument*/ Value *FindFunctionArgumentOfInstr(Instruction *I, Function *F) { int notFound = 1; Value *via = 0; Function::arg_iterator FI = F->arg_begin(), FE = F->arg_end(); while (FI != FE && notFound) { if (FI->getName() == I->getName()) { via = &*FI; notFound = 0; } ++FI; } return via; }
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; }
// Convert the given function to use normalized argument/return types. static bool ConvertFunction(Function *Func) { FunctionType *FTy = Func->getFunctionType(); FunctionType *NFTy = NormalizeFunctionType(FTy); if (NFTy == FTy) return false; // No change needed. Function *NewFunc = RecreateFunction(Func, NFTy); // Move the arguments across to the new function. for (Function::arg_iterator Arg = Func->arg_begin(), E = Func->arg_end(), NewArg = NewFunc->arg_begin(); Arg != E; ++Arg, ++NewArg) { NewArg->takeName(Arg); if (Arg->getType() == NewArg->getType()) { Arg->replaceAllUsesWith(NewArg); } else { Instruction *Trunc = new TruncInst( NewArg, Arg->getType(), NewArg->getName() + ".arg_trunc", NewFunc->getEntryBlock().getFirstInsertionPt()); Arg->replaceAllUsesWith(Trunc); } } if (FTy->getReturnType() != NFTy->getReturnType()) { // Fix up return instructions. Instruction::CastOps CastType = Func->getAttributes().hasAttribute(0, Attribute::SExt) ? Instruction::SExt : Instruction::ZExt; for (Function::iterator BB = NewFunc->begin(), E = NewFunc->end(); BB != E; ++BB) { for (BasicBlock::iterator Iter = BB->begin(), E = BB->end(); Iter != E; ) { Instruction *Inst = Iter++; if (ReturnInst *Ret = dyn_cast<ReturnInst>(Inst)) { Value *Ext = CopyDebug( CastInst::Create(CastType, Ret->getReturnValue(), NFTy->getReturnType(), Ret->getReturnValue()->getName() + ".ret_ext", Ret), Ret); CopyDebug(ReturnInst::Create(Ret->getContext(), Ext, Ret), Ret); Ret->eraseFromParent(); } } } } Func->eraseFromParent(); return true; }
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 *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 *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 *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; }
// 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; }
std::vector<Type*> lowerJuliaArrayArgumentsDecl(Function* F) { std::vector<Type*> ArgTypes; Type* ReturnType = F->getReturnType(); for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { Type* argType = I->getType(); if (is_jl_array_type(argType)) { ArgTypes.push_back(PointerType::get(ReturnType, 1)); } else { ArgTypes.push_back(I->getType()); } } return ArgTypes; }