diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -116,6 +116,8 @@ void clearArguments(); + void deleteBodyImpl(); + /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for /// the module. @@ -667,7 +669,7 @@ /// the linkage to external. /// void deleteBody() { - dropAllReferences(); + deleteBodyImpl(); setLinkage(ExternalLinkage); } diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -548,6 +548,32 @@ clearMetadata(); } +// This function do almost all the same things as Function::dropAllReferences(), +// except setting Op<0..3> with PointerNull. +void Function::deleteBodyImpl() { + setIsMaterializable(false); + + for (BasicBlock &BB : *this) + BB.dropAllReferences(); + + // Delete all basic blocks. They are now unused, except possibly by + // blockaddresses, but BasicBlock's destructor takes care of those. + while (!BasicBlocks.empty()) + BasicBlocks.begin()->eraseFromParent(); + + // The code needs to match Function::allocHungoffUselist(). + if (getNumOperands()) { + auto *CPN = ConstantPointerNull::get(PointerType::get(getContext(), 0)); + Op<0>().set(CPN); + Op<1>().set(CPN); + Op<2>().set(CPN); + setValueSubclassData(getSubclassDataFromValue() & ~0xe); + } + + // Metadata is stored in a side-table. + clearMetadata(); +} + void Function::addAttributeAtIndex(unsigned i, Attribute Attr) { AttributeSets = AttributeSets.addAttributeAtIndex(getContext(), i, Attr); }