First prototype finished

View: New views
1 Messages — Rating Filter:   Alert me  

First prototype finished

by Pippijn van Steenhoven :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I just finished the first prototype of the C++ lightning assembler. I
need to do a lot of work before I can call it usable, but it successfully
compiles the simple examples such as "add" and "fib" to machine code
using GNU Lightning. The attachment is an example snippet with in- and
output. I still don't have support for differently sized arguments, but
at least floating point (using the 32 bit float) and 32 bit integral
immediates work.

--
Pippijn van Steenhoven


#include <iostream>

#include <assembler/compiler.h>
#include <assembler.h>

int
main (int argc, char *argv[])
{
  compiler comp;
  // compile a named file "-" is stdin
  comp.compile (argc > 1 ? argv[1] : "-");
  // do some semantic checks such as whether all used
  // instructions actually exist, whether all arguments
  // are correctly typed, whether
  comp.check ();
  // store the parse tree into a string and load it back
  // to test whether serialisation works
  // deserialisation, by the way, generates the same AST the
  // parser did, so comp.check () could be done again to verify
  // the byte-code
  comp.load (comp.store ());
  // print out the AST in the same format it was read
  // (lightning asm). this output could be stored to a file
  // and is basically a disassembly of the byte-code
  std::cout << "Printing the parse tree back into lightning-asm:\n";
  std::cout << "------------------------------------------------\n";
  comp.print (std::cout);

  // assembler is an object whose only job is to transform
  // lightning-asm to machine code. it utilises lightning's
  // jit_* macros to do so
  assembler as;
  // generate machine code
  comp.assemble (as);
  // print a disassembly of the generated code to stdout
  std::cout << "\nPrinting a disassembly of the machine code:\n";
  std::cout << "-------------------------------------------\n";
  as.disassemble (std::cout);

  // assembler::cast can cast to any pointer type. before it does
  // so, it calls jit::flush_code.
  int (*func) (int) = as.cast ();
  // call the function
  std::cout << "\nCalling the function:\n";
  std::cout << "---------------------\n";
  std::cout << func (32) << '\n';

  return 0;
}

/* This is the input file I fed it:

# mnemonic      op1             op2             op3     ret
prolog          1
arg_ui                                                  => $in
getarg_ui       %v0,            $in                                   # V0 = n
blti_ui         !forward,       %v0,            2       => @ref       # If V0 < 2, jump
subi_ui         %v1,            %v0,            1                     # V1 = n - 1
subi_ui         %v2,            %v0,            2                     # V2 = n - 2
prepare_i       1                                                     # Prepare for a call with one argument
pusharg_ui      %v1                                                   # Push the argument
finish          @self         # The self-pointer is a pointer to the
                              # beginning of the code block (entry point).
                              # This instruction jumps to the beginning of the
                              # code, causing recursion

retval_i        %v1                                   # Store the result in V1
prepare_i       1                                     # Another
pusharg_ui      %v2                                   # recursive
finish          @self                                 # call
retval_i        %v2                                   # Store the result in V2
addi_ui         %v1,            %v1,            1     # V1++
addr_ui         %ret,           %v1,            %v2   # RET = V1 + V2
ret                                                   # Return

patch           @ref                                  # Patch jump, we get here if V0 was < 2
movi_i          %ret,           1                     # RET = 1
ret                                                   # Return

 */

/* This is the output of the program on my x86_64 machine:

Printing the parse tree back into lightning-asm:
------------------------------------------------
prolog 1
arg_ui => $in
getarg_ui %v0, $in
blti_ui !forward, %v0, 2 => @ref
subi_ui %v1, %v0, 1
subi_ui %v2, %v0, 2
prepare_i 1
pusharg_ui %v1
finish @self
retval_i %v1
prepare_i 1
pusharg_ui %v2
finish @self
retval_i %v2
addi_ui %v1, %v1, 1
addr_ui %ret, %v1, %v2
ret
patch @ref
movi_i %ret, 1
ret

Printing a disassembly of the machine code:
-------------------------------------------
0000000000000000 53                       push %rbx
0000000000000001 41 54                    push %r12
0000000000000003 41 55                    push %r13
0000000000000005 55                       push %rbp
0000000000000006 48 89 e5                 mov %rsp, %rbp
0000000000000009 89 fb                    mov %edi, %ebx
000000000000000b 83 fb 02                 cmp $0x2, %ebx
000000000000000e 0f 82 55 00 00 00        jb 0x69
0000000000000014 8d 73 ff                 lea -0x1(%rbx), %esi
0000000000000017 8d 7b fe                 lea -0x2(%rbx), %edi
000000000000001a 49 89 f0                 mov %rsi, %r8
000000000000001d 49 bb 48 3a 1f 8d ff 7f  mov $0x7fff8d1f3a48, %r11
               - 00 00
0000000000000027 49 89 f4                 mov %rsi, %r12
000000000000002a 49 89 fd                 mov %rdi, %r13
000000000000002d 4c 89 c7                 mov %r8, %rdi
0000000000000030 49 ff d3                 callq %r11
0000000000000033 4c 89 e6                 mov %r12, %rsi
0000000000000036 4c 89 ef                 mov %r13, %rdi
0000000000000039 89 c6                    mov %eax, %esi
000000000000003b 49 89 f8                 mov %rdi, %r8
000000000000003e 49 bb 48 3a 1f 8d ff 7f  mov $0x7fff8d1f3a48, %r11
               - 00 00
0000000000000048 49 89 f4                 mov %rsi, %r12
000000000000004b 49 89 fd                 mov %rdi, %r13
000000000000004e 4c 89 c7                 mov %r8, %rdi
0000000000000051 49 ff d3                 callq %r11
0000000000000054 4c 89 e6                 mov %r12, %rsi
0000000000000057 4c 89 ef                 mov %r13, %rdi
000000000000005a 89 c7                    mov %eax, %edi
000000000000005c 83 c6 01                 add $0x1, %esi
000000000000005f 8d 04 3e                 lea (%rsi,%rdi), %eax
0000000000000062 5d                       pop %rbp
0000000000000063 41 5d                    pop %r13
0000000000000065 41 5c                    pop %r12
0000000000000067 5b                       pop %rbx
0000000000000068 c3                       ret
0000000000000069 b8 01 00 00 00           mov $0x1, %eax
000000000000006e 5d                       pop %rbp
000000000000006f 41 5d                    pop %r13
0000000000000071 41 5c                    pop %r12
0000000000000073 5b                       pop %rbx
0000000000000074 c3                       ret

Calling the function:
---------------------
7049155

 */



_______________________________________________
Lightning mailing list
Lightning@...
http://lists.gnu.org/mailman/listinfo/lightning

signature.asc (196 bytes) Download Attachment