bytecode: Add bytecode parsing
authorDavid Schleef <ds@schleef.org>
Sat, 28 Jan 2012 22:18:11 +0000 (14:18 -0800)
committerDavid Schleef <ds@schleef.org>
Sat, 28 Jan 2012 22:18:11 +0000 (14:18 -0800)
orc/orcbytecode.c
orc/orcprogram.c
orc/orcprogram.h
tools/orcc.c

index 14a12dc..0d86373 100644 (file)
@@ -292,3 +292,211 @@ bytecode_append_string (OrcBytecode *bytecode, char *s)
   }
 }
 
+typedef struct _OrcBytecodeParse OrcBytecodeParse;
+struct _OrcBytecodeParse {
+  const orc_uint8 *bytecode;
+  int parse_offset;
+  int function_start;
+  int code_start;
+};
+
+int
+orc_bytecode_parse_get_byte (OrcBytecodeParse *parse)
+{
+  int value;
+  value = parse->bytecode[parse->parse_offset];
+  parse->parse_offset++;
+  return value;
+}
+
+int
+orc_bytecode_parse_get_int (OrcBytecodeParse *parse)
+{
+  int value;
+
+  value = orc_bytecode_parse_get_byte(parse);
+  if (value == 255) {
+    value = orc_bytecode_parse_get_byte(parse);
+    value |= orc_bytecode_parse_get_byte(parse) << 8;
+  }
+
+  return value;
+}
+
+char *
+orc_bytecode_parse_get_string (OrcBytecodeParse *parse)
+{
+  int len;
+  int i;
+  char *s;
+
+  len = orc_bytecode_parse_get_int (parse);
+  s = malloc (len + 1);
+  for(i=0;i<len;i++){
+    s[i] = orc_bytecode_parse_get_byte (parse);
+  }
+  s[i] = 0;
+
+  return s;
+}
+
+orc_uint32
+orc_bytecode_parse_get_uint32 (OrcBytecodeParse *parse)
+{
+  orc_uint32 value;
+  value = orc_bytecode_parse_get_byte (parse);
+  value |= orc_bytecode_parse_get_byte (parse) << 8;
+  value |= orc_bytecode_parse_get_byte (parse) << 16;
+  value |= orc_bytecode_parse_get_byte (parse) << 24;
+  return value;
+}
+
+orc_uint64
+orc_bytecode_parse_get_uint64 (OrcBytecodeParse *parse)
+{
+  orc_uint64 value;
+  value = orc_bytecode_parse_get_byte (parse);
+  value |= orc_bytecode_parse_get_byte (parse) << 8;
+  value |= orc_bytecode_parse_get_byte (parse) << 16;
+  value |= orc_bytecode_parse_get_byte (parse) << 24;
+  value |= (orc_uint64)orc_bytecode_parse_get_byte (parse) << 32;
+  value |= (orc_uint64)orc_bytecode_parse_get_byte (parse) << 40;
+  value |= (orc_uint64)orc_bytecode_parse_get_byte (parse) << 48;
+  value |= (orc_uint64)orc_bytecode_parse_get_byte (parse) << 56;
+  return value;
+}
+
+int
+orc_bytecode_parse_function (OrcProgram *program, const orc_uint8 *bytecode)
+{
+  OrcBytecodeParse _parse;
+  OrcBytecodeParse *parse = &_parse;
+  //int in_function = FALSE;
+  int bc;
+  int size;
+  int alignment;
+  OrcOpcodeSet *opcode_set;
+
+  memset (parse, 0, sizeof(*parse));
+  parse->bytecode = bytecode;
+
+  opcode_set = orc_opcode_set_get ("sys");
+
+  while (1) {
+    bc = orc_bytecode_parse_get_int (parse);
+    if (bc < ORC_BC_absb) {
+      switch (bc) {
+        case ORC_BC_END:
+          /* FIXME this is technically an error */
+          return 0;
+        case ORC_BC_BEGIN_FUNCTION:
+          //in_function = TRUE;
+          break;
+        case ORC_BC_END_FUNCTION:
+          return 0;
+        case ORC_BC_SET_CONSTANT_N:
+          program->constant_n = orc_bytecode_parse_get_int (parse);
+          break;
+        case ORC_BC_SET_N_MULTIPLE:
+          program->n_multiple = orc_bytecode_parse_get_int (parse);
+          break;
+        case ORC_BC_SET_N_MINIMUM:
+          program->n_minimum = orc_bytecode_parse_get_int (parse);
+          break;
+        case ORC_BC_SET_N_MAXIMUM:
+          program->n_maximum = orc_bytecode_parse_get_int (parse);
+          break;
+        case ORC_BC_SET_2D:
+          program->is_2d = TRUE;
+          break;
+        case ORC_BC_SET_CONSTANT_M:
+          program->constant_m = orc_bytecode_parse_get_int (parse);
+          break;
+        case ORC_BC_SET_NAME:
+          program->name = orc_bytecode_parse_get_string (parse);
+          break;
+        case ORC_BC_SET_BACKUP_FUNCTION:
+          /* FIXME error */
+          break;
+        case ORC_BC_ADD_DESTINATION:
+          size = orc_bytecode_parse_get_int (parse);
+          alignment = orc_bytecode_parse_get_int (parse);
+          orc_program_add_destination_full (program, size, "d", "unknown",
+              alignment);
+          break;
+        case ORC_BC_ADD_SOURCE:
+          size = orc_bytecode_parse_get_int (parse);
+          alignment = orc_bytecode_parse_get_int (parse);
+          orc_program_add_source_full (program, size, "s", "unknown",
+              alignment);
+          break;
+        case ORC_BC_ADD_ACCUMULATOR:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_accumulator (program, size, "a");
+          break;
+        case ORC_BC_ADD_CONSTANT:
+          {
+            orc_uint32 value;
+            size = orc_bytecode_parse_get_int (parse);
+            value = orc_bytecode_parse_get_uint32 (parse);
+            orc_program_add_constant (program, size, value, "c");
+          }
+          break;
+        case ORC_BC_ADD_CONSTANT_INT64:
+          {
+            orc_uint64 value;
+            size = orc_bytecode_parse_get_int (parse);
+            value = orc_bytecode_parse_get_uint64 (parse);
+            orc_program_add_constant_int64 (program, size, value, "c");
+          }
+          break;
+        case ORC_BC_ADD_PARAMETER:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_parameter (program, size, "p");
+          break;
+        case ORC_BC_ADD_PARAMETER_FLOAT:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_parameter_float (program, size, "p");
+          break;
+        case ORC_BC_ADD_PARAMETER_INT64:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_parameter_int64 (program, size, "p");
+          break;
+        case ORC_BC_ADD_PARAMETER_DOUBLE:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_parameter_double (program, size, "p");
+          break;
+        case ORC_BC_ADD_TEMPORARY:
+          size = orc_bytecode_parse_get_int (parse);
+          orc_program_add_temporary (program, size, "t");
+          break;
+        default:
+          break;
+      }
+    } else {
+      OrcInstruction *insn;
+
+      insn = program->insns + program->n_insns;
+
+      insn->opcode = opcode_set->opcodes + (bc - 32);
+      if (insn->opcode->dest_size[0] != 0) {
+        insn->dest_args[0] = orc_bytecode_parse_get_int (parse);
+      }
+      if (insn->opcode->dest_size[1] != 0) {
+        insn->dest_args[1] = orc_bytecode_parse_get_int (parse);
+      }
+      if (insn->opcode->src_size[0] != 0) {
+        insn->src_args[0] = orc_bytecode_parse_get_int (parse);
+      }
+      if (insn->opcode->src_size[1] != 0) {
+        insn->src_args[1] = orc_bytecode_parse_get_int (parse);
+      }
+      if (insn->opcode->src_size[2] != 0) {
+        insn->src_args[2] = orc_bytecode_parse_get_int (parse);
+      }
+
+      program->n_insns++;
+    }
+  }
+}
+
index 0e158fc..05a0baa 100644 (file)
@@ -136,6 +136,17 @@ orc_program_new_as (int size1, int size2)
   return p;
 }
 
+OrcProgram *
+orc_program_new_from_static_bytecode (const orc_uint8 *bytecode)
+{
+  OrcProgram *p;
+
+  p = orc_program_new ();
+  orc_bytecode_parse_function (p, bytecode);
+
+  return p;
+}
+
 /**
  * orc_program_free:
  * @program: a pointer to an OrcProgram structure
index d34b039..aa15fac 100644 (file)
@@ -646,6 +646,7 @@ OrcProgram * orc_program_new_ds (int size1, int size2);
 OrcProgram * orc_program_new_dss (int size1, int size2, int size3);
 OrcProgram * orc_program_new_as (int size1, int size2);
 OrcProgram * orc_program_new_ass (int size1, int size2, int size3);
+OrcProgram * orc_program_new_from_static_bytecode (const orc_uint8 *bytecode);
 OrcStaticOpcode * orc_opcode_find_by_name (const char *name);
 void orc_opcode_init (void);
 
@@ -808,6 +809,7 @@ void orc_code_chunk_free (OrcCodeChunk *chunk);
 OrcBytecode * orc_bytecode_new (void);
 void orc_bytecode_free (OrcBytecode *bytecode);
 OrcBytecode * orc_bytecode_from_program (OrcProgram *p);
+int orc_bytecode_parse_function (OrcProgram *program, const orc_uint8 *bytecode);
 
 
 #endif
index e90bdeb..465d464 100644 (file)
@@ -1,8 +1,11 @@
 
 #include "config.h"
 
+#define ORC_ENABLE_UNSTABLE_API
+
 #include <orc/orc.h>
 #include <orc/orcparse.h>
+#include <orc/orcbytecode.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -858,6 +861,65 @@ output_program_generation (OrcProgram *p, FILE *output, int is_inline)
   OrcVariable *var;
   int i;
 
+  if (ORC_VERSION(0,4,16,1) <= compat) {
+    OrcBytecode *bytecode;
+    int i;
+
+    bytecode = orc_bytecode_from_program (p);
+
+    fprintf(output, "#if 1\n");
+    //fprintf(output, "#ifdef bytecode\n");
+    fprintf(output, "    static const orc_uint8 bc[] = {\n");
+    for(i=0;i<bytecode->length;i++) {
+      if ((i&0xf) == 0) {
+        fprintf(output, "      ");
+      }
+      fprintf(output, "%d, ", bytecode->bytecode[i]);
+      if ((i&0xf) == 15) {
+        fprintf(output, "\n");
+      }
+    }
+    if ((i&0xf) != 15) {
+      fprintf(output, "\n");
+    }
+    fprintf(output, "    };\n");
+    fprintf(output, "    p = orc_program_new_from_static_bytecode (bc);\n");
+    //fprintf(output, "   orc_program_set_name (p, \"%s\");\n", p->name);
+    if (!is_inline) {
+      fprintf(output, "    orc_program_set_backup_function (p, _backup_%s);\n",
+          p->name);
+    }
+
+#if 0
+    /* CHECK */
+    {
+      OrcProgram *p2 = orc_program_new_from_static_bytecode (bytecode->bytecode);
+      OrcBytecode *bytecode2 = bytecode2 = orc_bytecode_from_program (p2);
+
+      fprintf(output, "#ifdef badbytecode\n");
+      fprintf(output, "    static const orc_uint8 bc[] = {\n");
+      for(i=0;i<bytecode2->length;i++) {
+        if ((i&0xf) == 0) {
+          fprintf(output, "      ");
+        }
+        fprintf(output, "%s%d, ",
+            (bytecode->bytecode[i] == bytecode2->bytecode[i]) ? "" : "/* */",
+            bytecode2->bytecode[i]);
+        if ((i&0xf) == 15) {
+          fprintf(output, "\n");
+        }
+      }
+      if ((i&0xf) != 15) {
+        fprintf(output, "\n");
+      }
+      fprintf(output, "    };\n");
+      fprintf(output, "#endif\n");
+    }
+#endif
+
+    fprintf(output, "#else\n");
+  }
+
   fprintf(output, "      p = orc_program_new ();\n");
   if (p->constant_n != 0) {
     fprintf(output, "      orc_program_set_constant_n (p, %d);\n",
@@ -1016,6 +1078,10 @@ output_program_generation (OrcProgram *p, FILE *output, int is_inline)
           enumnames[args[3]]);
     }
   }
+
+  if (ORC_VERSION(0,4,16,1) <= compat) {
+    fprintf(output, "#endif\n");
+  }
 }
 
 void