I'm attempting to use AsmJIT in a stack-based language implementation
here (BitBucket) and while running the word compiler on a test word (which will just push 5 and 10, and then add them), I get an assertion error:
*** ASSERTION FAILURE at ..\AsmJit\CompilerX86X64.cpp (line 3588)
*** osrc.isVar()
A small example of code that will cause this is:
#include <AsmJit.h>
using namespace AsmJit;
// CompiledFunc: pointer to (nothing -> void)
typedef void (*CompiledFunc)();
typedef char byte;
struct LObject { byte tag; int value; }
#define TAG_INT 0
LObject make_lobject(byte tag, int value)
{
LObject obj;
obj.tag = tag;
obj.value = value;
return obj;
}
// should push an object. do nothing...
void push_obj(LObject obj) { }
// should pop an object. return the same object every time...
LObject pop_obj() { return make_lobject(TAG_INT, 0); }
// a b -- a+b
void add()
{
LObject right = pop_obj();
LObject left = pop_obj();
push_obj(make_lobject(TAG_INT, left.value + right.value));
}
void main()
{
Compiler c;
// create a function to generate code for
EFunction* func = c.newFunction(CALL_CONV_DEFAULT, FunctionBuilder0<int>());
// attempt to generate without prologue/epilogue
func->setHint(FUNCTION_HINT_NAKED, true);
// generate a call that in C would look like: push_obj(TAG_INT, 5);
ECall* push_int5 = c.call((void*)(&push_obj));
push_int5->setPrototype(CALL_CONV_DEFAULT, FunctionBuilder2<int, byte, int>());
push_int5->setArgument(0, imm(TAG_INT));
push_int5->setArgument(1, imm(5));
// generate a call that in C would look like: push_obj(TAG_INT, 10);
ECall* push_int10 = c.call((void*)(&push_obj));
push_int10->setPrototype(CALL_CONV_DEFAULT, FunctionBuilder2<int, byte, int>());
push_int10->setArgument(0, imm(TAG_INT));
push_int10->setArgument(1, imm(10));
// generate a call call to the add() function above.
ECall* word_call = c.call(&add);
FunctionBuilder0<int> x;
word_call->setPrototype(CALL_CONV_DEFAULT, FunctionBuilder0<int>());
// now finish and compile the function
c.endFunction();
CompiledWord word = function_cast<CompiledWord>(c.make());
// and call it
(*word)();
}
I'm not sure what my code is doing incorrectly... any hints?
And also, how can I tell AsmJIT to call a function that takes no arguments and returns void (i.e. nothing)? Currently I'm just using FunctionBuilder0<int>, but that feels wrong; the function really is not returning an integer.
Another question: how can I generate a tail-call? I just want to be able to jump to a function, instead of calling it. Does AsmJIT do this? And if so, how do I tell AsmJIT to do the tail-call?
Thanks!