/// 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; }
static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, const TargetData *TD) { X86MachineFunctionInfo Info; uint64_t Size = 0; switch (F->getCallingConv()) { case CallingConv::X86_StdCall: Info.setDecorationStyle(StdCall); break; case CallingConv::X86_FastCall: Info.setDecorationStyle(FastCall); break; default: return Info; } unsigned argNum = 1; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI, ++argNum) { const Type* Ty = AI->getType(); // 'Dereference' type in case of byval parameter attribute if (F->paramHasAttr(argNum, Attribute::ByVal)) Ty = cast<PointerType>(Ty)->getElementType(); // Size should be aligned to DWORD boundary Size += ((TD->getTypePaddedSize(Ty) + 3)/4)*4; } // We're not supporting tooooo huge arguments :) Info.setBytesToPopOnReturn((unsigned int)Size); return Info; }
void Andersen::collectConstraintsForGlobals(Module& M) { // Create a pointer and an object for each global variable for (auto const& globalVal: M.globals()) { NodeIndex gVal = nodeFactory.createValueNode(&globalVal); NodeIndex gObj = nodeFactory.createObjectNode(&globalVal); constraints.emplace_back(AndersConstraint::ADDR_OF, gVal, gObj); } // Functions and function pointers are also considered global for (auto const& f: M) { // If f is an addr-taken function, create a pointer and an object for it if (f.hasAddressTaken()) { NodeIndex fVal = nodeFactory.createValueNode(&f); NodeIndex fObj = nodeFactory.createObjectNode(&f); constraints.emplace_back(AndersConstraint::ADDR_OF, fVal, fObj); } if (f.isDeclaration() || f.isIntrinsic()) continue; // Create return node if (f.getFunctionType()->getReturnType()->isPointerTy()) { nodeFactory.createReturnNode(&f); } // Create vararg node if (f.getFunctionType()->isVarArg()) nodeFactory.createVarargNode(&f); // Add nodes for all formal arguments. for (Function::const_arg_iterator itr = f.arg_begin(), ite = f.arg_end(); itr != ite; ++itr) { if (isa<PointerType>(itr->getType())) nodeFactory.createValueNode(itr); } } // Init globals here since an initializer may refer to a global var/func below it for (auto const& globalVal: M.globals()) { NodeIndex gObj = nodeFactory.getObjectNodeFor(&globalVal); assert(gObj != AndersNodeFactory::InvalidIndex && "Cannot find global object!"); if (globalVal.hasDefinitiveInitializer()) { addGlobalInitializerConstraints(gObj, globalVal.getInitializer()); } else { // If it doesn't have an initializer (i.e. it's defined in another translation unit), it points to the universal set. constraints.emplace_back(AndersConstraint::COPY, gObj, nodeFactory.getUniversalObjNode()); } } }
const Type* getArgumentType(const Function* f, const unsigned arg_index) { assert (f); assert (arg_index < f->arg_size()); Function::const_arg_iterator A = f->arg_begin(); for (unsigned i=0; i<arg_index; ++i) ++A; //is there a better way? :P return A->getType(); }
bool TriCoreCallingConvHook::isRegVali64Type (MachineFunction& _mf) { Function::const_arg_iterator FI; FI = _mf.getFunction()->arg_begin(); std::advance(FI,curArg); outs() << "size: " << FI->getType()->getScalarSizeInBits() << "\n"; return (FI->getType()->getScalarSizeInBits() == 64) ? true : false; }
// Clone OldFunc into NewFunc, transforming the old arguments into references to // VMap values. // void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, SmallVectorImpl<ReturnInst*> &Returns, const char *NameSuffix, ClonedCodeInfo *CodeInfo) { assert(NameSuffix && "NameSuffix cannot be null!"); #ifndef NDEBUG for (Function::const_arg_iterator I = OldFunc->arg_begin(), E = OldFunc->arg_end(); I != E; ++I) assert(VMap.count(I) && "No mapping from source argument specified!"); #endif // Clone any attributes. if (NewFunc->arg_size() == OldFunc->arg_size()) NewFunc->copyAttributesFrom(OldFunc); else { //Some arguments were deleted with the VMap. Copy arguments one by one for (Function::const_arg_iterator I = OldFunc->arg_begin(), E = OldFunc->arg_end(); I != E; ++I) if (Argument* Anew = dyn_cast<Argument>(VMap[I])) Anew->addAttr( OldFunc->getAttributes() .getParamAttributes(I->getArgNo() + 1)); NewFunc->setAttributes(NewFunc->getAttributes() .addAttr(0, OldFunc->getAttributes() .getRetAttributes())); NewFunc->setAttributes(NewFunc->getAttributes() .addAttr(~0, OldFunc->getAttributes() .getFnAttributes())); } // Loop over all of the basic blocks in the function, cloning them as // appropriate. Note that we save BE this way in order to handle cloning of // recursive functions into themselves. // for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end(); BI != BE; ++BI) { const BasicBlock &BB = *BI; // Create a new basic block and copy instructions into it! BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo); VMap[&BB] = CBB; // Add basic block mapping. if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator())) Returns.push_back(RI); } // Loop over all of the instructions in the function, fixing up operand // references as we go. This uses VMap to do all the hard work. for (Function::iterator BB = cast<BasicBlock>(VMap[OldFunc->begin()]), BE = NewFunc->end(); BB != BE; ++BB) // Loop over all instructions, fixing each one as we find it... for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) RemapInstruction(II, VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges); }
void ProgramCFG::setFuncVariable(const Function *F,string func, CFG* cfg, bool initial){ for (Function::const_arg_iterator it = F->arg_begin(), E = F->arg_end();it != E; ++it) { Type *Ty = it->getType(); if(initial){ string varNum = it->getName(); string varName = func+"_"+varNum; if(Ty->isPointerTy()){ Type *ETy = Ty->getPointerElementType(); int ID = cfg->counter_variable++; Variable var(varName, ID, PTR); cfg->variableList.push_back(var); InstParser::setVariable(cfg, NULL, ETy, varName, true); } else{ VarType type; if(Ty->isIntegerTy()) type = INT; else if(Ty->isFloatingPointTy()) type = FP; else errs()<<"0:programCFG.type error\n"; int ID = cfg->counter_variable++; Variable var(varName, ID, type); cfg->variableList.push_back(var); cfg->mainInput.push_back(ID); } } else{ int ID = cfg->counter_variable++; string varNum = it->getName(); string varName = func+"_"+varNum; VarType type; if(Ty->isPointerTy()) type = PTR; else if(Ty->isIntegerTy()) type = INT; else if(Ty->isFloatingPointTy()) type = FP; else errs()<<"1:programCFG.type error\n"; if(!cfg->hasVariable(varName)){ Variable var(varName, ID, type); cfg->variableList.push_back(var); } else errs()<<"1:setFuncVariable error 10086!!\t"<<varName<<"\n"; } } }
bool AArch64CallLowering::LowerFormalArguments( MachineIRBuilder &MIRBuilder, const Function::ArgumentListType &Args, const SmallVectorImpl<unsigned> &VRegs) const { if (!EMIT_IMPLEMENTATION) return false; MachineFunction &MF = MIRBuilder.getMF(); const Function &F = *MF.getFunction(); SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext()); unsigned NumArgs = Args.size(); Function::const_arg_iterator CurOrigArg = Args.begin(); const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); for (unsigned i = 0; i != NumArgs; ++i, ++CurOrigArg) { MVT ValVT = MVT::getVT(CurOrigArg->getType()); CCAssignFn *AssignFn = TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false); bool Res = AssignFn(i, ValVT, ValVT, CCValAssign::Full, ISD::ArgFlagsTy(), CCInfo); assert(!Res && "Call operand has unhandled type"); (void)Res; } assert(ArgLocs.size() == Args.size() && "We have a different number of location and args?!"); for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; assert(VA.isRegLoc() && "Not yet implemented"); // Transform the arguments in physical registers into virtual ones. MIRBuilder.getMBB().addLiveIn(VA.getLocReg()); MIRBuilder.buildInstr(TargetOpcode::COPY, VRegs[i], VA.getLocReg()); switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: break; case CCValAssign::BCvt: // We don't care about bitcast. break; case CCValAssign::AExt: case CCValAssign::SExt: case CCValAssign::ZExt: // Zero/Sign extend the register. assert(0 && "Not yet implemented"); break; } } return true; }
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); } }
/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require /// a suffix on their name indicating the number of words of arguments they /// take. static void AddFastCallStdCallSuffix(SmallVectorImpl<char> &OutName, const Function *F, const DataLayout &TD) { // Calculate arguments size total. unsigned ArgWords = 0; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) { Type *Ty = AI->getType(); // 'Dereference' type in case of byval parameter attribute if (AI->hasByValAttr()) Ty = cast<PointerType>(Ty)->getElementType(); // Size should be aligned to DWORD boundary ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; } raw_svector_ostream(OutName) << '@' << ArgWords; }
void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { const Function *F = MF.getFunction(); const TargetData *TD = TM.getTargetData(); // Emit the data section name. O << "\n"; PIC16Section *fPDataSection = const_cast<PIC16Section *>(getObjFileLowering(). SectionForFrame(CurrentFnSym->getName())); fPDataSection->setColor(getFunctionColor(F)); OutStreamer.SwitchSection(fPDataSection); // Emit function frame label O << PAN::getFrameLabel(CurrentFnSym->getName()) << ":\n"; const Type *RetType = F->getReturnType(); unsigned RetSize = 0; if (RetType->getTypeID() != Type::VoidTyID) RetSize = TD->getTypeAllocSize(RetType); //Emit function return value space // FIXME: Do not emit RetvalLable when retsize is zero. To do this // we will need to avoid printing a global directive for Retval label // in emitExternandGloblas. if(RetSize > 0) O << PAN::getRetvalLabel(CurrentFnSym->getName()) << " RES " << RetSize << "\n"; else O << PAN::getRetvalLabel(CurrentFnSym->getName()) << ": \n"; // Emit variable to hold the space for function arguments unsigned ArgSize = 0; for (Function::const_arg_iterator argi = F->arg_begin(), arge = F->arg_end(); argi != arge ; ++argi) { const Type *Ty = argi->getType(); ArgSize += TD->getTypeAllocSize(Ty); } O << PAN::getArgsLabel(CurrentFnSym->getName()) << " RES " << ArgSize << "\n"; // Emit temporary space int TempSize = PTLI->GetTmpSize(); if (TempSize > 0) O << PAN::getTempdataLabel(CurrentFnSym->getName()) << " RES " << TempSize << '\n'; }
/// Microsoft fastcall and stdcall functions require a suffix on their name /// indicating the number of words of arguments they take. static void addByteCountSuffix(raw_ostream &OS, const Function *F, const DataLayout &DL) { // Calculate arguments size total. unsigned ArgWords = 0; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); AI != AE; ++AI) { Type *Ty = AI->getType(); // 'Dereference' type in case of byval or inalloca parameter attribute. if (AI->hasByValOrInAllocaAttr()) Ty = cast<PointerType>(Ty)->getElementType(); // Size should be aligned to pointer size. unsigned PtrSize = DL.getPointerSize(); ArgWords += RoundUpToAlignment(DL.getTypeAllocSize(Ty), PtrSize); } OS << '@' << ArgWords; }
void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { const Function *F = MF.getFunction(); std::string FuncName = Mang->getValueName(F); const TargetData *TD = TM.getTargetData(); // Emit the data section name. O << "\n"; const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str(); const Section *fPDataSection = TAI->getNamedSection(SectionName, SectionFlags::Writeable); SwitchToSection(fPDataSection); // Emit function frame label O << PAN::getFrameLabel(CurrentFnName) << ":\n"; const Type *RetType = F->getReturnType(); unsigned RetSize = 0; if (RetType->getTypeID() != Type::VoidTyID) RetSize = TD->getTypeAllocSize(RetType); //Emit function return value space // FIXME: Do not emit RetvalLable when retsize is zero. To do this // we will need to avoid printing a global directive for Retval label // in emitExternandGloblas. if(RetSize > 0) O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n"; else O << PAN::getRetvalLabel(CurrentFnName) << ": \n"; // Emit variable to hold the space for function arguments unsigned ArgSize = 0; for (Function::const_arg_iterator argi = F->arg_begin(), arge = F->arg_end(); argi != arge ; ++argi) { const Type *Ty = argi->getType(); ArgSize += TD->getTypeAllocSize(Ty); } O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n"; // Emit temporary space int TempSize = PTLI->GetTmpSize(); if (TempSize > 0 ) O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize <<"\n"; }
std::vector<Type*> lowerJuliaArrayArguments(Function *OldFunc) { Module* M = OldFunc->getParent(); LLVMContext &context = M->getContext(); NamedMDNode* JuliaArgs = M->getOrInsertNamedMetadata("julia.args"); MDNode *node = JuliaArgs->getOperand(0); int operand = 0; std::vector<Type*> ArgTypes; for (Function::const_arg_iterator I = OldFunc->arg_begin(), E = OldFunc->arg_end(); I != E; ++I) { Type* argType = I->getType(); if (is_jl_array_type(argType)) { // Gets the type from custom metadata Value *value = node->getOperand(operand); if (MDString* mdstring = dyn_cast<MDString>(value)) { if (Type* type = extractType(context, mdstring->getString())) { ArgTypes.push_back(type); } else { errs() << "Could not extract type: "; mdstring->print(errs()); errs() << "\n"; exit(1); } } else { errs() << "Could not extract type: "; value->print(errs()); errs() << "\n"; exit(1); } } else { ArgTypes.push_back(I->getType()); } operand++; } return ArgTypes; }
/// Identify lowered values that originated from f128 arguments and record /// this. void MipsCCState::PreAnalyzeFormalArgumentsForF128( const SmallVectorImpl<ISD::InputArg> &Ins) { const MachineFunction &MF = getMachineFunction(); for (unsigned i = 0; i < Ins.size(); ++i) { Function::const_arg_iterator FuncArg = MF.getFunction()->arg_begin(); // SRet arguments cannot originate from f128 or {f128} returns so we just // push false. We have to handle this specially since SRet arguments // aren't mapped to an original argument. if (Ins[i].Flags.isSRet()) { OriginalArgWasF128.push_back(false); OriginalArgWasFloat.push_back(false); continue; } assert(Ins[i].getOrigArgIndex() < MF.getFunction()->arg_size()); std::advance(FuncArg, Ins[i].getOrigArgIndex()); OriginalArgWasF128.push_back( originalTypeIsF128(FuncArg->getType(), nullptr)); OriginalArgWasFloat.push_back(FuncArg->getType()->isFloatingPointTy()); } }
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; }
static bool ffiInvoke(RawFunc Fn, Function *F, ArrayRef<GenericValue> ArgVals, const DataLayout &TD, GenericValue &Result) { ffi_cif cif; FunctionType *FTy = F->getFunctionType(); const unsigned NumArgs = F->arg_size(); // TODO: We don't have type information about the remaining arguments, because // this information is never passed into ExecutionEngine::runFunction(). if (ArgVals.size() > NumArgs && F->isVarArg()) { report_fatal_error("Calling external var arg function '" + F->getName() + "' is not supported by the Interpreter."); } unsigned ArgBytes = 0; std::vector<ffi_type*> args(NumArgs); for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E; ++A) { const unsigned ArgNo = A->getArgNo(); Type *ArgTy = FTy->getParamType(ArgNo); args[ArgNo] = ffiTypeFor(ArgTy); ArgBytes += TD.getTypeStoreSize(ArgTy); } SmallVector<uint8_t, 128> ArgData; ArgData.resize(ArgBytes); uint8_t *ArgDataPtr = ArgData.data(); SmallVector<void*, 16> values(NumArgs); for (Function::const_arg_iterator A = F->arg_begin(), E = F->arg_end(); A != E; ++A) { const unsigned ArgNo = A->getArgNo(); Type *ArgTy = FTy->getParamType(ArgNo); values[ArgNo] = ffiValueFor(ArgTy, ArgVals[ArgNo], ArgDataPtr); ArgDataPtr += TD.getTypeStoreSize(ArgTy); } Type *RetTy = FTy->getReturnType(); ffi_type *rtype = ffiTypeFor(RetTy); if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NumArgs, rtype, args.data()) == FFI_OK) { SmallVector<uint8_t, 128> ret; if (RetTy->getTypeID() != Type::VoidTyID) ret.resize(TD.getTypeStoreSize(RetTy)); ffi_call(&cif, Fn, ret.data(), values.data()); switch (RetTy->getTypeID()) { case Type::IntegerTyID: switch (cast<IntegerType>(RetTy)->getBitWidth()) { case 8: Result.IntVal = APInt(8 , *(int8_t *) ret.data()); break; case 16: Result.IntVal = APInt(16, *(int16_t*) ret.data()); break; case 32: Result.IntVal = APInt(32, *(int32_t*) ret.data()); break; case 64: Result.IntVal = APInt(64, *(int64_t*) ret.data()); break; } break; case Type::FloatTyID: Result.FloatVal = *(float *) ret.data(); break; case Type::DoubleTyID: Result.DoubleVal = *(double*) ret.data(); break; case Type::PointerTyID: Result.PointerVal = *(void **) ret.data(); break; default: break; } return true; } return false; }
/* ************************************************************************** */ bool RangedAddressSanitizer::doInitialization(Module &M) { // Link FastAddressSanitizer functions into the target module LLVMContext & context = M.getContext(); const char * fasanPath = getenv("FASANMODULE"); if (! fasanPath) { return false; } std::stringstream ss; ss << fasanPath; SMDiagnostic diag; Module * fasanModule = ParseIRFile(ss.str(), diag, context); if (!fasanModule) { abort(); } #if 0 /* using LLVM linking facilities */ Linker linker(&M); std::string linkErr; if (linker.linkInModule(fasanModule, Linker::DestroySource, &linkErr)) { errs() << "[FASAN] Error while linking runtime module: " << fasanModule << "(!!)\n"; abort(); } #else PointerType * voidPtrTy = PointerType::getInt8PtrTy(context, 0); IntegerType * boolTy = IntegerType::get(context, 1); Type * voidTy = Type::getVoidTy(context); FunctionType * touchFunType = FunctionType::get(voidTy, ArrayRef<Type*>(voidPtrTy), false); FunctionType * verifyFunType = FunctionType::get(boolTy, ArrayRef<Type*>(voidPtrTy), false); ValueToValueMapTy reMap; reMap[fasanModule->getFunction("__fasan_touch")] = M.getOrInsertFunction("__fasan_touch", touchFunType); reMap[fasanModule->getFunction("__fasan_verify")] = M.getOrInsertFunction("__fasan_verify", verifyFunType); // migrate check function { std::string errMsg; Function * checkFunc = fasanModule->getFunction("__fasan_check"); if (!checkFunc) { abort(); } #if 1 FunctionType * checkFuncType = checkFunc->getFunctionType(); Function * targetFunc = dyn_cast<Function>(M.getOrInsertFunction("__fasan_check", checkFuncType)); assert(targetFunc && "function cast to const by getOrInsertFunc..?"); // Loop over the arguments, copying the names of the mapped arguments over... Function::arg_iterator DestI = targetFunc->arg_begin(); for (Function::const_arg_iterator I = checkFunc->arg_begin(), E = checkFunc->arg_end(); I != E; ++I) if (reMap.count(I) == 0) { // Is this argument preserved? DestI->setName(I->getName()); // Copy the name over... reMap[I] = DestI++; // Add mapping to VMap } SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. CloneFunctionInto(targetFunc, checkFunc, reMap, false, Returns, "", nullptr); targetFunc->addAttribute(0,Attribute::SanitizeAddress); #else Function * clonedCheckFunc = CloneFunction(checkFunc, reMap, false, 0); assert(!M.getFunction("__fasan_check") && "already exists in module"); M.getFunctionList().push_back(clonedCheckFunc); ReuseFn_ = clonedCheckFunc; clonedCheckFunc->setLinkage(GlobalValue::InternalLinkage); // avoid conflicts during linking // re-map fake use to local copy for (auto & BB : *clonedCheckFunc) { for (auto & Inst : BB) { RemapInstruction(&Inst, reMap, RF_IgnoreMissingEntries, 0, 0); } } #endif #endif } delete fasanModule; return true; }
/// NaClValueEnumerator - Enumerate module-level information. NaClValueEnumerator::NaClValueEnumerator(const Module *M) { // Create map for counting frequency of types, and set field // TypeCountMap accordingly. Note: Pointer field TypeCountMap is // used to deal with the fact that types are added through various // method calls in this routine. Rather than pass it as an argument, // we use a field. The field is a pointer so that the memory // footprint of count_map can be garbage collected when this // constructor completes. TypeCountMapType count_map; TypeCountMap = &count_map; IntPtrType = IntegerType::get(M->getContext(), PNaClIntPtrTypeBitSize); // Enumerate the functions. Note: We do this before global // variables, so that global variable initializations can refer to // the functions without a forward reference. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { EnumerateValue(I); } // Enumerate the global variables. FirstGlobalVarID = Values.size(); for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) EnumerateValue(I); NumGlobalVarIDs = Values.size() - FirstGlobalVarID; // Enumerate the aliases. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I); // Remember what is the cutoff between globalvalue's and other constants. unsigned FirstConstant = Values.size(); // Skip global variable initializers since they are handled within // WriteGlobalVars of file NaClBitcodeWriter.cpp. // Enumerate the aliasees. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I->getAliasee()); // Insert constants that are named at module level into the slot // pool so that the module symbol table can refer to them... EnumerateValueSymbolTable(M->getValueSymbolTable()); // Enumerate types used by function bodies and argument lists. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) EnumerateType(I->getType()); for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ // Don't generate types for elided pointer casts! if (IsElidedCast(I)) continue; if (const SwitchInst *SI = dyn_cast<SwitchInst>(I)) { // Handle switch instruction specially, so that we don't // write out unnecessary vector/array types used to model case // selectors. EnumerateOperandType(SI->getCondition()); } else { for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) { EnumerateOperandType(*OI); } } EnumerateType(I->getType()); } } // Optimized type indicies to put "common" expected types in with small // indices. OptimizeTypes(M); TypeCountMap = NULL; // Optimize constant ordering. OptimizeConstants(FirstConstant, Values.size()); }
// InlineFunction - This function inlines the called function into the basic // block of the caller. This returns false if it is not possible to inline this // call. The program is still in a well defined state if this occurs though. // // Note that this only does one level of inlining. For example, if the // instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now // exists in the instruction stream. Similiarly this will inline a recursive // function by one level. // bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD) { Instruction *TheCall = CS.getInstruction(); assert(TheCall->getParent() && TheCall->getParent()->getParent() && "Instruction not in function!"); const Function *CalledFunc = CS.getCalledFunction(); if (CalledFunc == 0 || // Can't inline external function or indirect CalledFunc->isDeclaration() || // call, or call to a vararg function! CalledFunc->getFunctionType()->isVarArg()) return false; // If the call to the callee is not a tail call, we must clear the 'tail' // flags on any calls that we inline. bool MustClearTailCallFlags = !(isa<CallInst>(TheCall) && cast<CallInst>(TheCall)->isTailCall()); // If the call to the callee cannot throw, set the 'nounwind' flag on any // calls that we inline. bool MarkNoUnwind = CS.doesNotThrow(); BasicBlock *OrigBB = TheCall->getParent(); Function *Caller = OrigBB->getParent(); // GC poses two hazards to inlining, which only occur when the callee has GC: // 1. If the caller has no GC, then the callee's GC must be propagated to the // caller. // 2. If the caller has a differing GC, it is invalid to inline. if (CalledFunc->hasGC()) { if (!Caller->hasGC()) Caller->setGC(CalledFunc->getGC()); else if (CalledFunc->getGC() != Caller->getGC()) return false; } // Get an iterator to the last basic block in the function, which will have // the new function inlined after it. // Function::iterator LastBlock = &Caller->back(); // Make sure to capture all of the return instructions from the cloned // function. std::vector<ReturnInst*> Returns; ClonedCodeInfo InlinedFunctionInfo; Function::iterator FirstNewBlock; { // Scope to destroy ValueMap after cloning. DenseMap<const Value*, Value*> ValueMap; assert(CalledFunc->arg_size() == CS.arg_size() && "No varargs calls can be inlined!"); // Calculate the vector of arguments to pass into the function cloner, which // matches up the formal to the actual argument values. CallSite::arg_iterator AI = CS.arg_begin(); unsigned ArgNo = 0; for (Function::const_arg_iterator I = CalledFunc->arg_begin(), E = CalledFunc->arg_end(); I != E; ++I, ++AI, ++ArgNo) { Value *ActualArg = *AI; // When byval arguments actually inlined, we need to make the copy implied // by them explicit. However, we don't do this if the callee is readonly // or readnone, because the copy would be unneeded: the callee doesn't // modify the struct. if (CalledFunc->paramHasAttr(ArgNo+1, Attribute::ByVal) && !CalledFunc->onlyReadsMemory()) { const Type *AggTy = cast<PointerType>(I->getType())->getElementType(); const Type *VoidPtrTy = PointerType::getUnqual(Type::Int8Ty); // Create the alloca. If we have TargetData, use nice alignment. unsigned Align = 1; if (TD) Align = TD->getPrefTypeAlignment(AggTy); Value *NewAlloca = new AllocaInst(AggTy, 0, Align, I->getName(), Caller->begin()->begin()); // Emit a memcpy. const Type *Tys[] = { Type::Int64Ty }; Function *MemCpyFn = Intrinsic::getDeclaration(Caller->getParent(), Intrinsic::memcpy, Tys, 1); Value *DestCast = new BitCastInst(NewAlloca, VoidPtrTy, "tmp", TheCall); Value *SrcCast = new BitCastInst(*AI, VoidPtrTy, "tmp", TheCall); Value *Size; if (TD == 0) Size = ConstantExpr::getSizeOf(AggTy); else Size = ConstantInt::get(Type::Int64Ty, TD->getTypeStoreSize(AggTy)); // Always generate a memcpy of alignment 1 here because we don't know // the alignment of the src pointer. Other optimizations can infer // better alignment. Value *CallArgs[] = { DestCast, SrcCast, Size, ConstantInt::get(Type::Int32Ty, 1) }; CallInst *TheMemCpy = CallInst::Create(MemCpyFn, CallArgs, CallArgs+4, "", TheCall); // If we have a call graph, update it. if (CG) { CallGraphNode *MemCpyCGN = CG->getOrInsertFunction(MemCpyFn); CallGraphNode *CallerNode = (*CG)[Caller]; CallerNode->addCalledFunction(TheMemCpy, MemCpyCGN); } // Uses of the argument in the function should use our new alloca // instead. ActualArg = NewAlloca; } ValueMap[I] = ActualArg; } // We want the inliner to prune the code as it copies. We would LOVE to // have no dead or constant instructions leftover after inlining occurs // (which can happen, e.g., because an argument was constant), but we'll be // happy with whatever the cloner can do. CloneAndPruneFunctionInto(Caller, CalledFunc, ValueMap, Returns, ".i", &InlinedFunctionInfo, TD); // Remember the first block that is newly cloned over. FirstNewBlock = LastBlock; ++FirstNewBlock; // Update the callgraph if requested. if (CG) UpdateCallGraphAfterInlining(CS, FirstNewBlock, ValueMap, *CG); } // If there are any alloca instructions in the block that used to be the entry // block for the callee, move them to the entry block of the caller. First // calculate which instruction they should be inserted before. We insert the // instructions at the end of the current alloca list. // { BasicBlock::iterator InsertPoint = Caller->begin()->begin(); for (BasicBlock::iterator I = FirstNewBlock->begin(), E = FirstNewBlock->end(); I != E; ) if (AllocaInst *AI = dyn_cast<AllocaInst>(I++)) { // If the alloca is now dead, remove it. This often occurs due to code // specialization. if (AI->use_empty()) { AI->eraseFromParent(); continue; } if (isa<Constant>(AI->getArraySize())) { // Scan for the block of allocas that we can move over, and move them // all at once. while (isa<AllocaInst>(I) && isa<Constant>(cast<AllocaInst>(I)->getArraySize())) ++I; // Transfer all of the allocas over in a block. Using splice means // that the instructions aren't removed from the symbol table, then // reinserted. Caller->getEntryBlock().getInstList().splice( InsertPoint, FirstNewBlock->getInstList(), AI, I); } } } // If the inlined code contained dynamic alloca instructions, wrap the inlined // code with llvm.stacksave/llvm.stackrestore intrinsics. if (InlinedFunctionInfo.ContainsDynamicAllocas) { Module *M = Caller->getParent(); // Get the two intrinsics we care about. Constant *StackSave, *StackRestore; StackSave = Intrinsic::getDeclaration(M, Intrinsic::stacksave); StackRestore = Intrinsic::getDeclaration(M, Intrinsic::stackrestore); // If we are preserving the callgraph, add edges to the stacksave/restore // functions for the calls we insert. CallGraphNode *StackSaveCGN = 0, *StackRestoreCGN = 0, *CallerNode = 0; if (CG) { // We know that StackSave/StackRestore are Function*'s, because they are // intrinsics which must have the right types. StackSaveCGN = CG->getOrInsertFunction(cast<Function>(StackSave)); StackRestoreCGN = CG->getOrInsertFunction(cast<Function>(StackRestore)); CallerNode = (*CG)[Caller]; } // Insert the llvm.stacksave. CallInst *SavedPtr = CallInst::Create(StackSave, "savedstack", FirstNewBlock->begin()); if (CG) CallerNode->addCalledFunction(SavedPtr, StackSaveCGN); // Insert a call to llvm.stackrestore before any return instructions in the // inlined function. for (unsigned i = 0, e = Returns.size(); i != e; ++i) { CallInst *CI = CallInst::Create(StackRestore, SavedPtr, "", Returns[i]); if (CG) CallerNode->addCalledFunction(CI, StackRestoreCGN); } // Count the number of StackRestore calls we insert. unsigned NumStackRestores = Returns.size(); // If we are inlining an invoke instruction, insert restores before each // unwind. These unwinds will be rewritten into branches later. if (InlinedFunctionInfo.ContainsUnwinds && isa<InvokeInst>(TheCall)) { for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->getTerminator())) { CallInst::Create(StackRestore, SavedPtr, "", UI); ++NumStackRestores; } } } // If we are inlining tail call instruction through a call site that isn't // marked 'tail', we must remove the tail marker for any calls in the inlined // code. Also, calls inlined through a 'nounwind' call site should be marked // 'nounwind'. if (InlinedFunctionInfo.ContainsCalls && (MustClearTailCallFlags || MarkNoUnwind)) { for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) if (CallInst *CI = dyn_cast<CallInst>(I)) { if (MustClearTailCallFlags) CI->setTailCall(false); if (MarkNoUnwind) CI->setDoesNotThrow(); } } // If we are inlining through a 'nounwind' call site then any inlined 'unwind' // instructions are unreachable. if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind) for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB) { TerminatorInst *Term = BB->getTerminator(); if (isa<UnwindInst>(Term)) { new UnreachableInst(Term); BB->getInstList().erase(Term); } } // If we are inlining for an invoke instruction, we must make sure to rewrite // any inlined 'unwind' instructions into branches to the invoke exception // destination, and call instructions into invoke instructions. if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) HandleInlinedInvoke(II, FirstNewBlock, InlinedFunctionInfo); // If we cloned in _exactly one_ basic block, and if that block ends in a // return instruction, we splice the body of the inlined callee directly into // the calling basic block. if (Returns.size() == 1 && std::distance(FirstNewBlock, Caller->end()) == 1) { // Move all of the instructions right before the call. OrigBB->getInstList().splice(TheCall, FirstNewBlock->getInstList(), FirstNewBlock->begin(), FirstNewBlock->end()); // Remove the cloned basic block. Caller->getBasicBlockList().pop_back(); // If the call site was an invoke instruction, add a branch to the normal // destination. if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) BranchInst::Create(II->getNormalDest(), TheCall); // If the return instruction returned a value, replace uses of the call with // uses of the returned value. if (!TheCall->use_empty()) { ReturnInst *R = Returns[0]; TheCall->replaceAllUsesWith(R->getReturnValue()); } // Since we are now done with the Call/Invoke, we can delete it. TheCall->eraseFromParent(); // Since we are now done with the return instruction, delete it also. Returns[0]->eraseFromParent(); // We are now done with the inlining. return true; } // Otherwise, we have the normal case, of more than one block to inline or // multiple return sites. // We want to clone the entire callee function into the hole between the // "starter" and "ender" blocks. How we accomplish this depends on whether // this is an invoke instruction or a call instruction. BasicBlock *AfterCallBB; if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) { // Add an unconditional branch to make this look like the CallInst case... BranchInst *NewBr = BranchInst::Create(II->getNormalDest(), TheCall); // Split the basic block. This guarantees that no PHI nodes will have to be // updated due to new incoming edges, and make the invoke case more // symmetric to the call case. AfterCallBB = OrigBB->splitBasicBlock(NewBr, CalledFunc->getName()+".exit"); } else { // It's a call // If this is a call instruction, we need to split the basic block that // the call lives in. // AfterCallBB = OrigBB->splitBasicBlock(TheCall, CalledFunc->getName()+".exit"); } // Change the branch that used to go to AfterCallBB to branch to the first // basic block of the inlined function. // TerminatorInst *Br = OrigBB->getTerminator(); assert(Br && Br->getOpcode() == Instruction::Br && "splitBasicBlock broken!"); Br->setOperand(0, FirstNewBlock); // Now that the function is correct, make it a little bit nicer. In // particular, move the basic blocks inserted from the end of the function // into the space made by splitting the source basic block. Caller->getBasicBlockList().splice(AfterCallBB, Caller->getBasicBlockList(), FirstNewBlock, Caller->end()); // Handle all of the return instructions that we just cloned in, and eliminate // any users of the original call/invoke instruction. const Type *RTy = CalledFunc->getReturnType(); if (Returns.size() > 1) { // The PHI node should go at the front of the new basic block to merge all // possible incoming values. PHINode *PHI = 0; if (!TheCall->use_empty()) { PHI = PHINode::Create(RTy, TheCall->getName(), AfterCallBB->begin()); // Anything that used the result of the function call should now use the // PHI node as their operand. TheCall->replaceAllUsesWith(PHI); } // Loop over all of the return instructions adding entries to the PHI node // as appropriate. if (PHI) { for (unsigned i = 0, e = Returns.size(); i != e; ++i) { ReturnInst *RI = Returns[i]; assert(RI->getReturnValue()->getType() == PHI->getType() && "Ret value not consistent in function!"); PHI->addIncoming(RI->getReturnValue(), RI->getParent()); } } // Add a branch to the merge points and remove return instructions. for (unsigned i = 0, e = Returns.size(); i != e; ++i) { ReturnInst *RI = Returns[i]; BranchInst::Create(AfterCallBB, RI); RI->eraseFromParent(); } } else if (!Returns.empty()) { // Otherwise, if there is exactly one return value, just replace anything // using the return value of the call with the computed value. if (!TheCall->use_empty()) TheCall->replaceAllUsesWith(Returns[0]->getReturnValue()); // Splice the code from the return block into the block that it will return // to, which contains the code that was after the call. BasicBlock *ReturnBB = Returns[0]->getParent(); AfterCallBB->getInstList().splice(AfterCallBB->begin(), ReturnBB->getInstList()); // Update PHI nodes that use the ReturnBB to use the AfterCallBB. ReturnBB->replaceAllUsesWith(AfterCallBB); // Delete the return instruction now and empty ReturnBB now. Returns[0]->eraseFromParent(); ReturnBB->eraseFromParent(); } else if (!TheCall->use_empty()) { // No returns, but something is using the return value of the call. Just // nuke the result. TheCall->replaceAllUsesWith(UndefValue::get(TheCall->getType())); } // Since we are now done with the Call/Invoke, we can delete it. TheCall->eraseFromParent(); // We should always be able to fold the entry block of the function into the // single predecessor of the block... assert(cast<BranchInst>(Br)->isUnconditional() && "splitBasicBlock broken!"); BasicBlock *CalleeEntry = cast<BranchInst>(Br)->getSuccessor(0); // Splice the code entry block into calling block, right before the // unconditional branch. OrigBB->getInstList().splice(Br, CalleeEntry->getInstList()); CalleeEntry->replaceAllUsesWith(OrigBB); // Update PHI nodes // Remove the unconditional branch. OrigBB->getInstList().erase(Br); // Now we can remove the CalleeEntry block, which is now empty. Caller->getBasicBlockList().erase(CalleeEntry); return true; }
Module *llvm::CloneModule(const Module *M, ValueToValueMapTy &VMap) { // First off, we need to create the new module. Module *New = new 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->getType()->getElementType(), 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->getType()->getElementType()), I->getLinkage(), I->getName(), New); 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) { auto *PTy = cast<PointerType>(I->getType()); auto *GA = GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), I->getLinkage(), I->getName(), New); 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 (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 (!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); } } // And aliases for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) { GlobalAlias *GA = cast<GlobalAlias>(VMap[I]); if (const Constant *C = I->getAliasee()) GA->setAliasee(cast<GlobalObject>(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(MapValue(NMD.getOperand(i), VMap)); } return New; }
/// /// Method: visitIntrinsic() /// /// Description: /// Generate correct DSNodes for calls to LLVM intrinsic functions. /// /// Inputs: /// CS - The CallSite representing the call or invoke to the intrinsic. /// F - A pointer to the function called by the call site. /// /// Return value: /// true - This intrinsic is properly handled by this method. /// false - This intrinsic is not recognized by DSA. /// bool GraphBuilder::visitIntrinsic(CallSite CS, Function *F) { ++NumIntrinsicCall; // // If this is a debug intrinsic, then don't do any special processing. // if (isa<DbgInfoIntrinsic>(CS.getInstruction())) return true; switch (F->getIntrinsicID()) { case Intrinsic::vastart: { visitVAStartInst(CS); return true; } case Intrinsic::vacopy: { // Simply merge the two arguments to va_copy. // This results in loss of precision on the temporaries used to manipulate // the va_list, and so isn't a big deal. In theory we would build a // separate graph for this (like the one created in visitVAStartNode) // and only merge the node containing the variable arguments themselves. DSNodeHandle destNH = getValueDest(CS.getArgument(0)); DSNodeHandle srcNH = getValueDest(CS.getArgument(1)); destNH.mergeWith(srcNH); return true; } case Intrinsic::stacksave: { DSNode * Node = createNode(); Node->setAllocaMarker()->setIncompleteMarker()->setUnknownMarker(); Node->foldNodeCompletely(); setDestTo (*(CS.getInstruction()), Node); return true; } case Intrinsic::stackrestore: getValueDest(CS.getInstruction()).getNode()->setAllocaMarker() ->setIncompleteMarker() ->setUnknownMarker() ->foldNodeCompletely(); return true; case Intrinsic::vaend: case Intrinsic::memcpy: case Intrinsic::memmove: { // Merge the first & second arguments, and mark the memory read and // modified. DSNodeHandle RetNH = getValueDest(*CS.arg_begin()); RetNH.mergeWith(getValueDest(*(CS.arg_begin()+1))); if (DSNode *N = RetNH.getNode()) N->setModifiedMarker()->setReadMarker(); return true; } case Intrinsic::memset: // Mark the memory modified. if (DSNode *N = getValueDest(*CS.arg_begin()).getNode()) N->setModifiedMarker(); return true; case Intrinsic::eh_exception: { DSNode * Node = createNode(); Node->setIncompleteMarker(); Node->foldNodeCompletely(); setDestTo (*(CS.getInstruction()), Node); return true; } case Intrinsic::eh_selector: { for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I) { if (isa<PointerType>((*I)->getType())) { DSNodeHandle Ptr = getValueDest(*I); if(Ptr.getNode()) { Ptr.getNode()->setReadMarker(); Ptr.getNode()->setIncompleteMarker(); } } } return true; } case Intrinsic::eh_typeid_for: { DSNodeHandle Ptr = getValueDest(*CS.arg_begin()); Ptr.getNode()->setReadMarker(); Ptr.getNode()->setIncompleteMarker(); return true; } case Intrinsic::prefetch: return true; case Intrinsic::objectsize: return true; // // The return address/frame address aliases with the stack, // is type-unknown, and should // have the unknown flag set since we don't know where it goes. // case Intrinsic::returnaddress: case Intrinsic::frameaddress: { DSNode * Node = createNode(); Node->setAllocaMarker()->setIncompleteMarker()->setUnknownMarker(); Node->foldNodeCompletely(); setDestTo (*(CS.getInstruction()), Node); return true; } // Process lifetime intrinsics case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: case Intrinsic::invariant_start: case Intrinsic::invariant_end: return true; default: { //ignore pointer free intrinsics if (!isa<PointerType>(F->getReturnType())) { bool hasPtr = false; for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E && !hasPtr; ++I) if (isa<PointerType>(I->getType())) hasPtr = true; if (!hasPtr) return true; } DEBUG(errs() << "[dsa:local] Unhandled intrinsic: " << F->getName() << "\n"); assert(0 && "Unhandled intrinsic"); return false; } } }
/// ValueEnumerator - Enumerate module-level information. ValueEnumerator::ValueEnumerator(const Module *M) { // Enumerate the global variables. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) EnumerateValue(I); // Enumerate the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { EnumerateValue(I); EnumerateAttributes(cast<Function>(I)->getAttributes()); } // Enumerate the aliases. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I); // Remember what is the cutoff between globalvalue's and other constants. unsigned FirstConstant = Values.size(); // Enumerate the global variable initializers. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) EnumerateValue(I->getInitializer()); // Enumerate the aliasees. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I->getAliasee()); // Insert constants and metadata that are named at module level into the slot // pool so that the module symbol table can refer to them... EnumerateValueSymbolTable(M->getValueSymbolTable()); EnumerateNamedMetadata(M); SmallVector<std::pair<unsigned, MDNode*>, 8> MDs; // Enumerate types used by function bodies and argument lists. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) EnumerateType(I->getType()); for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) { if (MDNode *MD = dyn_cast<MDNode>(*OI)) if (MD->isFunctionLocal() && MD->getFunction()) // These will get enumerated during function-incorporation. continue; EnumerateOperandType(*OI); } EnumerateType(I->getType()); if (const CallInst *CI = dyn_cast<CallInst>(I)) EnumerateAttributes(CI->getAttributes()); else if (const InvokeInst *II = dyn_cast<InvokeInst>(I)) EnumerateAttributes(II->getAttributes()); // Enumerate metadata attached with this instruction. MDs.clear(); I->getAllMetadataOtherThanDebugLoc(MDs); for (unsigned i = 0, e = MDs.size(); i != e; ++i) EnumerateMetadata(MDs[i].second); if (!I->getDebugLoc().isUnknown()) { MDNode *Scope, *IA; I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); if (Scope) EnumerateMetadata(Scope); if (IA) EnumerateMetadata(IA); } } } // Optimize constant ordering. OptimizeConstants(FirstConstant, Values.size()); }
/// NaClValueEnumerator - Enumerate module-level information. NaClValueEnumerator::NaClValueEnumerator(const Module *M) { // Create map for counting frequency of types, and set field // TypeCountMap accordingly. Note: Pointer field TypeCountMap is // used to deal with the fact that types are added through various // method calls in this routine. Rather than pass it as an argument, // we use a field. The field is a pointer so that the memory // footprint of count_map can be garbage collected when this // constructor completes. TypeCountMapType count_map; TypeCountMap = &count_map; // Enumerate the global variables. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) EnumerateValue(I); // Enumerate the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { EnumerateValue(I); EnumerateAttributes(cast<Function>(I)->getAttributes()); } // Enumerate the aliases. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I); // Remember what is the cutoff between globalvalue's and other constants. unsigned FirstConstant = Values.size(); // Enumerate the global variable initializers. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) EnumerateValue(I->getInitializer()); // Enumerate the aliasees. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I->getAliasee()); // Insert constants and metadata that are named at module level into the slot // pool so that the module symbol table can refer to them... EnumerateValueSymbolTable(M->getValueSymbolTable()); EnumerateNamedMetadata(M); SmallVector<std::pair<unsigned, MDNode*>, 8> MDs; // Enumerate types used by function bodies and argument lists. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) EnumerateType(I->getType()); for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) { if (MDNode *MD = dyn_cast<MDNode>(*OI)) if (MD->isFunctionLocal() && MD->getFunction()) // These will get enumerated during function-incorporation. continue; EnumerateOperandType(*OI); } EnumerateType(I->getType()); if (const CallInst *CI = dyn_cast<CallInst>(I)) EnumerateAttributes(CI->getAttributes()); else if (const InvokeInst *II = dyn_cast<InvokeInst>(I)) EnumerateAttributes(II->getAttributes()); // Enumerate metadata attached with this instruction. MDs.clear(); I->getAllMetadataOtherThanDebugLoc(MDs); for (unsigned i = 0, e = MDs.size(); i != e; ++i) EnumerateMetadata(MDs[i].second); if (!I->getDebugLoc().isUnknown()) { MDNode *Scope, *IA; I->getDebugLoc().getScopeAndInlinedAt(Scope, IA, I->getContext()); if (Scope) EnumerateMetadata(Scope); if (IA) EnumerateMetadata(IA); } } } // Optimized type indicies to put "common" expected types in with small // indices. OptimizeTypes(M); TypeCountMap = NULL; // Optimize constant ordering. OptimizeConstants(FirstConstant, Values.size()); }
void LowerEmAsyncify::transformAsyncFunction(Function &F, Instructions const& AsyncCalls) { assert(!AsyncCalls.empty()); // Pass 0 // collect all the return instructions from the original function // will use later std::vector<ReturnInst*> OrigReturns; for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { if (ReturnInst *RI = dyn_cast<ReturnInst>(&*I)) { OrigReturns.push_back(RI); } } // Pass 1 // Scan each async call and make the basic structure: // All these will be cloned into the callback functions // - allocate the async context before calling an async function // - check async right after calling an async function, save context & return if async, continue if not // - retrieve the async return value and free the async context if the called function turns out to be sync std::vector<AsyncCallEntry> AsyncCallEntries; AsyncCallEntries.reserve(AsyncCalls.size()); for (Instructions::const_iterator I = AsyncCalls.begin(), E = AsyncCalls.end(); I != E; ++I) { // prepare blocks Instruction *CurAsyncCall = *I; // The block containing the async call BasicBlock *CurBlock = CurAsyncCall->getParent(); // The block should run after the async call BasicBlock *AfterCallBlock = SplitBlock(CurBlock, CurAsyncCall->getNextNode()); // The block where we store the context and return BasicBlock *SaveAsyncCtxBlock = BasicBlock::Create(TheModule->getContext(), "SaveAsyncCtx", &F, AfterCallBlock); // return a dummy value at the end, to make the block valid new UnreachableInst(TheModule->getContext(), SaveAsyncCtxBlock); // allocate the context before making the call // we don't know the size yet, will fix it later // we cannot insert the instruction later because, // we need to make sure that all the instructions and blocks are fixed before we can generate DT and find context variables // In CallHandler.h `sp` will be put as the second parameter // such that we can take a note of the original sp CallInst *AllocAsyncCtxInst = CallInst::Create(AllocAsyncCtxFunction, Constant::getNullValue(I32), "AsyncCtx", CurAsyncCall); // Right after the call // check async and return if so // TODO: we can define truly async functions and partial async functions { // remove old terminator, which came from SplitBlock CurBlock->getTerminator()->eraseFromParent(); // go to SaveAsyncCtxBlock if the previous call is async // otherwise just continue to AfterCallBlock CallInst *CheckAsync = CallInst::Create(CheckAsyncFunction, "IsAsync", CurBlock); BranchInst::Create(SaveAsyncCtxBlock, AfterCallBlock, CheckAsync, CurBlock); } // take a note of this async call AsyncCallEntry CurAsyncCallEntry; CurAsyncCallEntry.AsyncCallInst = CurAsyncCall; CurAsyncCallEntry.AfterCallBlock = AfterCallBlock; CurAsyncCallEntry.AllocAsyncCtxInst = AllocAsyncCtxInst; CurAsyncCallEntry.SaveAsyncCtxBlock = SaveAsyncCtxBlock; // create an empty function for the callback, which will be constructed later CurAsyncCallEntry.CallbackFunc = Function::Create(CallbackFunctionType, F.getLinkage(), F.getName() + "__async_cb", TheModule); AsyncCallEntries.push_back(CurAsyncCallEntry); } // Pass 2 // analyze the context variables and construct SaveAsyncCtxBlock for each async call // also calculate the size of the context and allocate the async context accordingly for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { AsyncCallEntry & CurEntry = *EI; // Collect everything to be saved FindContextVariables(CurEntry); // Pack the variables as a struct { // TODO: sort them from large memeber to small ones, in order to make the struct compact even when aligned SmallVector<Type*, 8> Types; Types.push_back(CallbackFunctionType->getPointerTo()); for (Values::iterator VI = CurEntry.ContextVariables.begin(), VE = CurEntry.ContextVariables.end(); VI != VE; ++VI) { Types.push_back((*VI)->getType()); } CurEntry.ContextStructType = StructType::get(TheModule->getContext(), Types); } // fix the size of allocation CurEntry.AllocAsyncCtxInst->setOperand(0, ConstantInt::get(I32, DL->getTypeStoreSize(CurEntry.ContextStructType))); // construct SaveAsyncCtxBlock { // fill in SaveAsyncCtxBlock // temporarily remove the terminator for convenience CurEntry.SaveAsyncCtxBlock->getTerminator()->eraseFromParent(); assert(CurEntry.SaveAsyncCtxBlock->empty()); Type *AsyncCtxAddrTy = CurEntry.ContextStructType->getPointerTo(); BitCastInst *AsyncCtxAddr = new BitCastInst(CurEntry.AllocAsyncCtxInst, AsyncCtxAddrTy, "AsyncCtxAddr", CurEntry.SaveAsyncCtxBlock); SmallVector<Value*, 2> Indices; // store the callback { Indices.push_back(ConstantInt::get(I32, 0)); Indices.push_back(ConstantInt::get(I32, 0)); GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddrTy, AsyncCtxAddr, Indices, "", CurEntry.SaveAsyncCtxBlock); new StoreInst(CurEntry.CallbackFunc, AsyncVarAddr, CurEntry.SaveAsyncCtxBlock); } // store the context variables for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) { Indices.clear(); Indices.push_back(ConstantInt::get(I32, 0)); Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element is the callback function GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddrTy, AsyncCtxAddr, Indices, "", CurEntry.SaveAsyncCtxBlock); new StoreInst(CurEntry.ContextVariables[i], AsyncVarAddr, CurEntry.SaveAsyncCtxBlock); } // to exit the block, we want to return without unwinding the stack frame CallInst::Create(DoNotUnwindFunction, "", CurEntry.SaveAsyncCtxBlock); ReturnInst::Create(TheModule->getContext(), (F.getReturnType()->isVoidTy() ? 0 : Constant::getNullValue(F.getReturnType())), CurEntry.SaveAsyncCtxBlock); } } // Pass 3 // now all the SaveAsyncCtxBlock's have been constructed // we can clone F and construct callback functions // we could not construct the callbacks in Pass 2 because we need _all_ those SaveAsyncCtxBlock's appear in _each_ callback for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { AsyncCallEntry & CurEntry = *EI; Function *CurCallbackFunc = CurEntry.CallbackFunc; ValueToValueMapTy VMap; // Add the entry block // load variables from the context // also update VMap for CloneFunction BasicBlock *EntryBlock = BasicBlock::Create(TheModule->getContext(), "AsyncCallbackEntry", CurCallbackFunc); std::vector<LoadInst *> LoadedAsyncVars; { Type *AsyncCtxAddrTy = CurEntry.ContextStructType->getPointerTo(); BitCastInst *AsyncCtxAddr = new BitCastInst(CurCallbackFunc->arg_begin(), AsyncCtxAddrTy, "AsyncCtx", EntryBlock); SmallVector<Value*, 2> Indices; for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) { Indices.clear(); Indices.push_back(ConstantInt::get(I32, 0)); Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element of AsyncCtx is the callback function GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddrTy, AsyncCtxAddr, Indices, "", EntryBlock); LoadedAsyncVars.push_back(new LoadInst(AsyncVarAddr, "", EntryBlock)); // we want the argument to be replaced by the loaded value if (isa<Argument>(CurEntry.ContextVariables[i])) VMap[CurEntry.ContextVariables[i]] = LoadedAsyncVars.back(); } } // we don't need any argument, just leave dummy entries there to cheat CloneFunctionInto for (Function::const_arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE; ++AI) { if (VMap.count(AI) == 0) VMap[AI] = Constant::getNullValue(AI->getType()); } // Clone the function { SmallVector<ReturnInst*, 8> Returns; CloneFunctionInto(CurCallbackFunc, &F, VMap, false, Returns); // return type of the callback functions is always void // need to fix the return type if (!F.getReturnType()->isVoidTy()) { // for those return instructions that are from the original function // it means we are 'truly' leaving this function // need to store the return value right before ruturn for (size_t i = 0; i < OrigReturns.size(); ++i) { ReturnInst *RI = cast<ReturnInst>(VMap[OrigReturns[i]]); // Need to store the return value into the global area CallInst *RawRetValAddr = CallInst::Create(GetAsyncReturnValueAddrFunction, "", RI); BitCastInst *RetValAddr = new BitCastInst(RawRetValAddr, F.getReturnType()->getPointerTo(), "AsyncRetValAddr", RI); new StoreInst(RI->getOperand(0), RetValAddr, RI); } // we want to unwind the stack back to where it was before the original function as called // but we don't actually need to do this here // at this point it must be true that no callback is pended // so the scheduler will correct the stack pointer and pop the frame // here we just fix the return type for (size_t i = 0; i < Returns.size(); ++i) { ReplaceInstWithInst(Returns[i], ReturnInst::Create(TheModule->getContext())); } } } // the callback function does not have any return value // so clear all the attributes for return { AttributeSet Attrs = CurCallbackFunc->getAttributes(); CurCallbackFunc->setAttributes( Attrs.removeAttributes(TheModule->getContext(), AttributeSet::ReturnIndex, Attrs.getRetAttributes()) ); } // in the callback function, we never allocate a new async frame // instead we reuse the existing one for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { Instruction *I = cast<Instruction>(VMap[EI->AllocAsyncCtxInst]); ReplaceInstWithInst(I, CallInst::Create(ReallocAsyncCtxFunction, I->getOperand(0), "ReallocAsyncCtx")); } // mapped entry point & async call BasicBlock *ResumeBlock = cast<BasicBlock>(VMap[CurEntry.AfterCallBlock]); Instruction *MappedAsyncCall = cast<Instruction>(VMap[CurEntry.AsyncCallInst]); // To save space, for each async call in the callback function, we just ignore the sync case, and leave it to the scheduler // TODO need an option for this { for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { AsyncCallEntry & CurEntry = *EI; Instruction *MappedAsyncCallInst = cast<Instruction>(VMap[CurEntry.AsyncCallInst]); BasicBlock *MappedAsyncCallBlock = MappedAsyncCallInst->getParent(); BasicBlock *MappedAfterCallBlock = cast<BasicBlock>(VMap[CurEntry.AfterCallBlock]); // for the sync case of the call, go to NewBlock (instead of MappedAfterCallBlock) BasicBlock *NewBlock = BasicBlock::Create(TheModule->getContext(), "", CurCallbackFunc, MappedAfterCallBlock); MappedAsyncCallBlock->getTerminator()->setSuccessor(1, NewBlock); // store the return value if (!MappedAsyncCallInst->use_empty()) { CallInst *RawRetValAddr = CallInst::Create(GetAsyncReturnValueAddrFunction, "", NewBlock); BitCastInst *RetValAddr = new BitCastInst(RawRetValAddr, MappedAsyncCallInst->getType()->getPointerTo(), "AsyncRetValAddr", NewBlock); new StoreInst(MappedAsyncCallInst, RetValAddr, NewBlock); } // tell the scheduler that we want to keep the current async stack frame CallInst::Create(DoNotUnwindAsyncFunction, "", NewBlock); // finally we go to the SaveAsyncCtxBlock, to register the callbac, save the local variables and leave BasicBlock *MappedSaveAsyncCtxBlock = cast<BasicBlock>(VMap[CurEntry.SaveAsyncCtxBlock]); BranchInst::Create(MappedSaveAsyncCtxBlock, NewBlock); } } std::vector<AllocaInst*> ToPromote; // applying loaded variables in the entry block { BasicBlockSet ReachableBlocks = FindReachableBlocksFrom(ResumeBlock); for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) { Value *OrigVar = CurEntry.ContextVariables[i]; if (isa<Argument>(OrigVar)) continue; // already processed Value *CurVar = VMap[OrigVar]; assert(CurVar != MappedAsyncCall); if (Instruction *Inst = dyn_cast<Instruction>(CurVar)) { if (ReachableBlocks.count(Inst->getParent())) { // Inst could be either defined or loaded from the async context // Do the dirty works in memory // TODO: might need to check the safety first // TODO: can we create phi directly? AllocaInst *Addr = DemoteRegToStack(*Inst, false); new StoreInst(LoadedAsyncVars[i], Addr, EntryBlock); ToPromote.push_back(Addr); } else { // The parent block is not reachable, which means there is no confliction // it's safe to replace Inst with the loaded value assert(Inst != LoadedAsyncVars[i]); // this should only happen when OrigVar is an Argument Inst->replaceAllUsesWith(LoadedAsyncVars[i]); } } } } // resolve the return value of the previous async function // it could be the value just loaded from the global area // or directly returned by the function (in its sync case) if (!CurEntry.AsyncCallInst->use_empty()) { // load the async return value CallInst *RawRetValAddr = CallInst::Create(GetAsyncReturnValueAddrFunction, "", EntryBlock); BitCastInst *RetValAddr = new BitCastInst(RawRetValAddr, MappedAsyncCall->getType()->getPointerTo(), "AsyncRetValAddr", EntryBlock); LoadInst *RetVal = new LoadInst(RetValAddr, "AsyncRetVal", EntryBlock); AllocaInst *Addr = DemoteRegToStack(*MappedAsyncCall, false); new StoreInst(RetVal, Addr, EntryBlock); ToPromote.push_back(Addr); } // TODO remove unreachable blocks before creating phi // We go right to ResumeBlock from the EntryBlock BranchInst::Create(ResumeBlock, EntryBlock); /* * Creating phi's * Normal stack frames and async stack frames are interleaving with each other. * In a callback function, if we call an async function, we might need to realloc the async ctx. * at this point we don't want anything stored after the ctx, * such that we can free and extend the ctx by simply update STACKTOP. * Therefore we don't want any alloca's in callback functions. * */ if (!ToPromote.empty()) { DominatorTreeWrapperPass DTW; DTW.runOnFunction(*CurCallbackFunc); PromoteMemToReg(ToPromote, DTW.getDomTree()); } removeUnreachableBlocks(*CurCallbackFunc); } // Pass 4 // Here are modifications to the original function, which we won't want to be cloned into the callback functions for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { AsyncCallEntry & CurEntry = *EI; // remove the frame if no async functinon has been called CallInst::Create(FreeAsyncCtxFunction, CurEntry.AllocAsyncCtxInst, "", CurEntry.AfterCallBlock->getFirstNonPHI()); } }
/// ValueEnumerator - Enumerate module-level information. ValueEnumerator::ValueEnumerator(const Module *M) { InstructionCount = 0; // Enumerate the global variables. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) EnumerateValue(I); // Enumerate the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { EnumerateValue(I); EnumerateAttributes(cast<Function>(I)->getAttributes()); } // Enumerate the aliases. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I); // Remember what is the cutoff between globalvalue's and other constants. unsigned FirstConstant = Values.size(); // Enumerate the global variable initializers. for (Module::const_global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) EnumerateValue(I->getInitializer()); // Enumerate the aliasees. for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) EnumerateValue(I->getAliasee()); // Enumerate types used by the type symbol table. EnumerateTypeSymbolTable(M->getTypeSymbolTable()); // Insert constants that are named at module level into the slot pool so that // the module symbol table can refer to them... EnumerateValueSymbolTable(M->getValueSymbolTable()); // Enumerate types used by function bodies and argument lists. for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) { for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) EnumerateType(I->getType()); MetadataContext &TheMetadata = F->getContext().getMetadata(); typedef SmallVector<std::pair<unsigned, TrackingVH<MDNode> >, 2> MDMapTy; MDMapTy MDs; for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){ for (User::const_op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) EnumerateOperandType(*OI); EnumerateType(I->getType()); if (const CallInst *CI = dyn_cast<CallInst>(I)) EnumerateAttributes(CI->getAttributes()); else if (const InvokeInst *II = dyn_cast<InvokeInst>(I)) EnumerateAttributes(II->getAttributes()); // Enumerate metadata attached with this instruction. MDs.clear(); TheMetadata.getMDs(I, MDs); for (MDMapTy::const_iterator MI = MDs.begin(), ME = MDs.end(); MI != ME; ++MI) EnumerateMetadata(MI->second); } } // Optimize constant ordering. OptimizeConstants(FirstConstant, Values.size()); // Sort the type table by frequency so that most commonly used types are early // in the table (have low bit-width). std::stable_sort(Types.begin(), Types.end(), CompareByFrequency); // Partition the Type ID's so that the single-value types occur before the // aggregate types. This allows the aggregate types to be dropped from the // type table after parsing the global variable initializers. std::partition(Types.begin(), Types.end(), isSingleValueType); // Now that we rearranged the type table, rebuild TypeMap. for (unsigned i = 0, e = Types.size(); i != e; ++i) TypeMap[Types[i].first] = i+1; }
void CZeroInfo::depthFirstGatherer() { // Adding the pointer values among the arguments to the alias graph // We treat them as pointers to global targets. for (Function::const_arg_iterator I = TheFunction.arg_begin(), E = TheFunction.arg_end(); I != E; ++I) { if (I->getType()->getTypeID() == Type::PointerTyID) PointerAliasGraph.addEdge(I, PointsToTarget::GlobalTarget); } df_iterator<const Function*> It = df_begin(&TheFunction), End = df_end(&TheFunction); for ( ; It != End; It++) { const BasicBlock *BB = *It; // Look for store instructions sequentially in the basic block // updating pointer alias graphs for the other instructions BasicBlock::const_iterator iterBB; for (iterBB = BB->begin(); iterBB != BB->end(); ++iterBB) { const Instruction& I = *iterBB; // NOTE!!! Removed the if (I) clause here // if (I.hasName() && I.getType()->getTypeID() == Type::PointerTyID) { // Each of these cases needs to modify the alias graph appropriately if (isa<AllocaInst>(I)) { PointerAliasGraph.addEdge(&I, &I); } else if (isa<MallocInst>(I)) { // TODO: We'll be making this illegal and only allowing // calls to rmalloc and rfree. PointerAliasGraph.addEdge(&I, &I); } else if (isa<LoadInst>(I)) { PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget); } else if (isa<GetElementPtrInst>(I)) { // Check if the operand is a global value, in which case we // generate an alias to a generic global value. if (!isa<ConstantPointerNull>(I.getOperand(0))) if (isa<GlobalValue>(I.getOperand(0)) || isa<Constant>(I.getOperand(0))) PointerAliasGraph.addEdge(&I, PointsToTarget::GlobalTarget); else PointerAliasGraph.addAlias(&I, I.getOperand(0)); else PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget); } else if (isa<PHINode>(I)) { PointerAliasGraph.addEdge(&I, &I); } else if (isa<CallInst>(I)) { PointerAliasGraph.addEdge(&I, PointsToTarget::GlobalTarget); } else if (isa<CastInst>(I)) { PointerAliasGraph.addEdge(&I, PointsToTarget::DummyTarget); } } else if (!I.hasName()) { if (isa<StoreInst>(I)) { // We only consider stores of scalar pointers. if (I.getNumOperands() <= 2 || (I.getNumOperands() == 3 && I.getOperand(2) != getGlobalContext().getConstantInt(Type::Int32Ty, 0))) { if (!isa<ConstantPointerNull>(I.getOperand(1))) { BBPointerLiveInfo[BB][I.getOperand(1)] = true; df_iterator<const Function*> localIt = df_begin(&TheFunction), localEnd = df_end(&TheFunction); for ( ; localIt != localEnd; ++localIt) { if (DomTree->dominates((BasicBlock *) BB, (BasicBlock *) *localIt)) BBPointerLiveInfo[*localIt][I.getOperand(1)] = true; } } else { WarningsList += "Stores to null pointers disallowed in CZero\n"; } } } } } } }
bool TriCoreCallingConvHook::isRegValPtrType (MachineFunction& _mf) { Function::const_arg_iterator FI; FI = _mf.getFunction()->arg_begin(); std::advance(FI,curArg); return FI->getType()->isPointerTy()? true : false; }
SDValue NVPTXTargetLowering::LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); const DataLayout *TD = getDataLayout(); const Function *F = MF.getFunction(); const AttrListPtr &PAL = F->getAttributes(); SDValue Root = DAG.getRoot(); std::vector<SDValue> OutChains; bool isKernel = llvm::isKernelFunction(*F); bool isABI = (nvptxSubtarget.getSmVersion() >= 20); std::vector<Type *> argTypes; std::vector<const Argument *> theArgs; for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { theArgs.push_back(I); argTypes.push_back(I->getType()); } assert(argTypes.size() == Ins.size() && "Ins types and function types did not match"); int idx = 0; for (unsigned i=0, e=Ins.size(); i!=e; ++i, ++idx) { Type *Ty = argTypes[i]; EVT ObjectVT = getValueType(Ty); assert(ObjectVT == Ins[i].VT && "Ins type did not match function type"); // If the kernel argument is image*_t or sampler_t, convert it to // a i32 constant holding the parameter position. This can later // matched in the AsmPrinter to output the correct mangled name. if (isImageOrSamplerVal(theArgs[i], (theArgs[i]->getParent() ? theArgs[i]->getParent()->getParent() : 0))) { assert(isKernel && "Only kernels can have image/sampler params"); InVals.push_back(DAG.getConstant(i+1, MVT::i32)); continue; } if (theArgs[i]->use_empty()) { // argument is dead InVals.push_back(DAG.getNode(ISD::UNDEF, dl, ObjectVT)); continue; } // In the following cases, assign a node order of "idx+1" // to newly created nodes. The SDNOdes for params have to // appear in the same order as their order of appearance // in the original function. "idx+1" holds that order. if (PAL.getParamAttributes(i+1).hasAttribute(Attributes::ByVal) == false) { // A plain scalar. if (isABI || isKernel) { // If ABI, load from the param symbol SDValue Arg = getParamSymbol(DAG, idx); Value *srcValue = new Argument(PointerType::get(ObjectVT.getTypeForEVT( F->getContext()), llvm::ADDRESS_SPACE_PARAM)); SDValue p = DAG.getLoad(ObjectVT, dl, Root, Arg, MachinePointerInfo(srcValue), false, false, false, TD->getABITypeAlignment(ObjectVT.getTypeForEVT( F->getContext()))); if (p.getNode()) DAG.AssignOrdering(p.getNode(), idx+1); InVals.push_back(p); } else { // If no ABI, just move the param symbol SDValue Arg = getParamSymbol(DAG, idx, ObjectVT); SDValue p = DAG.getNode(NVPTXISD::MoveParam, dl, ObjectVT, Arg); if (p.getNode()) DAG.AssignOrdering(p.getNode(), idx+1); InVals.push_back(p); } continue; } // Param has ByVal attribute if (isABI || isKernel) { // Return MoveParam(param symbol). // Ideally, the param symbol can be returned directly, // but when SDNode builder decides to use it in a CopyToReg(), // machine instruction fails because TargetExternalSymbol // (not lowered) is target dependent, and CopyToReg assumes // the source is lowered. SDValue Arg = getParamSymbol(DAG, idx, getPointerTy()); SDValue p = DAG.getNode(NVPTXISD::MoveParam, dl, ObjectVT, Arg); if (p.getNode()) DAG.AssignOrdering(p.getNode(), idx+1); if (isKernel) InVals.push_back(p); else { SDValue p2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, ObjectVT, DAG.getConstant(Intrinsic::nvvm_ptr_local_to_gen, MVT::i32), p); InVals.push_back(p2); } } else { // Have to move a set of param symbols to registers and // store them locally and return the local pointer in InVals const PointerType *elemPtrType = dyn_cast<PointerType>(argTypes[i]); assert(elemPtrType && "Byval parameter should be a pointer type"); Type *elemType = elemPtrType->getElementType(); // Compute the constituent parts SmallVector<EVT, 16> vtparts; SmallVector<uint64_t, 16> offsets; ComputeValueVTs(*this, elemType, vtparts, &offsets, 0); unsigned totalsize = 0; for (unsigned j=0, je=vtparts.size(); j!=je; ++j) totalsize += vtparts[j].getStoreSizeInBits(); SDValue localcopy = DAG.getFrameIndex(MF.getFrameInfo()-> CreateStackObject(totalsize/8, 16, false), getPointerTy()); unsigned sizesofar = 0; std::vector<SDValue> theChains; for (unsigned j=0, je=vtparts.size(); j!=je; ++j) { unsigned numElems = 1; if (vtparts[j].isVector()) numElems = vtparts[j].getVectorNumElements(); for (unsigned k=0, ke=numElems; k!=ke; ++k) { EVT tmpvt = vtparts[j]; if (tmpvt.isVector()) tmpvt = tmpvt.getVectorElementType(); SDValue arg = DAG.getNode(NVPTXISD::MoveParam, dl, tmpvt, getParamSymbol(DAG, idx, tmpvt)); SDValue addr = DAG.getNode(ISD::ADD, dl, getPointerTy(), localcopy, DAG.getConstant(sizesofar, getPointerTy())); theChains.push_back(DAG.getStore(Chain, dl, arg, addr, MachinePointerInfo(), false, false, 0)); sizesofar += tmpvt.getStoreSizeInBits()/8; ++idx; } } --idx; Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &theChains[0], theChains.size()); InVals.push_back(localcopy); } } // Clang will check explicit VarArg and issue error if any. However, Clang // will let code with // implicit var arg like f() pass. // We treat this case as if the arg list is empty. //if (F.isVarArg()) { // assert(0 && "VarArg not supported yet!"); //} if (!OutChains.empty()) DAG.setRoot(DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &OutChains[0], OutChains.size())); return Chain; }
Module *llvm::CloneModule(const Module *M, DenseMap<const Value*, Value*> &ValueMap) { // First off, we need to create the new module... Module *New = new Module(M->getModuleIdentifier()); New->setDataLayout(M->getDataLayout()); New->setTargetTriple(M->getTargetTriple()); New->setModuleInlineAsm(M->getModuleInlineAsm()); // Copy all of the type symbol table entries over. const TypeSymbolTable &TST = M->getTypeSymbolTable(); for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end(); TI != TE; ++TI) New->addTypeName(TI->first, TI->second); // Copy all of the dependent libraries over. for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I) New->addLibrary(*I); // Loop over all of the global variables, making corresponding globals in the // new module. Here we add them to the ValueMap 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(I->getType()->getElementType(), false, GlobalValue::ExternalLinkage, 0, I->getName(), New); GV->setAlignment(I->getAlignment()); ValueMap[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->getType()->getElementType()), GlobalValue::ExternalLinkage, I->getName(), New); NF->copyAttributesFrom(I); ValueMap[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) ValueMap[I] = new GlobalAlias(I->getType(), GlobalAlias::ExternalLinkage, I->getName(), NULL, New); // 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>(ValueMap[I]); if (I->hasInitializer()) GV->setInitializer(cast<Constant>(MapValue(I->getInitializer(), ValueMap))); GV->setLinkage(I->getLinkage()); GV->setThreadLocal(I->isThreadLocal()); GV->setConstant(I->isConstant()); } // Similarly, copy over function bodies now... // for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) { Function *F = cast<Function>(ValueMap[I]); 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()); ValueMap[J] = DestI++; } std::vector<ReturnInst*> Returns; // Ignore returns cloned... CloneFunctionInto(F, I, ValueMap, Returns); } F->setLinkage(I->getLinkage()); } // And aliases for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) { GlobalAlias *GA = cast<GlobalAlias>(ValueMap[I]); GA->setLinkage(I->getLinkage()); if (const Constant* C = I->getAliasee()) GA->setAliasee(cast<Constant>(MapValue(C, ValueMap))); } return New; }