void orc_x86_do_fixups (OrcCompiler *compiler) { int i; for(i=0;i<compiler->n_fixups;i++){ if (compiler->fixups[i].type == 0) { unsigned char *label = compiler->labels[compiler->fixups[i].label]; unsigned char *ptr = compiler->fixups[i].ptr; int diff; diff = ((orc_int8)ptr[0]) + (label - ptr); if (diff != (orc_int8)diff) { orc_compiler_error (compiler, "short jump too long %d", diff); } ptr[0] = diff; } else if (compiler->fixups[i].type == 1) { unsigned char *label = compiler->labels[compiler->fixups[i].label]; unsigned char *ptr = compiler->fixups[i].ptr; int diff; diff = ORC_READ_UINT32_LE (ptr) + (label - ptr); ORC_WRITE_UINT32_LE(ptr, diff); } } }
void orc_x86_emit_mov_reg_memoffset (OrcCompiler *compiler, int size, int reg1, int offset, int reg2) { switch (size) { case 1: orc_x86_emit_cpuinsn_reg_memoffset (compiler, ORC_X86_movb_r_rm, reg1, offset, reg2); break; case 2: orc_x86_emit_cpuinsn_reg_memoffset (compiler, ORC_X86_movw_r_rm, reg1, offset, reg2); break; case 4: orc_x86_emit_cpuinsn_reg_memoffset (compiler, ORC_X86_movl_r_rm, reg1, offset, reg2); break; case 8: orc_x86_emit_cpuinsn_reg_memoffset_8 (compiler, ORC_X86_mov_r_rm, reg1, offset, reg2); break; default: orc_compiler_error(compiler, "bad size"); break; } }
int orc_compiler_allocate_register (OrcCompiler *compiler, int data_reg) { int i; int roff; int reg; int offset; if (data_reg) { offset = compiler->target->data_register_offset; } else { offset = ORC_GP_REG_BASE; } roff = 0; if (_orc_compiler_flag_randomize) { /* for testing */ roff = rand()&0x1f; } for(i=0;i<32;i++){ reg = offset + ((roff + i)&0x1f); if (compiler->valid_regs[reg] && !compiler->save_regs[reg] && compiler->alloc_regs[reg] == 0) { compiler->alloc_regs[reg]++; compiler->used_regs[reg] = 1; return reg; } } for(i=0;i<32;i++){ reg = offset + ((roff + i)&0x1f); if (compiler->valid_regs[reg] && compiler->alloc_regs[reg] == 0) { compiler->alloc_regs[reg]++; compiler->used_regs[reg] = 1; return reg; } } if (data_reg || !compiler->allow_gp_on_stack) { orc_compiler_error (compiler, "register overflow for %s reg", data_reg ? "vector" : "gp"); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; } return 0; }
int orc_compiler_get_temp_reg (OrcCompiler *compiler) { int j; for(j=0;j<ORC_N_REGS;j++){ compiler->alloc_regs[j] = 0; } for(j=0;j<ORC_N_COMPILER_VARIABLES;j++){ if (!compiler->vars[j].alloc) continue; ORC_DEBUG("var %d: %d %d %d", j, compiler->vars[j].alloc, compiler->vars[j].first_use, compiler->vars[j].last_use); if (compiler->vars[j].first_use == -1) { compiler->alloc_regs[compiler->vars[j].alloc] = 1; } else if (compiler->vars[j].first_use <= compiler->insn_index && compiler->vars[j].last_use >= compiler->insn_index) { compiler->alloc_regs[compiler->vars[j].alloc] = 1; } } for(j=0;j<compiler->n_constants;j++){ if (compiler->constants[j].alloc_reg) { compiler->alloc_regs[compiler->constants[j].alloc_reg] = 1; } } ORC_DEBUG("at insn %d %s", compiler->insn_index, compiler->insns[compiler->insn_index].opcode->name); for(j=compiler->min_temp_reg;j<ORC_VEC_REG_BASE+32;j++){ if (compiler->valid_regs[j] && !compiler->alloc_regs[j]) { compiler->min_temp_reg = j+1; if (compiler->max_used_temp_reg < j) compiler->max_used_temp_reg = j; return j; } } orc_compiler_error (compiler, "no temporary register available"); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; return 0; }
void orc_compiler_assign_rules (OrcCompiler *compiler) { int i; for(i=0;i<compiler->n_insns;i++) { OrcInstruction *insn = compiler->insns + i; insn->rule = orc_target_get_rule (compiler->target, insn->opcode, compiler->target_flags); if (insn->rule == NULL || insn->rule->emit == NULL) { orc_compiler_error (compiler, "no code generation rule for %s on " "target %s", insn->opcode->name, compiler->target->name); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; return; } } }
void orc_x86_emit_mov_memoffset_reg (OrcCompiler *compiler, int size, int offset, int reg1, int reg2) { switch (size) { case 1: orc_x86_emit_cpuinsn_memoffset_reg (compiler, ORC_X86_movzx_rm_r, 4, offset, reg1, reg2); return; case 2: orc_x86_emit_cpuinsn_memoffset_reg (compiler, ORC_X86_movw_rm_r, size, offset, reg1, reg2); break; case 4: orc_x86_emit_cpuinsn_memoffset_reg (compiler, ORC_X86_movl_rm_r, size, offset, reg1, reg2); break; case 8: orc_x86_emit_cpuinsn_memoffset_reg (compiler, ORC_X86_mov_rm_r, size, offset, reg1, reg2); break; default: orc_compiler_error(compiler, "bad size"); break; } }
void orc_compiler_global_reg_alloc (OrcCompiler *compiler) { int i; OrcVariable *var; for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){ var = compiler->vars + i; if (var->name == NULL) continue; switch (var->vartype) { case ORC_VAR_TYPE_CONST: break; case ORC_VAR_TYPE_PARAM: break; case ORC_VAR_TYPE_SRC: var->ptr_register = orc_compiler_allocate_register (compiler, FALSE); if (compiler->need_mask_regs) { var->mask_alloc = orc_compiler_allocate_register (compiler, TRUE); var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE); var->aligned_data = orc_compiler_allocate_register (compiler, TRUE); } if (var->need_offset_reg) { var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE); } break; case ORC_VAR_TYPE_DEST: var->ptr_register = orc_compiler_allocate_register (compiler, FALSE); break; case ORC_VAR_TYPE_ACCUMULATOR: var->first_use = -1; var->last_use = -1; var->alloc = orc_compiler_allocate_register (compiler, TRUE); break; case ORC_VAR_TYPE_TEMP: break; default: orc_compiler_error (compiler, "bad vartype"); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE; break; } if (compiler->error) break; } for(i=0;i<compiler->n_insns;i++){ OrcInstruction *insn = compiler->insns + i; OrcStaticOpcode *opcode = insn->opcode; if (opcode->flags & ORC_STATIC_OPCODE_INVARIANT) { var = compiler->vars + insn->dest_args[0]; var->first_use = -1; var->last_use = -1; var->alloc = orc_compiler_allocate_register (compiler, TRUE); insn->flags |= ORC_INSN_FLAG_INVARIANT; } if (opcode->flags & ORC_STATIC_OPCODE_ITERATOR) { compiler->has_iterator_opcode = TRUE; } } if (compiler->alloc_loop_counter && !compiler->error) { compiler->loop_counter = orc_compiler_allocate_register (compiler, FALSE); /* FIXME massive hack */ if (compiler->loop_counter == 0) { compiler->error = FALSE; compiler->result = ORC_COMPILE_RESULT_OK; } } }
/** * 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; int i; OrcCompileResult result; ORC_INFO("initializing compiler for program \"%s\"", program->name); compiler = malloc (sizeof(OrcCompiler)); memset (compiler, 0, sizeof(OrcCompiler)); if (program->backup_func) { program->code_exec = program->backup_func; } else { program->code_exec = (void *)orc_executor_emulate; } compiler->program = program; compiler->target = target; compiler->target_flags = flags; { ORC_LOG("variables"); for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].size > 0) { ORC_LOG("%d: %s size %d type %d alloc %d", i, program->vars[i].name, program->vars[i].size, program->vars[i].vartype, program->vars[i].alloc); } } ORC_LOG("instructions"); for(i=0;i<program->n_insns;i++){ ORC_LOG("%d: %s %d %d %d %d", i, program->insns[i].opcode->name, program->insns[i].dest_args[0], program->insns[i].dest_args[1], program->insns[i].src_args[0], program->insns[i].src_args[1]); } } memcpy (compiler->insns, program->insns, program->n_insns * sizeof(OrcInstruction)); compiler->n_insns = program->n_insns; memcpy (compiler->vars, program->vars, ORC_N_VARIABLES * sizeof(OrcVariable)); memset (compiler->vars + ORC_N_VARIABLES, 0, (ORC_N_COMPILER_VARIABLES - ORC_N_VARIABLES) * sizeof(OrcVariable)); compiler->n_temp_vars = program->n_temp_vars; compiler->n_dup_vars = 0; for(i=0;i<32;i++) { compiler->valid_regs[i] = 1; } orc_compiler_check_sizes (compiler); if (compiler->error) goto error; if (compiler->target) { compiler->target->compiler_init (compiler); } orc_compiler_rewrite_insns (compiler); if (compiler->error) goto error; orc_compiler_rewrite_vars (compiler); if (compiler->error) goto error; if (compiler->target) { orc_compiler_global_reg_alloc (compiler); orc_compiler_rewrite_vars2 (compiler); } #if 0 { ORC_ERROR("variables"); for(i=0;i<ORC_N_VARIABLES;i++){ if (compiler->vars[i].size > 0) { ORC_ERROR("%d: %s size %d type %d alloc %d [%d,%d]", i, compiler->vars[i].name, compiler->vars[i].size, compiler->vars[i].vartype, compiler->vars[i].alloc, compiler->vars[i].first_use, compiler->vars[i].last_use); } } ORC_ERROR("instructions"); for(i=0;i<compiler->n_insns;i++){ ORC_ERROR("%d: %s %d %d %d %d", i, compiler->insns[i].opcode->name, compiler->insns[i].dest_args[0], compiler->insns[i].dest_args[1], compiler->insns[i].src_args[0], compiler->insns[i].src_args[1]); } } #endif if (compiler->error) goto error; program->orccode = orc_code_new (); program->orccode->is_2d = program->is_2d; program->orccode->constant_n = program->constant_n; program->orccode->constant_m = program->constant_m; program->orccode->exec = program->code_exec; program->orccode->n_insns = compiler->n_insns; program->orccode->insns = malloc(sizeof(OrcInstruction) * compiler->n_insns); memcpy (program->orccode->insns, compiler->insns, sizeof(OrcInstruction) * compiler->n_insns); program->orccode->vars = malloc (sizeof(OrcCodeVariable) * ORC_N_COMPILER_VARIABLES); memset (program->orccode->vars, 0, sizeof(OrcCodeVariable) * ORC_N_COMPILER_VARIABLES); for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){ program->orccode->vars[i].vartype = compiler->vars[i].vartype; program->orccode->vars[i].size = compiler->vars[i].size; program->orccode->vars[i].value = compiler->vars[i].value; } if (program->backup_func && _orc_compiler_flag_backup) { orc_compiler_error (compiler, "Compilation disabled, using backup"); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; goto error; } if (_orc_compiler_flag_emulate || target == NULL) { program->code_exec = (void *)orc_executor_emulate; program->orccode->exec = (void *)orc_executor_emulate; orc_compiler_error (compiler, "Compilation disabled, using emulation"); compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; goto error; } orc_compiler_assign_rules (compiler); if (compiler->error) goto error; ORC_INFO("allocating code memory"); compiler->code = malloc(65536); compiler->codeptr = compiler->code; if (compiler->error) goto error; ORC_INFO("compiling for target \"%s\"", compiler->target->name); compiler->target->compile (compiler); if (compiler->error) { compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; goto error; } program->orccode->code_size = compiler->codeptr - compiler->code; orc_code_allocate_codemem (program->orccode, program->orccode->code_size); memcpy (program->orccode->code, compiler->code, program->orccode->code_size); #ifdef VALGRIND_DISCARD_TRANSLATIONS VALGRIND_DISCARD_TRANSLATIONS (program->orccode->exec, program->orccode->code_size); #endif if (compiler->target->flush_cache) { compiler->target->flush_cache (program->orccode); } program->code_exec = program->orccode->exec; program->asm_code = compiler->asm_code; result = compiler->result; for (i=0;i<compiler->n_dup_vars;i++){ free(compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name); compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name = NULL; } free (compiler->code); compiler->code = NULL; if (compiler->output_insns) free (compiler->output_insns); free (compiler); ORC_INFO("finished compiling (success)"); return result; error: if (compiler->error_msg) { ORC_WARNING ("program %s failed to compile, reason: %s", program->name, compiler->error_msg); } else { ORC_WARNING("program %s failed to compile, reason %d", program->name, compiler->result); } result = compiler->result; if (program->error_msg) free (program->error_msg); program->error_msg = compiler->error_msg; if (result == 0) { result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE; } if (compiler->asm_code) { free (compiler->asm_code); compiler->asm_code = NULL; } for (i=0;i<compiler->n_dup_vars;i++){ free(compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name); compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name = NULL; } free (compiler->code); compiler->code = NULL; if (compiler->output_insns) free (compiler->output_insns); free (compiler); ORC_INFO("finished compiling (fail)"); return result; }