#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include void bytecode_append_code (OrcBytecode *bytecode, int code); void bytecode_append_int (OrcBytecode *bytecode, int value); void bytecode_append_uint32 (OrcBytecode *bytecode, orc_uint32 value); void bytecode_append_uint64 (OrcBytecode *bytecode, orc_uint64 value); void bytecode_append_string (OrcBytecode *bytecode, char *s); OrcBytecode * orc_bytecode_new (void) { OrcBytecode *bytecode; bytecode = malloc (sizeof(OrcBytecode)); memset (bytecode, 0, sizeof(OrcBytecode)); bytecode->alloc_len = 256; bytecode->bytecode = malloc(bytecode->alloc_len); return bytecode; } void orc_bytecode_free (OrcBytecode *bytecode) { free (bytecode->bytecode); free (bytecode); } OrcBytecode * orc_bytecode_from_program (OrcProgram *p) { OrcBytecode *bytecode = orc_bytecode_new (); int i; OrcVariable *var; OrcOpcodeSet *opcode_set; opcode_set = orc_opcode_set_get ("sys"); bytecode_append_code (bytecode, ORC_BC_BEGIN_FUNCTION); if (p->constant_n != 0) { bytecode_append_code (bytecode, ORC_BC_SET_CONSTANT_N); bytecode_append_int (bytecode, p->constant_n); } if (p->n_multiple != 0) { bytecode_append_code (bytecode, ORC_BC_SET_N_MULTIPLE); bytecode_append_int (bytecode, p->n_multiple); } if (p->n_minimum != 0) { bytecode_append_code (bytecode, ORC_BC_SET_N_MINIMUM); bytecode_append_int (bytecode, p->n_minimum); } if (p->n_maximum != 0) { bytecode_append_code (bytecode, ORC_BC_SET_N_MAXIMUM); bytecode_append_int (bytecode, p->n_maximum); } if (p->is_2d) { bytecode_append_code (bytecode, ORC_BC_SET_2D); if (p->constant_m != 0) { bytecode_append_code (bytecode, ORC_BC_SET_CONSTANT_M); bytecode_append_int (bytecode, p->constant_m); } } if (p->name) { bytecode_append_code (bytecode, ORC_BC_SET_NAME); bytecode_append_string (bytecode, p->name); } #if 0 /* if (!is_inline) { */ if (p->backup_function) { bytecode_append_code (bytecode, ORC_BC_SET_BACKUP_FUNCTION); bytecode_pointer (bytecode, p->backup_function); } #endif for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { bytecode_append_code (bytecode, ORC_BC_ADD_DESTINATION); bytecode_append_int (bytecode, var->size); bytecode_append_int (bytecode, var->alignment); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { bytecode_append_code (bytecode, ORC_BC_ADD_SOURCE); bytecode_append_int (bytecode, var->size); bytecode_append_int (bytecode, var->alignment); } } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_A1 + i]; if (var->size) { bytecode_append_code (bytecode, ORC_BC_ADD_ACCUMULATOR); bytecode_append_int (bytecode, var->size); /* bytecode_append_int (bytecode, var->alignment); */ } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_C1 + i]; if (var->size == 0) continue; if (var->size <= 4) { bytecode_append_code (bytecode, ORC_BC_ADD_CONSTANT); bytecode_append_int (bytecode, var->size); bytecode_append_uint32 (bytecode, (orc_uint32)var->value.i); } else if (var->size > 4) { bytecode_append_code (bytecode, ORC_BC_ADD_CONSTANT_INT64); bytecode_append_int (bytecode, var->size); bytecode_append_uint64 (bytecode, (orc_uint64)var->value.i); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_P1 + i]; if (var->size) { switch (var->param_type) { case ORC_PARAM_TYPE_INT: bytecode_append_code (bytecode, ORC_BC_ADD_PARAMETER); break; case ORC_PARAM_TYPE_FLOAT: bytecode_append_code (bytecode, ORC_BC_ADD_PARAMETER_FLOAT); break; case ORC_PARAM_TYPE_INT64: bytecode_append_code (bytecode, ORC_BC_ADD_PARAMETER_INT64); break; case ORC_PARAM_TYPE_DOUBLE: bytecode_append_code (bytecode, ORC_BC_ADD_PARAMETER_INT64); break; default: ORC_ASSERT(0); break; } bytecode_append_int (bytecode, var->size); } } for(i=0;i<16;i++){ var = &p->vars[ORC_VAR_T1 + i]; if (var->size) { bytecode_append_code (bytecode, ORC_BC_ADD_TEMPORARY); bytecode_append_int (bytecode, var->size); } } for(i=0;in_insns;i++){ OrcInstruction *insn = p->insns + i; if (insn->flags) { bytecode_append_code (bytecode, ORC_BC_INSTRUCTION_FLAGS); bytecode_append_int (bytecode, insn->flags); } bytecode_append_code (bytecode, (insn->opcode - opcode_set->opcodes) + 32); if (insn->opcode->dest_size[0] != 0) { bytecode_append_int (bytecode, insn->dest_args[0]); } if (insn->opcode->dest_size[1] != 0) { bytecode_append_int (bytecode, insn->dest_args[1]); } if (insn->opcode->src_size[0] != 0) { bytecode_append_int (bytecode, insn->src_args[0]); } if (insn->opcode->src_size[1] != 0) { bytecode_append_int (bytecode, insn->src_args[1]); } if (insn->opcode->src_size[2] != 0) { bytecode_append_int (bytecode, insn->src_args[2]); } } bytecode_append_code (bytecode, ORC_BC_END_FUNCTION); bytecode_append_code (bytecode, ORC_BC_END); return bytecode; } void bytecode_append_byte (OrcBytecode *bytecode, int byte) { if (bytecode->length >= bytecode->alloc_len) { bytecode->alloc_len += 256; bytecode->bytecode = realloc (bytecode->bytecode, bytecode->alloc_len); } bytecode->bytecode[bytecode->length] = byte; bytecode->length++; } void bytecode_append_code (OrcBytecode *bytecode, int code) { bytecode_append_byte (bytecode, code); #if 0 OrcOpcodeSet *opcode_set = orc_opcode_set_get ("sys"); fprintf(bytecode, "\n "); if (code >= 32) { fprintf(bytecode, "ORC_BC_%s, ", opcode_set->opcodes[code-32].name); } else { static char *codes[32] = { "END", "BEGIN_FUNCTION", "END_FUNCTION", "SET_CONSTANT_N", "SET_N_MULTIPLE", "SET_N_MINIMUM", "SET_N_MAXIMUM", "SET_2D", "SET_CONSTANT_M", "SET_NAME", "SET_BACKUP_FUNCTION", "ADD_DESTINATION", "ADD_SOURCE", "ADD_ACCUMULATOR", "ADD_CONSTANT", "ADD_CONSTANT_INT64", "ADD_PARAMETER", "ADD_PARAMETER_FLOAT", "ADD_PARAMETER_INT64", "ADD_PARAMETER_DOUBLE", "ADD_TEMPORARY", "RESERVED_21", "RESERVED_22", "RESERVED_23", "RESERVED_24", "RESERVED_25", "RESERVED_26", "RESERVED_27", "RESERVED_28", "RESERVED_29", "RESERVED_30", "RESERVED_31" }; fprintf(bytecode, "ORC_BC_%s, ", codes[code]); } #endif } void bytecode_append_int (OrcBytecode *bytecode, int value) { ORC_ASSERT(value >= 0); if (value < 255) { bytecode_append_byte (bytecode, value); } else if (value < 65535) { bytecode_append_byte (bytecode, 255); bytecode_append_byte (bytecode, value & 0xff); bytecode_append_byte (bytecode, value >> 8); } else { ORC_ASSERT(0); } } void bytecode_append_uint32 (OrcBytecode *bytecode, orc_uint32 value) { bytecode_append_byte (bytecode, value & 0xff); bytecode_append_byte (bytecode, (value >> 8) & 0xff); bytecode_append_byte (bytecode, (value >> 16) & 0xff); bytecode_append_byte (bytecode, (value >> 24) & 0xff); } void bytecode_append_uint64 (OrcBytecode *bytecode, orc_uint64 value) { bytecode_append_byte (bytecode, value & 0xff); bytecode_append_byte (bytecode, (value >> 8) & 0xff); bytecode_append_byte (bytecode, (value >> 16) & 0xff); bytecode_append_byte (bytecode, (value >> 24) & 0xff); bytecode_append_byte (bytecode, (value >> 32) & 0xff); bytecode_append_byte (bytecode, (value >> 40) & 0xff); bytecode_append_byte (bytecode, (value >> 48) & 0xff); bytecode_append_byte (bytecode, (value >> 56) & 0xff); } void bytecode_append_string (OrcBytecode *bytecode, char *s) { int i; int len = strlen(s); bytecode_append_int (bytecode, len); for(i=0;ibytecode[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;ibytecode = 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: if (program->name) { free (program->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; case ORC_BC_INSTRUCTION_FLAGS: instruction_flags = orc_bytecode_parse_get_int (parse); 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); } insn->flags = instruction_flags; instruction_flags = 0; program->n_insns++; } } }