/* hellovm.c - a kind of "hello world" for libjit * * Written by Norbert Bollow * * This program is a JIT for the "Hello VM" bytecode language, which * has just one (string) register, and three opcodes: A) load string * constant into register, B) output contents of register, C) exit program. * * Compile with: gcc hellovm.c -ljit -o hellovm * * A valid "Hello VM" bytecode language program, suitable as input file for * this JIT, can be generated by the following perl script * * #!/usr/bin/perl * open TEST, ">test"; * $bytecode="AHello World!\n\x00BC"; * print TEST "HelloVM\x00", pack('i',length($bytecode)), $bytecode; * * A slightly less trivial example can be generated e.g. with * $bytecode="AHello, \x00BBAWorld!\n\x00BC"; * * The contents of this file are in the Public Domain. */ #include #include #include #include char* readbytes(int, int); static void hellovm_output(char *); static void hellovm_exit(); static void out_of_memory(); int main(int argc, char *argv[]) { int fd; char *buf; int len; jit_context_t context; const jit_type_t hellovm_output_arg_type=jit_type_void_ptr; jit_type_t hellovm_signature_main; jit_type_t hellovm_signature_exit, hellovm_signature_output; jit_type_t hellovm_type_string; jit_value_t hellovm_reg; jit_value_t tmp; char *str; jit_function_t hellovm_main; int pos; int willexit=0; int retval; if(argc != 2) { printf("Usage: hellovm program\n"); return 99; } if((fd = open(argv[1], O_RDONLY)) < 0) { perror(argv[1]); return 99; } /* read filetype identification string and length field */ buf=readbytes(fd, 12); /* check filetype identification string */ if(jit_strcmp("HelloVM", buf)!=0) { fprintf(stderr, "%s is not in HelloVM format.\n", argv[1]); return 99; } /* check length field and read bytecode data */ len=*((int*) (buf+8)); if(len<0) { fprintf(stderr, "%s: Invalid length field.\n", argv[1]); return 99; } free(buf); buf=readbytes(fd, len); close(fd); /* Now the fun begins :) */ jit_init(); context = jit_context_create(); jit_context_build_start(context); /* Build signatures for output and exit functions */ hellovm_signature_output = jit_type_create_signature (jit_abi_cdecl, jit_type_void, (jit_type_t*)&hellovm_output_arg_type, 1, 0); if (!hellovm_signature_output) out_of_memory(); hellovm_signature_exit = jit_type_create_signature (jit_abi_cdecl, jit_type_void, NULL, 0, 0); if (!hellovm_signature_exit) out_of_memory(); /* There is always a single function with signature: int main() */ hellovm_signature_main = jit_type_create_signature (jit_abi_cdecl, jit_type_int, NULL, 0, 0); if (!hellovm_signature_main) out_of_memory(); hellovm_main = jit_function_create(context, hellovm_signature_main); if (!hellovm_main) out_of_memory(); /* The HelloVM has a single register holding a NUL-terminated string */ hellovm_type_string = jit_type_create_pointer(jit_type_sys_char, 1); if (!hellovm_type_string) out_of_memory(); hellovm_reg = jit_value_create(hellovm_main, hellovm_type_string); if (!hellovm_reg) out_of_memory(); /* Initialize the string register with "" */ tmp=jit_value_create_nint_constant (hellovm_main, hellovm_type_string, (int)""); if (!tmp) out_of_memory(); jit_insn_store(hellovm_main, hellovm_reg, tmp); /* Now JIT the supplied bytecodes */ pos=0; while(pos