// Clone the module-level debug info associated with OldFunc. The cloned data // will point to NewFunc instead. static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap) { DebugInfoFinder Finder; Finder.processModule(*OldFunc->getParent()); const MDNode *OldSubprogramMDNode = FindSubprogram(OldFunc, Finder); if (!OldSubprogramMDNode) return; // Ensure that OldFunc appears in the map. // (if it's already there it must point to NewFunc anyway) VMap[OldFunc] = NewFunc; DISubprogram NewSubprogram(MapMetadata(OldSubprogramMDNode, VMap)); for (DICompileUnit CU : Finder.compile_units()) { DIArray Subprograms(CU.getSubprograms()); // If the compile unit's function list contains the old function, it should // also contain the new one. for (unsigned i = 0; i < Subprograms.getNumElements(); i++) { if ((MDNode*)Subprograms.getElement(i) == OldSubprogramMDNode) { AddOperand(CU, Subprograms, NewSubprogram); break; } } } }
void PTXAsmPrinter::EmitStartOfAsmFile(Module &M) { const PTXSubtarget& ST = TM.getSubtarget<PTXSubtarget>(); // Emit the PTX .version and .target attributes OutStreamer.EmitRawText(Twine("\t.version ") + ST.getPTXVersionString()); OutStreamer.EmitRawText(Twine("\t.target ") + ST.getTargetString() + (ST.supportsDouble() ? "" : ", map_f64_to_f32")); // .address_size directive is optional, but it must immediately follow // the .target directive if present within a module if (ST.supportsPTX23()) { const char *addrSize = ST.is64Bit() ? "64" : "32"; OutStreamer.EmitRawText(Twine("\t.address_size ") + addrSize); } OutStreamer.AddBlankLine(); // Define any .file directives DebugInfoFinder DbgFinder; DbgFinder.processModule(M); for (DebugInfoFinder::iterator I = DbgFinder.compile_unit_begin(), E = DbgFinder.compile_unit_end(); I != E; ++I) { DICompileUnit DIUnit(*I); StringRef FN = DIUnit.getFilename(); StringRef Dir = DIUnit.getDirectory(); GetOrCreateSourceID(FN, Dir); } OutStreamer.AddBlankLine(); // declare external functions for (Module::const_iterator i = M.begin(), e = M.end(); i != e; ++i) EmitFunctionDeclaration(i); // declare global variables for (Module::const_global_iterator i = M.global_begin(), e = M.global_end(); i != e; ++i) EmitVariableDeclaration(i); }
// Clone the module-level debug info associated with OldFunc. The cloned data // will point to NewFunc instead. static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap) { DebugInfoFinder Finder; Finder.processModule(*OldFunc->getParent()); const DISubprogram *OldSubprogramMDNode = FindSubprogram(OldFunc, Finder); if (!OldSubprogramMDNode) return; auto *NewSubprogram = cast<DISubprogram>(MapMetadata(OldSubprogramMDNode, VMap)); NewFunc->setSubprogram(NewSubprogram); for (auto *CU : Finder.compile_units()) { auto Subprograms = CU->getSubprograms(); // If the compile unit's function list contains the old function, it should // also contain the new one. for (auto *SP : Subprograms) { if (SP == OldSubprogramMDNode) { AddOperand(CU, Subprograms, NewSubprogram); break; } } } }
// 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); }
/// 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) { 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<Value *, 64> LiveGlobalVariables; SmallVector<Value *, 64> LiveSubprograms; DenseSet<const MDNode *> VisitedSet; for (DebugInfoFinder::iterator CI = F.compile_unit_begin(), CE = F.compile_unit_end(); CI != CE; ++CI) { // Create our compile unit. DICompileUnit DIC(*CI); assert(DIC.Verify() && "DIC must verify as a DICompileUnit."); // Create our live subprogram list. DIArray SPs = DIC.getSubprograms(); bool SubprogramChange = false; for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { DISubprogram DISP(SPs.getElement(i)); assert(DISP.Verify() && "DISP must verify as a DISubprogram."); // Make sure we visit each subprogram only once. if (!VisitedSet.insert(DISP).second) continue; // If the function referenced by DISP is not null, the function is live. if (DISP.getFunction()) LiveSubprograms.push_back(DISP); else SubprogramChange = true; } // Create our live global variable list. DIArray GVs = DIC.getGlobalVariables(); bool GlobalVariableChange = false; for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) { DIGlobalVariable DIG(GVs.getElement(i)); assert(DIG.Verify() && "DIG must verify as DIGlobalVariable."); // Make sure we only visit each global variable only once. if (!VisitedSet.insert(DIG).second) continue; // If the global variable referenced by DIG is not null, the global // variable is live. if (DIG.getGlobal()) LiveGlobalVariables.push_back(DIG); else GlobalVariableChange = true; } // If we found dead subprograms or global variables, replace the current // subprogram list/global variable list with our new live subprogram/global // variable list. if (SubprogramChange) { // Make sure that 9 is still the index of the subprograms. This is to make // sure that an assert is hit if the location of the subprogram array // changes. This is just to make sure that this is updated if such an // event occurs. assert(DIC->getNumOperands() >= 10 && SPs == DIC->getOperand(9) && "DICompileUnits is expected to store Subprograms in operand " "9."); DIC->replaceOperandWith(9, MDNode::get(C, LiveSubprograms)); Changed = true; } if (GlobalVariableChange) { // Make sure that 10 is still the index of global variables. This is to // make sure that an assert is hit if the location of the subprogram array // changes. This is just to make sure that this index is updated if such // an event occurs. assert(DIC->getNumOperands() >= 11 && GVs == DIC->getOperand(10) && "DICompileUnits is expected to store Global Variables in operand " "10."); DIC->replaceOperandWith(10, MDNode::get(C, LiveGlobalVariables)); Changed = true; } // Reset lists for the next iteration. LiveSubprograms.clear(); LiveGlobalVariables.clear(); } return Changed; }
void DIEItem::CreateCompileUnitChildren(wxTreeCtrl *tree, const wxTreeItemId& id) { // It's expensive to rescan the entire module, but it's only done lazily. DebugInfoFinder diFinder; diFinder.processModule(*const_cast<Module *>(module_)); // CU-specific Types if (diFinder.type_count() > 0) { llvm::SmallVector<llvm::MDNode*, 32> cuTypes; for (DebugInfoFinder::iterator it = diFinder.type_begin(), itEnd = diFinder.type_end(); it != itEnd; ++it) { DIType diType(*it); if (diType.getCompileUnit() == node_) { cuTypes.push_back(*it); } } if (!cuTypes.empty()) { CreateChild(tree, id, new DIETypeListItem( module_, _("Types"), cuTypes.begin(), cuTypes.end())); } } // CU-specific Global variables if (diFinder.global_variable_count() > 0) { llvm::SmallVector<llvm::MDNode*, 32> cuVariables; for (DebugInfoFinder::iterator it = diFinder.global_variable_begin(), itEnd = diFinder.global_variable_end(); it != itEnd; ++it) { DIGlobalVariable diVar(*it); if (diVar.getCompileUnit() == node_) { cuVariables.push_back(*it); } } if (!cuVariables.empty()) { CreateChild(tree, id, new DIEListItem( module_, _("Global Variables"), cuVariables.begin(), cuVariables.end())); } } // CU-specific Subprograms if (diFinder.subprogram_count() > 0) { llvm::SmallVector<llvm::MDNode*, 32> cuSubprograms; for (DebugInfoFinder::iterator it = diFinder.subprogram_begin(), itEnd = diFinder.subprogram_end(); it != itEnd; ++it) { DISubprogram diSubprogram(*it); if (diSubprogram.getCompileUnit() == node_) { cuSubprograms.push_back(*it); } } if (!cuSubprograms.empty()) { CreateChild(tree, id, new DIEListItem( module_, _("Subprograms"), cuSubprograms.begin(), cuSubprograms.end())); } } }
// 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; }