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 )