LLVM Discussion Forums

Try to extract a set of basic blocks as a new function and insert it into a new module

I was trying to extract a set of basic blocks as a new function, and insert this new function into a new module and print it out as a new IR (sounds a bit complicated).

Below is my code (this is run on functions):

                        CodeExtractor CE(vistedBBs, nullptr, /* AggregateArgs */ false, /* BFI */ nullptr,
                        /* BPI */ nullptr, nullptr, /* AllowVarArgs */ false,/* AllowAlloca */ true,
                        /* Suffix */ s);
                        errs() << "\nCE function runs fine\n";
                        CodeExtractorAnalysisCache CEAC(F);
                        Function *new_F = CE.extractCodeRegion(CEAC);
                        errs() << "generating function runs fine\n";
                        errs() << "Function name is "<< new_F->getName() << "\n";

                        LLVMModuleRef new_M =  LLVMModuleCreateWithName("test");
                        Module * new_mod = unwrap(new_M);
                        errs() << "generating module runs fine\n";
                         for (auto curFref = new_mod->getFunctionList().begin(), 
                                    endFref = new_mod->getFunctionList().end(); 
                                          curFref != endFref; ++curFref) {
                                  errs() << "found function: " << curFref->getName() << "\n";
                        }
                        // here I want to insert new_F into this new module..
                        // 
                        //
                        errs() << "instrution count "<< new_mod->getInstructionCount() << "\n";
                        std::string Str;
                        raw_string_ostream OS(Str);
                        OS << *new_mod;
                        OS.flush();
                        errs() << Str;

The new_F that I extracted looks good. I got a couple of problems when I tried to insert it into the new module:

a. The module new_mod is supposed to be a new, empty module. And here, I didn’t inject the new_F function yet. However, when I print the module, I got the following errors:

; ModuleID = ‘test’
source_filename = “test”
preheader…2 header…2 body…2 then…1 continue…1 exiting…2 exit…2 preheader…3 header…3 body…3 exiting…3 exit…3 opt: /llvm/include/llvm/ADT/ilist_iterator.h:138: llvm::ilist_iterator<OptionsT, IsReverse, IsConst>::reference llvm::ilist_iterator<OptionsT, IsReverse, IsConst>::operator*() const [with OptionsT = llvm::ilist_detail::node_options<llvm::BasicBlock, true, false, void>; bool IsReverse = false; bool IsConst = false; llvm::ilist_iterator<OptionsT, IsReverse, IsConst>::reference = llvm::BasicBlock&]: Assertion `!NodePtr->isKnownSentinel()’ failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.

The module seems to already have a list of basic blocks. But when I tried to print the function list and the number of instructions, they are empty and 0.

b. How can I insert the function into that module? I tried either to manipulate the function list (to push_back the new function), or to use getOrInsertFunction (which allows me to insert a function type, but how should I actually insert that function new_F). neither of them work.

c. maybe a fundamental question would be is this the right way to do what I wanted to do?

Really appreciate your help!

Albert