bool ReduceCrashingNamedMDOps::TestNamedMDOps( std::vector<const MDNode *> &NamedMDOps) { // Convert list to set for fast lookup... SmallPtrSet<const MDNode *, 32> OldMDNodeOps; for (unsigned i = 0, e = NamedMDOps.size(); i != e; ++i) { OldMDNodeOps.insert(NamedMDOps[i]); } outs() << "Checking for crash with only " << OldMDNodeOps.size(); if (OldMDNodeOps.size() == 1) outs() << " named metadata operand: "; else outs() << " named metadata operands: "; ValueToValueMapTy VMap; Module *M = CloneModule(BD.getProgram(), VMap).release(); // This is a little wasteful. In the future it might be good if we could have // these dropped during cloning. for (auto &NamedMD : BD.getProgram()->named_metadata()) { // Drop the old one and create a new one M->eraseNamedMetadata(M->getNamedMetadata(NamedMD.getName())); NamedMDNode *NewNamedMDNode = M->getOrInsertNamedMetadata(NamedMD.getName()); for (MDNode *op : NamedMD.operands()) if (OldMDNodeOps.count(op)) NewNamedMDNode->addOperand(cast<MDNode>(MapMetadata(op, VMap))); } // Verify that this is still valid. legacy::PassManager Passes; Passes.add(createVerifierPass()); Passes.run(*M); // Try running on the hacked up program... if (TestFn(BD, M)) { // Make sure to use instruction pointers that point into the now-current // module, and that they don't include any deleted blocks. NamedMDOps.clear(); for (const MDNode *Node : OldMDNodeOps) NamedMDOps.push_back(cast<MDNode>(VMap.MD()[Node].get())); BD.setNewProgram(M); // It crashed, keep the trimmed version... return true; } delete M; // It didn't crash, try something else. return 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, ValueMapTypeRemapper *TypeMapper, ValueMaterializer *Materializer) { assert(NameSuffix && "NameSuffix cannot be null!"); #ifndef NDEBUG for (const Argument &I : OldFunc->args()) assert(VMap.count(&I) && "No mapping from source argument specified!"); #endif // Copy all attributes other than those stored in the AttributeList. We need // to remap the parameter indices of the AttributeList. AttributeList NewAttrs = NewFunc->getAttributes(); NewFunc->copyAttributesFrom(OldFunc); NewFunc->setAttributes(NewAttrs); // Fix up the personality function that got copied over. if (OldFunc->hasPersonalityFn()) NewFunc->setPersonalityFn( MapValue(OldFunc->getPersonalityFn(), VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer)); SmallVector<AttributeSet, 4> NewArgAttrs(NewFunc->arg_size()); AttributeList OldAttrs = OldFunc->getAttributes(); // Clone any argument attributes that are present in the VMap. for (const Argument &OldArg : OldFunc->args()) { if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) { NewArgAttrs[NewArg->getArgNo()] = OldAttrs.getParamAttributes(OldArg.getArgNo()); } } NewFunc->setAttributes( AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttributes(), OldAttrs.getRetAttributes(), NewArgAttrs)); bool MustCloneSP = OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent(); DISubprogram *SP = OldFunc->getSubprogram(); if (SP) { assert(!MustCloneSP || ModuleLevelChanges); // Add mappings for some DebugInfo nodes that we don't want duplicated // even if they're distinct. auto &MD = VMap.MD(); MD[SP->getUnit()].reset(SP->getUnit()); MD[SP->getType()].reset(SP->getType()); MD[SP->getFile()].reset(SP->getFile()); // If we're not cloning into the same module, no need to clone the // subprogram if (!MustCloneSP) MD[SP].reset(SP); } SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; OldFunc->getAllMetadata(MDs); for (auto MD : MDs) { NewFunc->addMetadata( MD.first, *MapMetadata(MD.second, VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer)); } // When we remap instructions, we want to avoid duplicating inlined // DISubprograms, so record all subprograms we find as we duplicate // instructions and then freeze them in the MD map. DebugInfoFinder DIFinder; // 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, SP ? &DIFinder : nullptr); // Add basic block mapping. VMap[&BB] = CBB; // It is only legal to clone a function if a block address within that // function is never referenced outside of the function. Given that, we // want to map block addresses from the old function to block addresses in // the clone. (This is different from the generic ValueMapper // implementation, which generates an invalid blockaddress when // cloning a function.) if (BB.hasAddressTaken()) { Constant *OldBBAddr = BlockAddress::get(const_cast<Function*>(OldFunc), const_cast<BasicBlock*>(&BB)); VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB); } // Note return instructions for the caller. if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator())) Returns.push_back(RI); } for (DISubprogram *ISP : DIFinder.subprograms()) { if (ISP != SP) { VMap.MD()[ISP].reset(ISP); } } // 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->front()])->getIterator(), BE = NewFunc->end(); BB != BE; ++BB) // Loop over all instructions, fixing each one as we find it... for (Instruction &II : *BB) RemapInstruction(&II, VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, TypeMapper, Materializer); }