Alien-LibJIT
view release on metacpan or search on metacpan
libjit/samples/hellovm.c view on Meta::CPAN
/* hellovm.c - a kind of "hello world" for libjit
*
* Written by Norbert Bollow <nb@SoftwareEconomics.biz>
*
* 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 <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <jit/jit.h>
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<len)
{
switch(buf[pos])
{
case 'A':
{
/* load string constant into hellovm_reg */
pos++;
str=jit_strndup(buf+pos, len-pos);
if (!str && buf[pos] && len-pos)
out_of_memory();
tmp=jit_value_create_nint_constant
(hellovm_main, hellovm_type_string,
(int)str);
if (!tmp) out_of_memory();
jit_insn_store(hellovm_main, hellovm_reg, tmp);
pos+=jit_strlen(str)+1;
}
break;
case 'B':
{
/* output contents of hellovm_reg */
pos++;
jit_insn_call_native
( run in 1.665 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )