Saturday, March 28, 2009

LIR Compiler - Goal 1 reached

I got the lex file to compile and work for the small program to add two integers. I must say the flex script isn't really flexible at the moment, and really, it is the hardcore 0th level in which you can get Goal 1 done, but I can say that goal 1 has been done. Now, I will try to build upon the code to improve the lexical analysis, and hopefully will get a good working parser in the coming weeks. Comments on the work are welcome, especially for those who are following the project.

The lex source code is posted here

Updates

Alright, I have been a little lax on posting updates regarding the project partly because I have not been able to get much done, and I had exams.
In my last post, I had mentioned that I had made the temporary source code ready which would take two numbers and add them, and output the result. In the past week, I wrote down the flex script to convert the little LIR instructions into their corresponding statements in the source. But so far, I haven't gotten much success with flex. The .c file generated by flex doesn't seem to compile, giving an error:
Undefined reference to yywrap().
I am trying to read up on flex more, so that I can get some insight on what I am doing wrong. I will try to post on their mailing lists as well, since I couldn't find any IRC channels or anything.

I have also posted information about Guards on https://developer.mozilla.org/En/Nanojit. The information is not much, and I am trying to get the tracer output so as to illustrate in a more transparent manner about guards(and where they occur).

Sunday, March 1, 2009

Updates for LIR Compiler

Currently, for the LIR Compiler project, I need to make a parser for LIR, which can then generate the required C code to then compile LIR.
Part of this task is also to see how nanojit currently uses LIR. It is pretty simple once you refer to the code snippet provided here - https://developer.mozilla.org/En/Nanojit

Interesting part are the lines 38-44:
// Write a few LIR instructions to the buffer: add the first parameter
// to the constant 2.
writer.ins0(LIR_start);
LIns *two = writer.insImm(2);
LIns *firstParam = writer.insParam(0, 0);
LIns *result = writer.ins2(LIR_add, firstParam, two);
writer.ins1(LIR_ret, result);
Basically, what the code provided above is doing is feeding raw LIR into the LIR Buffer, using the LIRWriter's writer object. From an operational point of view, it is creating a function, which takes an integer input, and adds it to two, and outputs the result. The function is created here on lines 57-69:
// Compile the fragment.
compile(fragmento->assm(), f);
if (fragmento->assm()->error() != None) {
fprintf(stderr, "error compiling fragment\n");
return 1;
}
printf("Compilation successful.\n");

// Call the compiled function.
typedef JS_FASTCALL int32_t (*AddTwoFn)(int32_t);
AddTwoFn fn = reinterpret_cast(f->code());
printf("2 + 5 = %d\n", fn(5));
return 0;

This upper half of this snippet includes code where the raw LIR is first converted into machine code.(where compile(fragmento->assm(), f); is called basically).

Then a pointer to a function is used, which takes an int as input and returns the sum of that parameter with two. (
typedef JS_FASTCALL int32_t (*AddTwoFn)(int32_t); )

Then, printf is hardcoded to call it with a parameter 5, and on linking with nanojit library, the following program will display
2+5=7
Now, what I need to do is generate output for this:

   start
two = int 2
twoPlusTwo = add two, two
ret twoPlusTwo


This adds two and two in the most hardcoded way possible. The conversion from LIR to a program like one shown above is the task of the parser.
What the parser needs to generate for the above code will be this(in a raw form)(changes only):

writer.ins0(LIR_start);
LIns *two = writer.insImm(2);
LIns *firstParam = writer.insImm(2);
LIns *result = writer.ins2(LIR_add, firstParam, two);
writer.ins1(LIR_ret, result);

and
// Call the compiled function.
typedef JS_FASTCALL int32_t (*AddTwoFn)();
AddTwoFn fn = reinterpret_cast(f->code());
printf("2 + 2 = %d\n", fn());
return 0;

Two minor changes, and we have working end product for the parser to produce to complete Goal 0.
Regarding the parser, I am planning to use Flex as suggested by jorendorff