diff options
author | David Schleef <ds@schleef.org> | 2012-01-28 14:18:11 -0800 |
---|---|---|
committer | David Schleef <ds@schleef.org> | 2012-01-28 14:18:11 -0800 |
commit | 34139bfbb286829b469825e01664c3d34058f63b (patch) | |
tree | 63ef4d29b6b68f327c0195d21aa21a2bdf3f9508 | |
parent | 31c75253f3299f5af62970d3a3093201d726bfbf (diff) | |
download | orc-34139bfbb286829b469825e01664c3d34058f63b.tar.gz |
bytecode: Add bytecode parsing
-rw-r--r-- | orc/orcbytecode.c | 208 | ||||
-rw-r--r-- | orc/orcprogram.c | 11 | ||||
-rw-r--r-- | orc/orcprogram.h | 2 | ||||
-rw-r--r-- | tools/orcc.c | 66 |
4 files changed, 287 insertions, 0 deletions
diff --git a/orc/orcbytecode.c b/orc/orcbytecode.c index 14a12dc..0d86373 100644 --- a/orc/orcbytecode.c +++ b/orc/orcbytecode.c @@ -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++; + } + } +} + diff --git a/orc/orcprogram.c b/orc/orcprogram.c index 0e158fc..05a0baa 100644 --- a/orc/orcprogram.c +++ b/orc/orcprogram.c @@ -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 diff --git a/orc/orcprogram.h b/orc/orcprogram.h index d34b039..aa15fac 100644 --- a/orc/orcprogram.h +++ b/orc/orcprogram.h @@ -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 diff --git a/tools/orcc.c b/tools/orcc.c index e90bdeb..465d464 100644 --- a/tools/orcc.c +++ b/tools/orcc.c @@ -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 |