This is actually easy and supported. The only requirement is to keep the instances returned by `addFunc()`.
Example:
X86Compiler c(...);
// Variables to keep the function nodes.
X86FuncNode* funcA;
X86FuncNode* funcB;
// ------- Function A -------.
funcA = c.addFunc(kFuncConvHost, FuncBuilder0<Void>());
...
c.endFunc();
// ------- Function B -------.
funcB = c.addFunc(kFuncConvHost, FuncBuilder0<Void>());
...
c.endFunc();
// This will make both.
void* p = c.make();
Problem here is how you will get the pointer to the second function. I will explain below.
2. I saw some references to setCurrentEmmitable but does not seem to exist?
It does, the function is called `setCursor()`, but it doesn't do what you want. The setCursor is for injecting code and it basically sets the current node so the next emitted node is added after it (you can use this technique to put some variable to be initialized at the beginning of the function for example).
3. Expanding on the previous question, how does one create two mutually recursive functions? Eg: function A calls B and function B calls A?
Okay, more complicated, more ways how it can be done, but possible and supported.
Let's extend the first example, but instead of using addFunc() we can use newFunc(). This method creates a new function node, but won't add it to the compiler.
Each function always has two labels - Entry and Exit. You can use entry label to reference the function that you didn't yet generate by function that you are just generating. See the example:
X86FuncNode* funcA = c.newFunc(kFuncConvHost, FuncBuilder0<Void>());
X86FuncNode* funcB = c.newFunc(kFuncConvHost, FuncBuilder0<Void>());
// ------- Function A -------.
c.addNode(funcA);
// You can call func A or func B simply by:
c.call(funcA->getEntryLabel());
c.call(funcB->getEntryLabel());
...
c.endFunc();
// ------- Function B -------.
c.addNode(funcB);
// You can call func A or func B simply by (the same...):
c.call(funcA->getEntryLabel());
c.call(funcB->getEntryLabel());
...
c.endFunc();
...
c.make();
4. I need pointer to both the functions after compilation, while make() returns pointer to a single function afaik.
I think I have to work on this one as it's possible to get the pointer, but it's not straightforward as it should be. Basically the Compiler itself doesn't have such functionality yet, but it's easy to get the pointer from the assembler. As Compiler is basically a high-level interface that serializes to assembler, you can create X86Assembler instance and serialize the compiler content to it.
JitRuntime runtime;
X86Compiler c(&runtime);
// Instead of calling c.make(), do the following:
X86Assembler a(c.getRuntime());
// Serialize to assembler.
c.serialize(a);
// This will allocate a virtual memory and relocate to it.
void* p = a.make();
// To get any function, you will have to use labels again, as assembler
// always stores the offset of bound labels, the pointer can be easily
// calculated:
void* pFuncB = (void*)( (uint8_t*)p + a.getLabelData(funcB->getEntryLabel() );
Also when calling `c.make()` or `a.make()` the virtual memory allocated is for the whole code, so it can only be released by a single call to `runtime.release(ptr)`.
PS: Thanks for the questions, I will put this to tests so it's tested. I just wrote it how it should work, but didn't test now. If you face any problems please let me know.