dotgnu-libjit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libjit-developers] Maybe someone else besides me will also find this am


From: Norbert Bollow
Subject: [Libjit-developers] Maybe someone else besides me will also find this amusing :)
Date: Sun, 5 Sep 2004 01:39:33 +0200

/* hellovm.c - a kind of "hello world" for libjit
 * 
 * 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
                                        (hellovm_main, "hellovm_output",
                                         (void *)hellovm_output, 
                                         hellovm_signature_output,
                                         &hellovm_reg, 1,
                                         JIT_CALL_NOTHROW);
                        }
                        break;
                        case 'C':
                        {
                                /* exit with exit value 0 */
                                pos++;
                                jit_insn_call_native
                                        (hellovm_main, "hellovm_exit",
                                         (void *)hellovm_exit, 
                                         hellovm_signature_exit,
                                         NULL, 0,
                                         JIT_CALL_NOTHROW|JIT_CALL_NORETURN);
                                willexit=1;
                        }
                        break;
                        default:
                        {
                                fprintf(stderr, "Error: Illegal opcode\n");
                                return 99;
                        }
                }
        }
        if(willexit)
        {
                if (!jit_function_compile(hellovm_main))
                {
                        fprintf(stderr, "JIT compilation error\n");
                        return 99;
                }
                jit_context_build_end(context);
                free(buf);
                if (!jit_function_apply(hellovm_main, NULL, &retval))
                {
                        fprintf(stderr, "Exception during execution\n");
                        return 99;
                }
                /* not reached with the current instruction set */
                return retval;
        }
        else
        {
                jit_function_abandon(hellovm_main);
                fprintf(stderr, "Error: program without exit opcode\n");
                return 99;
        }
}

static void hellovm_output(char *value)
{
        fputs(value, stdout);
}

static void hellovm_nulput(char *value)
{
        putchar(0);
}

static void hellovm_exit()
{
        exit(0);
}

static void out_of_memory()
{
        fprintf(stderr, "Out of memory.\n");
        exit(99);       
}

/* This function will not return unless the specified number of bytes
 * has been read successfully */
char* readbytes(int file, int bytestoread)
{
        char *buffer;
        int pos=0;
        int bytesread;

        if((buffer = jit_malloc(bytestoread)) == NULL)
        {
                perror("memory allocation error in readbytes()");
                exit(99);
        }

        while (pos<bytestoread)
        {
                bytesread=read(file, buffer+pos, bytestoread-pos);
                if(bytesread==-1)
                {
                        perror("read error in readbytes()");
                        exit(99);
                }
                if(bytesread==0)
                {
                        fprintf(stderr, "unexpected eof in readbytes()\n");
                        exit(99);
                }
                pos+=bytesread;
        }
        return buffer;
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]