#include "config.h" #include #include #include #include #include #include #include #include #include /** * SECTION:orcprogram * @title: OrcProgram * @short_description: Creating and manipulating Orc programs */ /** * orc_program_new: * * Create a new OrcProgram. The program should be freed using * @orc_program_free(). * * Returns: a pointer to an OrcProgram structure */ OrcProgram * orc_program_new (void) { OrcProgram *p; orc_init (); p = malloc(sizeof(OrcProgram)); memset (p, 0, sizeof(OrcProgram)); p->name = malloc (40); sprintf(p->name, "func_%p", p); return p; } /** * orc_program_new_dss: * @size1: size of destination array members * @size2: size of first source array members * @size3: size of second source array members * * Create a new OrcProgram, with a destination named "d1" and * two sources named "s1" and "s2". * * Returns: a pointer to an OrcProgram structure */ OrcProgram * orc_program_new_dss (int size1, int size2, int size3) { OrcProgram *p; p = orc_program_new (); orc_program_add_destination (p, size1, "d1"); orc_program_add_source (p, size2, "s1"); orc_program_add_source (p, size3, "s2"); return p; } /** * orc_program_new_ds: * @size1: size of destination array members * @size2: size of source array members * * Create a new OrcProgram, with a destination named "d1" and * one source named "s1". * * Returns: a pointer to an OrcProgram structure */ OrcProgram * orc_program_new_ds (int size1, int size2) { OrcProgram *p; p = orc_program_new (); orc_program_add_destination (p, size1, "d1"); orc_program_add_source (p, size2, "s1"); return p; } /** * orc_program_new_ass: * @size1: size of destination array members * @size2: size of first source array members * @size3: size of second source array members * * Create a new OrcProgram, with an accumulator named "a1" and * two source named "s1" and "s2". * * Returns: a pointer to an OrcProgram structure */ OrcProgram * orc_program_new_ass (int size1, int size2, int size3) { OrcProgram *p; p = orc_program_new (); orc_program_add_accumulator (p, size1, "a1"); orc_program_add_source (p, size2, "s1"); orc_program_add_source (p, size3, "s2"); return p; } /** * orc_program_new_as: * @size1: size of destination array members * @size2: size of source array members * * Create a new OrcProgram, with an accumulator named "a1" and * one source named "s1". * * Returns: a pointer to an OrcProgram structure */ OrcProgram * orc_program_new_as (int size1, int size2) { OrcProgram *p; p = orc_program_new (); orc_program_add_accumulator (p, size1, "a1"); orc_program_add_source (p, size2, "s1"); 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 * * Frees an OrcProgram. */ void orc_program_free (OrcProgram *program) { int i; for(i=0;ivars[i].name) { free (program->vars[i].name); program->vars[i].name = NULL; } if (program->vars[i].type_name) { free (program->vars[i].type_name); program->vars[i].type_name = NULL; } } if (program->asm_code) { free (program->asm_code); program->asm_code = NULL; } if (program->orccode) { orc_code_free (program->orccode); program->orccode = NULL; } if (program->init_function) { free (program->init_function); program->init_function = NULL; } if (program->backup_name) { free (program->backup_name); program->backup_name = NULL; } if (program->name) { free (program->name); program->name = NULL; } if (program->error_msg) { free (program->error_msg); program->error_msg = NULL; } free (program); } /** * orc_program_set_name: * @program: a pointer to an OrcProgram structure * @name: string to set the name to * * Sets the name of the program. The string is copied. */ void orc_program_set_name (OrcProgram *program, const char *name) { if (program->name) { free (program->name); } program->name = strdup (name); } /** * orc_program_set_line: * @program: a pointer to an OrcProgram structure * @name: define where we are in the source * * Sets the current line of the program. */ void orc_program_set_line (OrcProgram *program, unsigned int line) { program->current_line = line; } /** * orc_program_set_2d: * @program: a pointer to an OrcProgram structure * * Sets a flag on the program indicating that arrays are two * dimensional. This causes the compiler to generate code for * an OrcExec2D executor. */ void orc_program_set_2d (OrcProgram *program) { program->is_2d = TRUE; } void orc_program_set_constant_n (OrcProgram *program, int n) { program->constant_n = n; } void orc_program_set_n_multiple (OrcProgram *program, int n) { program->n_multiple = n; } void orc_program_set_n_minimum (OrcProgram *program, int n) { program->n_minimum = n; } void orc_program_set_n_maximum (OrcProgram *program, int n) { program->n_maximum = n; } void orc_program_set_constant_m (OrcProgram *program, int m) { program->constant_m = m; } /** * orc_program_set_backup_function: * @program: a pointer to an OrcProgram structure * @func: a function that performs the operations in the program * * Normally, if a program cannot be compiled for a particular CPU, * Orc will emulate the function, which is typically very slow. This * function allows the developer to provide a function that is called * instead of resorting to emulation. */ void orc_program_set_backup_function (OrcProgram *program, OrcExecutorFunc func) { program->backup_func = func; if (program->code_exec == NULL) { program->code_exec = func; } } /** * orc_program_set_backup_name: * @program: a pointer to an OrcProgram structure * @name: a function name that performs the operations in the program */ void orc_program_set_backup_name (OrcProgram *program, const char *name) { if (program->backup_name) free (program->backup_name); program->backup_name = strdup (name); } /** * orc_program_get_name: * @program: a pointer to an OrcProgram structure * * Gets the name of the program. The string is valid until the name * is changed or the program is freed. * * Returns: a character string */ const char * orc_program_get_name (OrcProgram *program) { return program->name; } /** * orc_program_add_temporary: * @program: a pointer to an OrcProgram structure * @size: size of data values * @name: name of variable * * Creates a new variable holding temporary values. * * Returns: the index of the new variable */ int orc_program_add_temporary (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_T1 + program->n_temp_vars; if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) { orc_program_set_error (program, "too many temporary variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_TEMP; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_temp_vars++; return i; } /** * orc_program_dup_temporary: * @program: a pointer to an OrcProgram structure * @var: variable to duplicate * @j: index * * Internal function. * * Returns: the index of the new variable */ int orc_program_dup_temporary (OrcProgram *program, int var, int j) { int i = ORC_VAR_T1 + program->n_temp_vars; if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) { orc_program_set_error (program, "too many temporary variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_TEMP; program->vars[i].size = program->vars[var].size; program->vars[i].name = malloc (strlen(program->vars[var].name) + 10); sprintf(program->vars[i].name, "%s.dup%d", program->vars[var].name, j); program->n_temp_vars++; return i; } /** * orc_program_add_source_full: * @program: a pointer to an OrcProgram structure * @size: size of data values * @name: name of variable * @type_name: name of type, or NULL * @alignment: alignment in bytes, or 0 * * Creates a new variable representing a source array. * * Returns: the index of the new variable */ int orc_program_add_source_full (OrcProgram *program, int size, const char *name, const char *type_name, int alignment) { int i = ORC_VAR_S1 + program->n_src_vars; if (program->n_src_vars >= ORC_MAX_SRC_VARS) { orc_program_set_error (program, "too many source variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_SRC; program->vars[i].size = size; if (alignment == 0) alignment = size; program->vars[i].alignment = alignment; program->vars[i].name = strdup(name); if (type_name) { program->vars[i].type_name = strdup(type_name); } program->n_src_vars++; return i; } /** * orc_program_add_source: * @program: a pointer to an OrcProgram structure * @size: size of data values * @name: name of variable * * Creates a new variable representing a source array. * * Returns: the index of the new variable */ int orc_program_add_source (OrcProgram *program, int size, const char *name) { return orc_program_add_source_full (program, size, name, NULL, 0); } /** * orc_program_add_destination_full: * @program: a pointer to an OrcProgram structure * @size: size of data values * @name: name of variable * * Creates a new variable representing a destination array. * * Returns: the index of the new variable */ int orc_program_add_destination_full (OrcProgram *program, int size, const char *name, const char *type_name, int alignment) { int i = ORC_VAR_D1 + program->n_dest_vars; if (program->n_dest_vars >= ORC_MAX_DEST_VARS) { orc_program_set_error (program, "too many destination variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_DEST; program->vars[i].size = size; if (alignment == 0) alignment = size; program->vars[i].alignment = alignment; program->vars[i].name = strdup(name); if (type_name) { program->vars[i].type_name = strdup(type_name); } program->n_dest_vars++; return i; } /** * orc_program_add_destination: * @program: a pointer to an OrcProgram structure * @size: size of data values * @name: name of variable * * Creates a new variable representing a destination array. * * Returns: the index of the new variable */ int orc_program_add_destination (OrcProgram *program, int size, const char *name) { return orc_program_add_destination_full (program, size, name, NULL, 0); } /** * orc_program_add_constant: * @program: a pointer to an OrcProgram structure * @size: size of data value * @value: the value * @name: name of variable * * Creates a new variable representing a constant value. * * Returns: the index of the new variable */ int orc_program_add_constant (OrcProgram *program, int size, int value, const char *name) { int i; i = ORC_VAR_C1 + program->n_const_vars; if (program->n_const_vars >= ORC_MAX_CONST_VARS) { orc_program_set_error (program, "too many constants allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_CONST; program->vars[i].size = size; program->vars[i].value.i = value; program->vars[i].name = strdup(name); program->n_const_vars++; return i; } int orc_program_add_constant_int64 (OrcProgram *program, int size, orc_int64 value, const char *name) { int i; i = ORC_VAR_C1 + program->n_const_vars; if (program->n_const_vars >= ORC_MAX_CONST_VARS) { orc_program_set_error (program, "too many constants allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_CONST; program->vars[i].size = size; program->vars[i].value.i = value; program->vars[i].name = strdup(name); program->n_const_vars++; return i; } int orc_program_add_constant_float (OrcProgram *program, int size, float value, const char *name) { orc_union32 u; u.f = value; return orc_program_add_constant (program, size, u.i, name); } int orc_program_add_constant_double (OrcProgram *program, int size, double value, const char *name) { orc_union64 u; u.f = value; return orc_program_add_constant_int64 (program, size, u.i, name); } int orc_program_add_constant_str (OrcProgram *program, int size, const char *value, const char *name) { int i; char *end; orc_int64 val_i; double val_d; int j; i = ORC_VAR_C1 + program->n_const_vars; if (program->n_const_vars >= ORC_MAX_CONST_VARS) { orc_program_set_error (program, "too many constants allocated"); return 0; } val_i = _strtoll (value, &end, 0); if (end[0] == 0) { program->vars[i].value.i = val_i; if (size == 0) size = 4; } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) { program->vars[i].value.i = val_i; if (size == 0) size = 8; } else { val_d = strtod (value, &end); if (end[0] == 0) { orc_union32 u; u.f = val_d; program->vars[i].value.i = u.i; if (size == 0) size = 4; } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) { program->vars[i].value.f = val_d; if (size == 0) size = 8; } else { return -1; } } for(j=0;jn_const_vars;j++){ if (program->vars[ORC_VAR_C1 + j].value.i == program->vars[i].value.i && program->vars[ORC_VAR_C1 + j].size == size) { return ORC_VAR_C1 + j; } } program->vars[i].vartype = ORC_VAR_TYPE_CONST; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_const_vars++; return i; } /** * orc_program_add_parameter: * @program: a pointer to an OrcProgram structure * @size: size of data value * @name: name of variable * * Creates a new variable representing a scalar parameter. * * Returns: the index of the new variable */ int orc_program_add_parameter (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_P1 + program->n_param_vars; if (program->n_param_vars >= ORC_MAX_PARAM_VARS) { orc_program_set_error (program, "too many parameter variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_PARAM; program->vars[i].param_type = ORC_PARAM_TYPE_INT; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_param_vars++; return i; } /** * orc_program_add_parameter_float: * @program: a pointer to an OrcProgram structure * @size: size of data value * @name: name of variable * * Creates a new variable representing a scalar parameter. * * Returns: the index of the new variable */ int orc_program_add_parameter_float (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_P1 + program->n_param_vars; if (program->n_param_vars >= ORC_MAX_PARAM_VARS) { orc_program_set_error (program, "too many parameter variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_PARAM; program->vars[i].param_type = ORC_PARAM_TYPE_FLOAT; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_param_vars++; return i; } int orc_program_add_parameter_double (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_P1 + program->n_param_vars; if (program->n_param_vars >= ORC_MAX_PARAM_VARS) { orc_program_set_error (program, "too many parameter variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_PARAM; program->vars[i].param_type = ORC_PARAM_TYPE_DOUBLE; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_param_vars++; return i; } int orc_program_add_parameter_int64 (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_P1 + program->n_param_vars; if (program->n_param_vars >= ORC_MAX_PARAM_VARS) { orc_program_set_error (program, "too many parameter variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_PARAM; program->vars[i].param_type = ORC_PARAM_TYPE_INT64; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_param_vars++; return i; } /** * orc_program_add_accumulator: * @program: a pointer to an OrcProgram structure * @size: size of data value * @name: name of variable * * Creates a new variable representing an accumulator. * * Returns: the index of the new variable */ int orc_program_add_accumulator (OrcProgram *program, int size, const char *name) { int i = ORC_VAR_A1 + program->n_accum_vars; if (program->n_accum_vars >= ORC_MAX_ACCUM_VARS) { orc_program_set_error (program, "too many accumulator variables allocated"); return 0; } program->vars[i].vartype = ORC_VAR_TYPE_ACCUMULATOR; program->vars[i].size = size; program->vars[i].name = strdup(name); program->n_accum_vars++; return i; } void orc_program_set_type_name (OrcProgram *program, int var, const char *type_name) { program->vars[var].type_name = strdup(type_name); } void orc_program_set_var_alignment (OrcProgram *program, int var, int alignment) { program->vars[var].alignment = alignment; if (program->vars[var].alignment >= 16) { program->vars[var].is_aligned = TRUE; } } void orc_program_set_sampling_type (OrcProgram *program, int var, int sampling_type) { /* This doesn't do anything yet */ } /** * orc_program_append_ds: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @arg0: index of first variable * @arg1: index of second variable * * Appends an instruction to the program, with arguments @arg0 and * @arg1. The instruction must take 2 operands. */ void orc_program_append_ds (OrcProgram *program, const char *name, int arg0, int arg1) { OrcInstruction *insn; insn = program->insns + program->n_insns; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return; } insn->dest_args[0] = arg0; insn->src_args[0] = arg1; program->n_insns++; } /** * orc_program_append_ds: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @arg0: index of first variable * @arg1: index of second variable * @arg2: index of second variable * * Appends an instruction to the program, with arguments @arg0, * @arg1, and @arg2. The instruction must take 3 operands. */ void orc_program_append (OrcProgram *program, const char *name, int arg0, int arg1, int arg2) { OrcInstruction *insn; insn = program->insns + program->n_insns; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return; } insn->dest_args[0] = arg0; insn->src_args[0] = arg1; insn->src_args[1] = arg2; program->n_insns++; } /** * orc_program_append_ds_2: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @arg0: index of first variable * @arg1: index of second variable * @arg2: index of third variable * @arg3: index of fourth variable * * Appends an instruction to the program, with arguments @arg0, * @arg1, @arg2, and @arg3. */ void orc_program_append_2 (OrcProgram *program, const char *name, unsigned int flags, int arg0, int arg1, int arg2, int arg3) { OrcInstruction *insn; int args[4]; int i; insn = program->insns + program->n_insns; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return; } if (insn->opcode->dest_size[1] != 0 && insn->opcode->src_size[2] != 0) { ORC_ERROR ("opcode has too many dest/src parameters: %s", name); orc_program_set_error (program, "opcode has too many dest/src parameters"); return; } insn->flags = flags; args[0] = arg0; args[1] = arg1; args[2] = arg2; args[3] = arg3; insn->flags = flags; i = 0; insn->dest_args[0] = args[i++]; if (insn->opcode->dest_size[1] != 0) { insn->dest_args[1] = args[i++]; } if (insn->opcode->src_size[0] != 0) { insn->src_args[0] = args[i++]; } if (insn->opcode->src_size[1] != 0) { insn->src_args[1] = args[i++]; } if (insn->opcode->src_size[2] != 0) { insn->src_args[2] = args[i++]; } program->n_insns++; } /** * orc_program_find_var_by_name: * @program: a pointer to an OrcProgram structure * @name: name of instruction * * Finds the variable with the name @name. If no variable with the * given name exists in the program, -1 is returned. * * Returns: the index of the variable */ int orc_program_find_var_by_name (OrcProgram *program, const char *name) { int i; if (name == NULL) return -1; for(i=0;ivars[i].name && strcmp (program->vars[i].name, name) == 0) { return i; } } return -1; } /** * orc_program_append_str: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @arg0: name of first variable * @arg1: name of second variable * @arg2: name of third variable * * Appends an instruction to the program, with arguments @arg0, * @arg1, and @arg2. The instruction must take 3 operands. */ void orc_program_append_str (OrcProgram *program, const char *name, const char *arg1, const char *arg2, const char *arg3) { const char *args[3] = { arg1, arg2, arg3 }; int argc; if (arg3) argc = 3; else if (arg2) argc = 2; else if (arg1) argc = 1; else argc = 0; orc_program_append_str_n (program, name, 0, argc, args); } /** * orc_program_append_str_2: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @flags: flags * @arg0: name of first variable * @arg1: name of second variable * @arg2: name of third variable * @arg3: name of fourth variable * * Appends an instruction to the program, with arguments @arg0, * @arg1, @arg2, and @arg3. */ void orc_program_append_str_2 (OrcProgram *program, const char *name, unsigned int flags, const char *arg1, const char *arg2, const char *arg3, const char *arg4) { const char *args[4] = { arg1, arg2, arg3, arg4 }; int argc; if (arg4) argc = 4; else if (arg3) argc = 3; else if (arg2) argc = 2; else if (arg1) argc = 1; else argc = 0; orc_program_append_str_n (program, name, flags, argc, args); } /** * orc_program_append_str_n: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @flags: flags * @argc: number of variableds * @argv: array of variables * * Appends an instruction to the program, with any number of * arguments. Only 1 <= number <= 6 is supported. * * Returns: status code. * 0: succesfull * <0: malformed opcode (unknown or bad arguments) * >0: unknown argument. Then the return value equals to the nth * argument. Beware: this is index, not offset (the first is 1). */ int orc_program_append_str_n (OrcProgram *program, const char *name, unsigned int flags, int argc, const char **argv) { OrcInstruction *insn; int args[6]; int i; int expected_args = 0; insn = program->insns + program->n_insns; insn->line = program->current_line; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return -1; } /* dest_size[0] */ expected_args++; if (insn->opcode->dest_size[1] != 0) expected_args++; if (insn->opcode->src_size[0] != 0) expected_args++; if (insn->opcode->src_size[1] != 0) expected_args++; if (insn->opcode->src_size[2] != 0) expected_args++; if (insn->opcode->src_size[3] != 0) expected_args++; if (argc < expected_args) { ORC_ERROR ("not the correct number of arguments provided for opcode: %s expects %d but got %d", name, expected_args, argc); orc_program_set_error (program, "not the correct number of arguments provided for opcode"); return -1; } if (argc != expected_args) { ORC_WARNING ("not the correct number of arguments provided for opcode: %s expects %d but got %d", name, expected_args, argc); }; for (i=0;iline); orc_program_set_error (program, "bad operand"); return i+1; } } insn->flags = flags; i = 0; insn->dest_args[0] = args[i++]; if (insn->opcode->dest_size[1] != 0) insn->dest_args[1] = args[i++]; if (insn->opcode->src_size[0] != 0) insn->src_args[0] = args[i++]; if (insn->opcode->src_size[1] != 0) insn->src_args[1] = args[i++]; if (insn->opcode->src_size[2] != 0) insn->src_args[2] = args[i++]; if (insn->opcode->src_size[3] != 0) insn->src_args[3] = args[i++]; program->n_insns++; return 0; } /** * orc_program_append_ds_str: * @program: a pointer to an OrcProgram structure * @name: name of instruction * @arg0: name of first variable * @arg1: name of second variable * * Appends an instruction to the program, with arguments @arg0 and * @arg2. The instruction must take 2 operands. */ void orc_program_append_ds_str (OrcProgram *program, const char *name, const char *arg1, const char *arg2) { OrcInstruction *insn; insn = program->insns + program->n_insns; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return; } insn->dest_args[0] = orc_program_find_var_by_name (program, arg1); insn->src_args[0] = orc_program_find_var_by_name (program, arg2); program->n_insns++; } void orc_program_append_dds_str (OrcProgram *program, const char *name, const char *arg1, const char *arg2, const char *arg3) { OrcInstruction *insn; insn = program->insns + program->n_insns; insn->opcode = orc_opcode_find_by_name (name); if (!insn->opcode) { ORC_ERROR ("unknown opcode: %s", name); orc_program_set_error (program, "unknown opcode"); return; } insn->dest_args[0] = orc_program_find_var_by_name (program, arg1); insn->dest_args[1] = orc_program_find_var_by_name (program, arg2); insn->src_args[0] = orc_program_find_var_by_name (program, arg3); program->n_insns++; } /** * orc_program_get_asm_code: * @program: a pointer to an OrcProgram structure * * Returns a character string containing the assembly code created * by compiling the program. This string is valid until the program * is compiled again or the program is freed. * * Returns: a character string */ const char * orc_program_get_asm_code (OrcProgram *program) { return program->asm_code; } /** * orc_program_get_error: * @program: a pointer to an OrcProgram structure * * Returns a character string containing the error message from * compilation. This string is valid until the program * is compiled again, the program is freed, or another error * is set. * * Returns: a character string */ const char * orc_program_get_error (OrcProgram *program) { if (program->error_msg) return program->error_msg; return ""; } /** * orc_program_set_error: * @program: a pointer to an OrcProgram structure * @error: an error string * * Stores the error in the program. This string is duplicated. * If an error has already been set, this new error is ignored. * An error will stay till the next call to _reset, if any. */ void orc_program_set_error (OrcProgram *program, const char *error) { if (!program->error_msg && error) { program->error_msg = strdup (error); } } /** * orc_program_get_max_array_size: * @program: a pointer to an OrcProgram structure * * Returns the size of the largest array used in the program. * * Returns: the number of bytes */ int orc_program_get_max_array_size (OrcProgram *program) { int i; int max; max = 0; for(i=0;ivars[i].size) { if (program->vars[i].vartype == ORC_VAR_TYPE_SRC || program->vars[i].vartype == ORC_VAR_TYPE_DEST) { max = MAX(max, program->vars[i].size); } } } return max; } /** * orc_program_get_max_accumulator_size: * @program: a pointer to an OrcProgram structure * * Returns the size of the largest array used in the program. * * Returns: the number of bytes */ int orc_program_get_max_accumulator_size (OrcProgram *program) { int i; int max; max = 0; for(i=0;ivars[i].size) { if (program->vars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) { max = MAX(max, program->vars[i].size); } } } return max; } int _orc_data_cache_size_level1; int _orc_data_cache_size_level2; int _orc_data_cache_size_level3; int _orc_cpu_family; int _orc_cpu_model; int _orc_cpu_stepping; const char *_orc_cpu_name = "unknown"; void orc_get_data_cache_sizes (int *level1, int *level2, int *level3) { if (level1) { *level1 = _orc_data_cache_size_level1; } if (level2) { *level2 = _orc_data_cache_size_level2; } if (level3) { *level3 = _orc_data_cache_size_level3; } } void orc_get_cpu_family_model_stepping (int *family, int *model, int *stepping) { if (family) { *family = _orc_cpu_family; } if (model) { *model = _orc_cpu_model; } if (stepping) { *stepping = _orc_cpu_stepping; } } const char * orc_get_cpu_name (void) { return _orc_cpu_name; } void orc_program_reset (OrcProgram *program) { if (program->orccode) { orc_code_free (program->orccode); program->orccode = NULL; } if (program->asm_code) { free(program->asm_code); program->asm_code = NULL; } if (program->error_msg) { free(program->error_msg); program->error_msg = NULL; } } OrcCode * orc_program_take_code (OrcProgram *program) { OrcCode *code = program->orccode; program->orccode = NULL; return code; } int orc_program_has_float (OrcCompiler *compiler) { int j; for(j=0;jn_insns;j++){ OrcInstruction *insn = compiler->insns + j; OrcStaticOpcode *opcode = insn->opcode; if (opcode->flags & ORC_STATIC_OPCODE_FLOAT) return TRUE; } return FALSE; } /** * orc_program_compile: * @program: the OrcProgram to compile * * Compiles an Orc program for the current CPU. If successful, * executable code for the program was generated and can be * executed. * * The return value indicates various levels of success or failure. * Success can be determined by checking for a true value of the * macro ORC_COMPILE_RESULT_IS_SUCCESSFUL() on the return value. This * indicates that executable code was generated. If the macro * ORC_COMPILE_RESULT_IS_FATAL() on the return value evaluates to * true, then there was a syntactical error in the program. If the * result is neither successful nor fatal, the program can still be * emulated. * * Returns: an OrcCompileResult */ OrcCompileResult orc_program_compile (OrcProgram *program) { return orc_program_compile_for_target (program, orc_target_get_default ()); } /** * orc_program_compile_for_target: * @program: the OrcProgram to compile * * Compiles an Orc program for the given target, using the * default target flags for that target. * * Returns: an OrcCompileResult */ OrcCompileResult orc_program_compile_for_target (OrcProgram *program, OrcTarget *target) { unsigned int flags; if (target) { flags = target->get_default_flags (); } else { flags = 0; } return orc_program_compile_full (program, target, flags); } /** * orc_program_compile_full: * @program: the OrcProgram to compile * * Compiles an Orc program for the given target, using the * given target flags. * * Returns: an OrcCompileResult */ OrcCompileResult orc_program_compile_full (OrcProgram *program, OrcTarget *target, unsigned int flags) { OrcCompiler *compiler; compiler = malloc (sizeof(OrcCompiler)); memset (compiler, 0, sizeof(OrcCompiler)); return orc_compiler_compile_program (compiler, program, target, flags); }