Software: Apache. PHP/5.4.45 

uname -a: Linux webm056.cluster010.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue
Sep 17 08:14:20 UTC 2024 x86_64
 

uid=243112(mycochar) gid=100(users) groups=100(users)  

Safe-mode: OFF (not secure)

/home/mycochar/www/image/photo/gcc-12.3.0/gcc/jit/docs/examples/tut04-toyvm/   drwxr-xr-x
Free 0 B of 0 B (0%)
Your ip: 216.73.216.77 - Server ip: 213.186.33.19
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    

[Enumerate]    [Encoder]    [Tools]    [Proc.]    [FTP Brute]    [Sec.]    [SQL]    [PHP-Code]    [Backdoor Host]    [Back-Connection]    [milw0rm it!]    [PHP-Proxy]    [Self remove]
    


Viewing file:     toyvm.c (20.76 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* A simple stack-based virtual machine to demonstrate
   JIT-compilation.
   Copyright (C) 2014-2022 Free Software Foundation, Inc.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "jit-dejagnu.h"

#include <libgccjit.h>

/* Typedefs.  */
typedef struct toyvm_op toyvm_op;
typedef struct toyvm_function toyvm_function;
typedef struct toyvm_frame toyvm_frame;
typedef struct compilation_state compilation_state;
typedef struct toyvm_compiled_function toyvm_compiled_function;

/* Functions are compiled to this function ptr type.  */
typedef int (*toyvm_compiled_code) (int);

enum opcode {
  /* Ops taking no operand.  */
  DUP,
  ROT,
  BINARY_ADD,
  BINARY_SUBTRACT,
  BINARY_MULT,
  BINARY_COMPARE_LT,
  RECURSE,
  RETURN,

  /* Ops taking an operand.  */
  PUSH_CONST,
  JUMP_ABS_IF_TRUE
};

#define FIRST_UNARY_OPCODE (PUSH_CONST)

const char * const opcode_names[] = {
  "DUP",
  "ROT",
  "BINARY_ADD",
  "BINARY_SUBTRACT",
  "BINARY_MULT",
  "BINARY_COMPARE_LT",
  "RECURSE",
  "RETURN",

  "PUSH_CONST",
  "JUMP_ABS_IF_TRUE",
};

struct toyvm_op
{
  /* Which operation.  */
  enum opcode op_opcode;

  /* Some opcodes take an argument.  */
  int op_operand;

  /* The line number of the operation within the source file.  */
  int op_linenum;
};

#define MAX_OPS  (64)

struct toyvm_function
{
  const char *fn_filename;
  int         fn_num_ops;
  toyvm_op    fn_ops[MAX_OPS];
};

#define MAX_STACK_DEPTH (8)

struct toyvm_frame
{
  toyvm_function *frm_function;
  int             frm_pc;
  int             frm_stack[MAX_STACK_DEPTH];
  int             frm_cur_depth;
};

static void
add_op (toyvm_function *fn, enum opcode opcode,
    int operand, int linenum)
{
  toyvm_op *op;
  assert (fn->fn_num_ops < MAX_OPS);
  op = &fn->fn_ops[fn->fn_num_ops++];
  op->op_opcode = opcode;
  op->op_operand = operand;
  op->op_linenum = linenum;
}

static void
add_unary_op (toyvm_function *fn, enum opcode opcode,
          const char *rest_of_line, int linenum)
{
  int operand = atoi (rest_of_line);
  add_op (fn, opcode, operand, linenum);
}

static char *
get_function_name (const char *filename)
{
  /* Skip any path separators.  */
  const char *pathsep = strrchr (filename, '/');
  if (pathsep)
    filename = pathsep + 1;

  /* Copy filename to funcname.  */
  char *funcname = (char *)malloc (strlen (filename) + 1);

  strcpy (funcname, filename);

  /* Convert "." to NIL terminator.  */
  *(strchr (funcname, '.')) = '\0';

  return funcname;
}

static toyvm_function *
toyvm_function_parse (const char *filename, const char *name)
{
  FILE *f = NULL;
  toyvm_function *fn = NULL;
  char *line = NULL;
  ssize_t linelen;
  size_t bufsize;
  int linenum = 0;

  assert (filename);
  assert (name);

  f = fopen (filename, "r");
  if (!f)
    {
      fprintf (stderr,
           "cannot open file %s: %s\n",
           filename, strerror (errno));
      goto error;
    }

  fn = (toyvm_function *)calloc (1, sizeof (toyvm_function));
  if (!fn)
    {
      fprintf (stderr, "out of memory allocating toyvm_function\n");
      goto error;
    }
  fn->fn_filename = filename;

  /* Read the lines of the file.  */
  while ((linelen = getline (&line, &bufsize, f)) != -1)
    {
      /* Note that this is a terrible parser, but it avoids the need to
     bring in lex/yacc as a dependency.  */
      linenum++;

      if (0)
    fprintf (stdout, "%3d: %s", linenum, line);

      /* Lines beginning with # are comments.  */
      if (line[0] == '#')
    continue;

      /* Skip blank lines.  */
      if (line[0] == '\n')
    continue;

#define LINE_MATCHES(OPCODE) (0 == strncmp ((OPCODE), line, strlen (OPCODE)))
      if (LINE_MATCHES ("DUP\n"))
    add_op (fn, DUP, 0, linenum);
      else if (LINE_MATCHES ("ROT\n"))
    add_op (fn, ROT, 0, linenum);
      else if (LINE_MATCHES ("BINARY_ADD\n"))
    add_op (fn, BINARY_ADD, 0, linenum);
      else if (LINE_MATCHES ("BINARY_SUBTRACT\n"))
    add_op (fn, BINARY_SUBTRACT, 0, linenum);
      else if (LINE_MATCHES ("BINARY_MULT\n"))
    add_op (fn, BINARY_MULT, 0, linenum);
      else if (LINE_MATCHES ("BINARY_COMPARE_LT\n"))
    add_op (fn, BINARY_COMPARE_LT, 0, linenum);
      else if (LINE_MATCHES ("RECURSE\n"))
    add_op (fn, RECURSE, 0, linenum);
      else if (LINE_MATCHES ("RETURN\n"))
    add_op (fn, RETURN, 0, linenum);
      else if (LINE_MATCHES ("PUSH_CONST "))
    add_unary_op (fn, PUSH_CONST,
              line + strlen ("PUSH_CONST "), linenum);
      else if (LINE_MATCHES ("JUMP_ABS_IF_TRUE "))
    add_unary_op (fn, JUMP_ABS_IF_TRUE,
              line + strlen("JUMP_ABS_IF_TRUE "), linenum);
      else
    {
      fprintf (stderr, "%s:%d: parse error\n", filename, linenum);
      free (fn);
      fn = NULL;
      goto error;
    }
#undef LINE_MATCHES
    }
  free (line);
  fclose (f);

  return fn;

 error:
  free (line);
  if (f)
    fclose (f);
  free (fn);
  return NULL;
}

static void
toyvm_function_disassemble_op (toyvm_function *fn, toyvm_op *op, int index, FILE *out)
{
  fprintf (out, "%s:%d: index %d: %s",
       fn->fn_filename, op->op_linenum, index,
       opcode_names[op->op_opcode]);
  if (op->op_opcode >= FIRST_UNARY_OPCODE)
    fprintf (out, " %d", op->op_operand);
  fprintf (out, "\n");
}

static void
toyvm_function_disassemble (toyvm_function *fn, FILE *out)
{
  int i;
  for (i = 0; i < fn->fn_num_ops; i++)
    {
      toyvm_op *op = &fn->fn_ops[i];
      toyvm_function_disassemble_op (fn, op, i, out);
    }
}

static void
toyvm_frame_push (toyvm_frame *frame, int arg)
{
  assert (frame->frm_cur_depth < MAX_STACK_DEPTH);
  frame->frm_stack[frame->frm_cur_depth++] = arg;
}

static int
toyvm_frame_pop (toyvm_frame *frame)
{
  assert (frame->frm_cur_depth > 0);
  return frame->frm_stack[--frame->frm_cur_depth];
}

static void
toyvm_frame_dump_stack (toyvm_frame *frame, FILE *out)
{
  int i;
  fprintf (out, "stack:");
  for (i = 0; i < frame->frm_cur_depth; i++)
    {
      fprintf (out, " %d", frame->frm_stack[i]);
    }
  fprintf (out, "\n");
}

/* Execute the given function.  */

static int
toyvm_function_interpret (toyvm_function *fn, int arg, FILE *trace)
{
  toyvm_frame frame;
#define PUSH(ARG) (toyvm_frame_push (&frame, (ARG)))
#define POP(ARG) (toyvm_frame_pop (&frame))

  frame.frm_function = fn;
  frame.frm_pc = 0;
  frame.frm_cur_depth = 0;

  PUSH (arg);

  while (1)
    {
      toyvm_op *op;
      int x, y;
      assert (frame.frm_pc < fn->fn_num_ops);
      op = &fn->fn_ops[frame.frm_pc++];

      if (trace)
    {
      toyvm_frame_dump_stack (&frame, trace);
      toyvm_function_disassemble_op (fn, op, frame.frm_pc, trace);
    }

      switch (op->op_opcode)
    {
      /* Ops taking no operand.  */
    case DUP:
      x = POP ();
      PUSH (x);
      PUSH (x);
      break;

    case ROT:
      y = POP ();
      x = POP ();
      PUSH (y);
      PUSH (x);
      break;

    case BINARY_ADD:
      y = POP ();
      x = POP ();
      PUSH (x + y);
      break;

    case BINARY_SUBTRACT:
      y = POP ();
      x = POP ();
      PUSH (x - y);
      break;

    case BINARY_MULT:
      y = POP ();
      x = POP ();
      PUSH (x * y);
      break;

    case BINARY_COMPARE_LT:
      y = POP ();
      x = POP ();
      PUSH (x < y);
      break;

    case RECURSE:
      x = POP ();
      x = toyvm_function_interpret (fn, x, trace);
      PUSH (x);
      break;

    case RETURN:
      return POP ();

      /* Ops taking an operand.  */
    case PUSH_CONST:
      PUSH (op->op_operand);
      break;

    case JUMP_ABS_IF_TRUE:
      x = POP ();
      if (x)
        frame.frm_pc = op->op_operand;
      break;

    default:
      assert (0); /* unknown opcode */

    } /* end of switch on opcode */
    } /* end of while loop */

#undef PUSH
#undef POP
}

/* JIT compilation.  */

struct compilation_state
{
  gcc_jit_context *ctxt;

  gcc_jit_type *int_type;
  gcc_jit_type *bool_type;
  gcc_jit_type *stack_type; /* int[MAX_STACK_DEPTH] */

  gcc_jit_rvalue *const_one;

  gcc_jit_function *fn;
  gcc_jit_param *param_arg;
  gcc_jit_lvalue *stack;
  gcc_jit_lvalue *stack_depth;
  gcc_jit_lvalue *x;
  gcc_jit_lvalue *y;

  gcc_jit_location *op_locs[MAX_OPS];
  gcc_jit_block *initial_block;
  gcc_jit_block *op_blocks[MAX_OPS];

};

/* Stack manipulation.  */

static void
add_push (compilation_state *state,
      gcc_jit_block *block,
      gcc_jit_rvalue *rvalue,
      gcc_jit_location *loc)
{
  /* stack[stack_depth] = RVALUE */
  gcc_jit_block_add_assignment (
    block,
    loc,
    /* stack[stack_depth] */
    gcc_jit_context_new_array_access (
      state->ctxt,
      loc,
      gcc_jit_lvalue_as_rvalue (state->stack),
      gcc_jit_lvalue_as_rvalue (state->stack_depth)),
    rvalue);

  /* "stack_depth++;".  */
  gcc_jit_block_add_assignment_op (
    block,
    loc,
    state->stack_depth,
    GCC_JIT_BINARY_OP_PLUS,
    state->const_one);
}

static void
add_pop (compilation_state *state,
     gcc_jit_block *block,
     gcc_jit_lvalue *lvalue,
     gcc_jit_location *loc)
{
  /* "--stack_depth;".  */
  gcc_jit_block_add_assignment_op (
    block,
    loc,
    state->stack_depth,
    GCC_JIT_BINARY_OP_MINUS,
    state->const_one);

  /* "LVALUE = stack[stack_depth];".  */
  gcc_jit_block_add_assignment (
    block,
    loc,
    lvalue,
    /* stack[stack_depth] */
    gcc_jit_lvalue_as_rvalue (
      gcc_jit_context_new_array_access (
    state->ctxt,
    loc,
    gcc_jit_lvalue_as_rvalue (state->stack),
    gcc_jit_lvalue_as_rvalue (state->stack_depth))));
}

/* A struct to hold the compilation results.  */

struct toyvm_compiled_function
{
  gcc_jit_result *cf_jit_result;
  toyvm_compiled_code cf_code;
};

/* The main compilation hook.  */

static toyvm_compiled_function *
toyvm_function_compile (toyvm_function *fn)
{
  compilation_state state;
  int pc;
  char *funcname;

  memset (&state, 0, sizeof (state));

  funcname = get_function_name (fn->fn_filename);

  state.ctxt = gcc_jit_context_acquire ();

  gcc_jit_context_set_bool_option (state.ctxt,
                   GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE,
                   0);
  gcc_jit_context_set_bool_option (state.ctxt,
                   GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE,
                   0);
  gcc_jit_context_set_int_option (state.ctxt,
                  GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
                  3);
  gcc_jit_context_set_bool_option (state.ctxt,
                   GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES,
                   0);
  gcc_jit_context_set_bool_option (state.ctxt,
                   GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING,
                   0);
  gcc_jit_context_set_bool_option (state.ctxt,
                   GCC_JIT_BOOL_OPTION_DEBUGINFO,
                   1);

  /* Create types.  */
  state.int_type =
    gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_INT);
  state.bool_type =
    gcc_jit_context_get_type (state.ctxt, GCC_JIT_TYPE_BOOL);
  state.stack_type =
    gcc_jit_context_new_array_type (state.ctxt, NULL,
                    state.int_type, MAX_STACK_DEPTH);

  /* The constant value 1.  */
  state.const_one = gcc_jit_context_one (state.ctxt, state.int_type);

  /* Create locations.  */
  for (pc = 0; pc < fn->fn_num_ops; pc++)
    {
      toyvm_op *op = &fn->fn_ops[pc];

      state.op_locs[pc] = gcc_jit_context_new_location (state.ctxt,
                            fn->fn_filename,
                            op->op_linenum,
                            0); /* column */
    }

  /* Creating the function.  */
  state.param_arg =
    gcc_jit_context_new_param (state.ctxt, state.op_locs[0],
                   state.int_type, "arg");
  state.fn =
    gcc_jit_context_new_function (state.ctxt,
                  state.op_locs[0],
                  GCC_JIT_FUNCTION_EXPORTED,
                  state.int_type,
                  funcname,
                  1, &state.param_arg, 0);

  /* Create stack lvalues.  */
  state.stack =
    gcc_jit_function_new_local (state.fn, NULL,
                state.stack_type, "stack");
  state.stack_depth =
    gcc_jit_function_new_local (state.fn, NULL,
                state.int_type, "stack_depth");
  state.x =
    gcc_jit_function_new_local (state.fn, NULL,
                state.int_type, "x");
  state.y =
    gcc_jit_function_new_local (state.fn, NULL,
                state.int_type, "y");

  /* 1st pass: create blocks, one per opcode. */

  /* We need an entry block to do one-time initialization, so create that
     first.  */
  state.initial_block = gcc_jit_function_new_block (state.fn, "initial");

  /* Create a block per operation.  */
  for (pc = 0; pc < fn->fn_num_ops; pc++)
    {
      char buf[100];
      sprintf (buf, "instr%i", pc);
      state.op_blocks[pc] = gcc_jit_function_new_block (state.fn, buf);
    }

  /* Populate the initial block.  */

  /* "stack_depth = 0;".  */
  gcc_jit_block_add_assignment (
    state.initial_block,
    state.op_locs[0],
    state.stack_depth,
    gcc_jit_context_zero (state.ctxt, state.int_type));

  /* "PUSH (arg);".  */
  add_push (&state,
        state.initial_block,
        gcc_jit_param_as_rvalue (state.param_arg),
        state.op_locs[0]);

  /* ...and jump to insn 0.  */
  gcc_jit_block_end_with_jump (state.initial_block,
                   state.op_locs[0],
                   state.op_blocks[0]);

  /* 2nd pass: fill in instructions.  */
  for (pc = 0; pc < fn->fn_num_ops; pc++)
    {
      gcc_jit_location *loc = state.op_locs[pc];

      gcc_jit_block *block = state.op_blocks[pc];
      gcc_jit_block *next_block = (pc < fn->fn_num_ops
                   ? state.op_blocks[pc + 1]
                   : NULL);

      toyvm_op *op;
      op = &fn->fn_ops[pc];

      /* Helper macros.  */

#define X_EQUALS_POP()\
      add_pop (&state, block, state.x, loc)
#define Y_EQUALS_POP()\
      add_pop (&state, block, state.y, loc)
#define PUSH_RVALUE(RVALUE)\
      add_push (&state, block, (RVALUE), loc)
#define PUSH_X()\
      PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.x))
#define PUSH_Y() \
      PUSH_RVALUE (gcc_jit_lvalue_as_rvalue (state.y))

      gcc_jit_block_add_comment (block, loc, opcode_names[op->op_opcode]);

      /* Handle the individual opcodes.  */

      switch (op->op_opcode)
    {
    case DUP:
      X_EQUALS_POP ();
      PUSH_X ();
      PUSH_X ();
      break;

    case ROT:
      Y_EQUALS_POP ();
      X_EQUALS_POP ();
      PUSH_Y ();
      PUSH_X ();
      break;

    case BINARY_ADD:
      Y_EQUALS_POP ();
      X_EQUALS_POP ();
      PUSH_RVALUE (
       gcc_jit_context_new_binary_op (
         state.ctxt,
         loc,
         GCC_JIT_BINARY_OP_PLUS,
         state.int_type,
         gcc_jit_lvalue_as_rvalue (state.x),
         gcc_jit_lvalue_as_rvalue (state.y)));
      break;

    case BINARY_SUBTRACT:
      Y_EQUALS_POP ();
      X_EQUALS_POP ();
      PUSH_RVALUE (
       gcc_jit_context_new_binary_op (
         state.ctxt,
         loc,
         GCC_JIT_BINARY_OP_MINUS,
         state.int_type,
         gcc_jit_lvalue_as_rvalue (state.x),
         gcc_jit_lvalue_as_rvalue (state.y)));
      break;

    case BINARY_MULT:
      Y_EQUALS_POP ();
      X_EQUALS_POP ();
      PUSH_RVALUE (
       gcc_jit_context_new_binary_op (
         state.ctxt,
         loc,
         GCC_JIT_BINARY_OP_MULT,
         state.int_type,
         gcc_jit_lvalue_as_rvalue (state.x),
         gcc_jit_lvalue_as_rvalue (state.y)));
      break;

    case BINARY_COMPARE_LT:
      Y_EQUALS_POP ();
      X_EQUALS_POP ();
      PUSH_RVALUE (
         /* cast of bool to int */
         gcc_jit_context_new_cast (
           state.ctxt,
           loc,
           /* (x < y) as a bool */
           gcc_jit_context_new_comparison (
         state.ctxt,
         loc,
         GCC_JIT_COMPARISON_LT,
         gcc_jit_lvalue_as_rvalue (state.x),
         gcc_jit_lvalue_as_rvalue (state.y)),
           state.int_type));
      break;

    case RECURSE:
      {
        X_EQUALS_POP ();
        gcc_jit_rvalue *arg = gcc_jit_lvalue_as_rvalue (state.x);
        PUSH_RVALUE (
          gcc_jit_context_new_call (
        state.ctxt,
        loc,
        state.fn,
        1, &arg));
        break;
      }

    case RETURN:
      X_EQUALS_POP ();
      gcc_jit_block_end_with_return (
        block,
        loc,
        gcc_jit_lvalue_as_rvalue (state.x));
      break;

      /* Ops taking an operand.  */
    case PUSH_CONST:
      PUSH_RVALUE (
        gcc_jit_context_new_rvalue_from_int (
          state.ctxt,
          state.int_type,
          op->op_operand));
      break;

    case JUMP_ABS_IF_TRUE:
      X_EQUALS_POP ();
      gcc_jit_block_end_with_conditional (
        block,
        loc,
        /* "(bool)x".  */
        gcc_jit_context_new_cast (
          state.ctxt,
          loc,
          gcc_jit_lvalue_as_rvalue (state.x),
          state.bool_type),
        state.op_blocks[op->op_operand], /* on_true */
        next_block); /* on_false */
      break;

    default:
      assert(0);
    } /* end of switch on opcode */

      /* Go to the next block.  */
      if (op->op_opcode != JUMP_ABS_IF_TRUE
      && op->op_opcode != RETURN)
    gcc_jit_block_end_with_jump (
      block,
      loc,
      next_block);

    } /* end of loop on PC locations.  */

  /* We've now finished populating the context.  Compile it.  */
  gcc_jit_result *jit_result = gcc_jit_context_compile (state.ctxt);
  gcc_jit_context_release (state.ctxt);

  toyvm_compiled_function *toyvm_result =
    (toyvm_compiled_function *)calloc (1, sizeof (toyvm_compiled_function));
  if (!toyvm_result)
    {
      fprintf (stderr, "out of memory allocating toyvm_compiled_function\n");
      gcc_jit_result_release (jit_result);
      return NULL;
    }

  toyvm_result->cf_jit_result = jit_result;
  toyvm_result->cf_code =
    (toyvm_compiled_code)gcc_jit_result_get_code (jit_result,
                          funcname);

  free (funcname);

  return toyvm_result;
}

char test[1024];

#define CHECK_NON_NULL(PTR) \
  do {                                       \
    if ((PTR) != NULL)                       \
      {                                      \
    pass ("%s: %s is non-null", test, #PTR); \
      }                                      \
    else                                     \
      {                                      \
    fail ("%s: %s is NULL", test, #PTR); \
    abort ();                            \
    }                                        \
  } while (0)

#define CHECK_VALUE(ACTUAL, EXPECTED) \
  do {                                       \
    if ((ACTUAL) == (EXPECTED))              \
      {                                      \
    pass ("%s: actual: %s == expected: %s", test, #ACTUAL, #EXPECTED); \
      }                                      \
    else                                     \
      {                                        \
    fail ("%s: actual: %s != expected: %s", test, #ACTUAL, #EXPECTED); \
    fprintf (stderr, "incorrect value\n"); \
    abort ();                              \
    }                                        \
  } while (0)

static void
test_script (const char *scripts_dir, const char *script_name, int input,
         int expected_result)
{
  char *script_path;
  toyvm_function *fn;
  int interpreted_result;
  toyvm_compiled_function *compiled_fn;
  toyvm_compiled_code code;
  int compiled_result;

  snprintf (test, sizeof (test), "toyvm.c: %s", script_name);

  script_path = (char *)malloc (strlen (scripts_dir)
                + strlen (script_name) + 1);
  CHECK_NON_NULL (script_path);
  sprintf (script_path, "%s%s", scripts_dir, script_name);

  fn = toyvm_function_parse (script_path, script_name);
  CHECK_NON_NULL (fn);

  interpreted_result = toyvm_function_interpret (fn, input, NULL);
  CHECK_VALUE (interpreted_result, expected_result);

  compiled_fn = toyvm_function_compile (fn);
  CHECK_NON_NULL (compiled_fn);

  code = (toyvm_compiled_code)compiled_fn->cf_code;
  CHECK_NON_NULL (code);

  compiled_result = code (input);
  CHECK_VALUE (compiled_result, expected_result);

  gcc_jit_result_release (compiled_fn->cf_jit_result);
  free (compiled_fn);
  free (fn);
  free (script_path);
}

#define PATH_TO_SCRIPTS  ("/jit/docs/examples/tut04-toyvm/")

static void
test_suite (void)
{
  const char *srcdir;
  char *scripts_dir;

  snprintf (test, sizeof (test), "toyvm.c");

  /* We need to locate the test scripts.
     Rely on "srcdir" being set in the environment.  */

  srcdir = getenv ("srcdir");
  CHECK_NON_NULL (srcdir);

  scripts_dir = (char *)malloc (strlen (srcdir) + strlen(PATH_TO_SCRIPTS)
                + 1);
  CHECK_NON_NULL (scripts_dir);
  sprintf (scripts_dir, "%s%s", srcdir, PATH_TO_SCRIPTS);

  test_script (scripts_dir, "factorial.toy", 10, 3628800);
  test_script (scripts_dir, "fibonacci.toy", 10, 55);

  free (scripts_dir);
}

int
main (int argc, char **argv)
{
  const char *filename = NULL;
  toyvm_function *fn = NULL;

  /* If called with no args, assume we're being run by the test suite.  */
  if (argc < 3)
    {
      test_suite ();
      return 0;
    }

  if (argc != 3)
    {
      fprintf (stdout,
    "%s FILENAME INPUT: Parse and run a .toy file\n",
    argv[0]);
      exit (1);
    }

  filename = argv[1];
  fn = toyvm_function_parse (filename, filename);
  if (!fn)
    exit (1);

  if (0)
    toyvm_function_disassemble (fn, stdout);

  printf ("interpreter result: %d\n",
      toyvm_function_interpret (fn, atoi (argv[2]), NULL));

  /* JIT-compilation.  */
  toyvm_compiled_function *compiled_fn
    = toyvm_function_compile (fn);

  toyvm_compiled_code code = compiled_fn->cf_code;
  printf ("compiler result: %d\n",
      code (atoi (argv[2])));

  gcc_jit_result_release (compiled_fn->cf_jit_result);
  free (compiled_fn);

 return 0;
}

Enter:
 
Select:
 

Useful Commands
 
Warning. Kernel may be alerted using higher levels
Kernel Info:

Php Safe-Mode Bypass (Read Files)

File:

eg: /etc/passwd

Php Safe-Mode Bypass (List Directories):

Dir:

eg: /etc/

Search
  - regexp 

Upload
 
[ ok ]

Make Dir
 
[ ok ]
Make File
 
[ ok ]

Go Dir
 
Go File
 

--[ x2300 Locus7Shell v. 1.0a beta Modded by #!physx^ | www.LOCUS7S.com | Generation time: 0.0074 ]--