Force link all definitions

Hi, all!

I am using Cling for make some kind of hot reload, and now I’m stuck with lazy linking.
Here is an example:

 interp.process("class Class { public: void Func() { int c = 100; }; };"
                 "Class obj; obj.Func();");

  if (const cling::Transaction* transaction = interp.getLastTransaction()) {
    if (auto module = transaction->getModule()) {
      for (auto& function : module->getFunctionList()) {
        std::cout << function.getName().str() << std::endl;
      }
    }
  }

produce:

?__cling_Un1Qu30@@YAXPEAX@Z
?Func@Class@@QEAAXXZ
llvm.stackprotector

This is ok, this is what I’m waiting for

But when I process this (only definitions without using this class and method):

 interp.process("class Class { public: void Func() { int c = 100; }; };");

  if (const cling::Transaction* transaction = interp.getLastTransaction()) {
    if (auto module = transaction->getModule()) {
      for (auto& function : module->getFunctionList()) {
        std::cout << function.getName().str() << std::endl;
      }
    }
  }

It produces an empty output . So I realized that the function has delayed linking. It does not have its own address in memory until I run (process) the code that will use it.

How can I force link all definitions in module?

Which way should I look? Are there any ways for cling/clang/llvm to force link?

Compilers generally do not emit all symbols.

I don’t understand yet why you need cling to emit all symbols. Could you explain with a bit more detail?

Yes of course. I have a object of my class running in the program, and I need to compile a new version of this class, and I don’t want to reinitialize (destroy) the existing object, I want to save its state and all existing pointers to it.

So I need to initialize all the symbols in the module to “replace” the previous version of the working functions (methods) with a new one (like “hot reload”) using the assembler insert to add jmp from the old function to the new one. And I still don’t know how to get pointers to constructor/destructor, I see them in the disassembler, but not with Cling.

This works well with Cling and standalone functions, which I enclosed in “extern C”, but not with class definitions.

There may be other ways to change the old class type to a new compiled one, but I don’t know them.

Thanks, interesting!

How do you plan to identify call locations to the functions to be replaced? Do you expect to iterate the symbols emitted by cling?

Generally, the logic is exactly the inverse: symbol resolution requests will trigger compilation. You want the opposite: emit all symbols to identify possible symbol usages?

You could try Interpreter::emitAllDecls(Transaction*); - does that help?

Axel.

I am trying this:

 interp.process("class Class { public: void Func() { int c = 100; }; };" );
 interp.emitAllDecls(const_cast<cling::Transaction*>(interp.getLastTransaction()));

But get exception:

getState() == kCollecting && “Cannot append declarations in current state.”

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.