// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See // the comment in `back/lto.rs` for why this exists. extern "C" void LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { Module *M = unwrap(Mod); // If the original source module didn't have a `DICompileUnit` then try to // merge all the existing compile units. If there aren't actually any though // then there's not much for us to do so return. if (Unit == nullptr) { for (DICompileUnit *CU : M->debug_compile_units()) { Unit = CU; break; } if (Unit == nullptr) return; } // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and // process it recursively. Note that we specifically iterate over instructions // to ensure we feed everything into it. DebugInfoFinder Finder; Finder.processModule(*M); for (Function &F : M->functions()) { for (auto &FI : F) { for (Instruction &BI : FI) { if (auto Loc = BI.getDebugLoc()) Finder.processLocation(*M, Loc); if (auto DVI = dyn_cast<DbgValueInst>(&BI)) Finder.processValue(*M, DVI); if (auto DDI = dyn_cast<DbgDeclareInst>(&BI)) Finder.processDeclare(*M, DDI); } } } // After we've found all our debuginfo, rewrite all subprograms to point to // the same `DICompileUnit`. for (auto &F : Finder.subprograms()) { F->replaceUnit(Unit); } // Erase any other references to other `DICompileUnit` instances, the verifier // will later ensure that we don't actually have any other stale references to // worry about. auto *MD = M->getNamedMetadata("llvm.dbg.cu"); MD->clearOperands(); MD->addOperand(Unit); }
// 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); }
/// Remove any debug info for global variables/functions in the given module for /// which said global variable/function no longer exists (i.e. is null). /// /// Debugging information is encoded in llvm IR using metadata. This is designed /// such a way that debug info for symbols preserved even if symbols are /// optimized away by the optimizer. This special pass removes debug info for /// such symbols. bool StripDeadDebugInfo::runOnModule(Module &M) { if (skipModule(M)) return false; bool Changed = false; LLVMContext &C = M.getContext(); // Find all debug info in F. This is actually overkill in terms of what we // want to do, but we want to try and be as resilient as possible in the face // of potential debug info changes by using the formal interfaces given to us // as much as possible. DebugInfoFinder F; F.processModule(M); // For each compile unit, find the live set of global variables/functions and // replace the current list of potentially dead global variables/functions // with the live list. SmallVector<Metadata *, 64> LiveGlobalVariables; DenseSet<DIGlobalVariableExpression *> VisitedSet; std::set<DIGlobalVariableExpression *> LiveGVs; for (GlobalVariable &GV : M.globals()) { SmallVector<DIGlobalVariableExpression *, 1> GVEs; GV.getDebugInfo(GVEs); for (auto *GVE : GVEs) LiveGVs.insert(GVE); } std::set<DICompileUnit *> LiveCUs; // Any CU referenced from a subprogram is live. for (DISubprogram *SP : F.subprograms()) { if (SP->getUnit()) LiveCUs.insert(SP->getUnit()); } bool HasDeadCUs = false; for (DICompileUnit *DIC : F.compile_units()) { // Create our live global variable list. bool GlobalVariableChange = false; for (auto *DIG : DIC->getGlobalVariables()) { if (DIG->getExpression() && DIG->getExpression()->isConstant()) LiveGVs.insert(DIG); // Make sure we only visit each global variable only once. if (!VisitedSet.insert(DIG).second) continue; // If a global variable references DIG, the global variable is live. if (LiveGVs.count(DIG)) LiveGlobalVariables.push_back(DIG); else GlobalVariableChange = true; } if (!LiveGlobalVariables.empty()) LiveCUs.insert(DIC); else if (!LiveCUs.count(DIC)) HasDeadCUs = true; // If we found dead global variables, replace the current global // variable list with our new live global variable list. if (GlobalVariableChange) { DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables)); Changed = true; } // Reset lists for the next iteration. LiveGlobalVariables.clear(); } if (HasDeadCUs) { // Delete the old node and replace it with a new one NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); NMD->clearOperands(); if (!LiveCUs.empty()) { for (DICompileUnit *CU : LiveCUs) NMD->addOperand(CU); } Changed = true; } return Changed; }