OrcTestResult orc_test_compare_output_full (OrcProgram *program, int flags) { OrcExecutor *ex; int n; int m; OrcArray *dest_exec[4] = { NULL, NULL, NULL, NULL }; OrcArray *dest_emul[4] = { NULL, NULL, NULL, NULL }; OrcArray *src[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int i; int j; int k; int have_dest = FALSE; OrcCompileResult result; int have_acc = FALSE; int acc_exec = 0, acc_emul = 0; int ret = ORC_TEST_OK; int bad = 0; int misalignment; ORC_DEBUG ("got here"); { OrcTarget *target; unsigned int flags; target = orc_target_get_default (); flags = orc_target_get_default_flags (target); result = orc_program_compile_full (program, target, flags); if (ORC_COMPILE_RESULT_IS_FATAL(result)) { ret = ORC_TEST_FAILED; goto out; } if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { ret = ORC_TEST_INDETERMINATE; goto out; } } if (program->constant_n > 0) { n = program->constant_n; } else { n = 64 + (orc_random(&rand_context)&0xf); } ex = orc_executor_new (program); orc_executor_set_n (ex, n); if (program->is_2d) { if (program->constant_m > 0) { m = program->constant_m; } else { m = 8 + (orc_random(&rand_context)&0xf); } } else { m = 1; } orc_executor_set_m (ex, m); ORC_DEBUG("size %d %d", ex->n, ex->params[ORC_VAR_A1]); misalignment = 0; for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].name == NULL) continue; if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { src[i-ORC_VAR_S1] = orc_array_new (n, m, program->vars[i].size, misalignment); orc_array_set_random (src[i-ORC_VAR_S1], &rand_context); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_DEST) { dest_exec[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment); orc_array_set_pattern (dest_exec[i], ORC_OOB_VALUE); dest_emul[i-ORC_VAR_D1] = orc_array_new (n, m, program->vars[i].size, misalignment); orc_array_set_pattern (dest_emul[i], ORC_OOB_VALUE); misalignment++; } else if (program->vars[i].vartype == ORC_VAR_TYPE_PARAM) { switch (program->vars[i].param_type) { case ORC_PARAM_TYPE_INT: orc_executor_set_param (ex, i, 2); break; case ORC_PARAM_TYPE_FLOAT: orc_executor_set_param_float (ex, i, 2.0); break; case ORC_PARAM_TYPE_INT64: orc_executor_set_param_int64 (ex, i, 2); break; case ORC_PARAM_TYPE_DOUBLE: orc_executor_set_param_double (ex, i, 2.0); break; } } } for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].vartype == ORC_VAR_TYPE_DEST) { orc_executor_set_array (ex, i, dest_exec[i-ORC_VAR_D1]->data); orc_executor_set_stride (ex, i, dest_exec[i-ORC_VAR_D1]->stride); have_dest = TRUE; } if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { orc_executor_set_array (ex, i, src[i-ORC_VAR_S1]->data); orc_executor_set_stride (ex, i, src[i-ORC_VAR_S1]->stride); } } ORC_DEBUG ("running"); if (flags & ORC_TEST_FLAGS_BACKUP) { orc_executor_run_backup (ex); } else { orc_executor_run (ex); } ORC_DEBUG ("done running"); for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) { acc_exec = ex->accumulators[0]; have_acc = TRUE; } } for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].vartype == ORC_VAR_TYPE_DEST) { orc_executor_set_array (ex, i, dest_emul[i]->data); orc_executor_set_stride (ex, i, dest_emul[i]->stride); } if (program->vars[i].vartype == ORC_VAR_TYPE_SRC) { ORC_DEBUG("setting array %p", src[i-ORC_VAR_S1]->data); orc_executor_set_array (ex, i, src[i-ORC_VAR_S1]->data); orc_executor_set_stride (ex, i, src[i-ORC_VAR_S1]->stride); } } orc_executor_emulate (ex); for(i=0;i<ORC_N_VARIABLES;i++){ if (program->vars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) { acc_emul = ex->accumulators[0]; } } for(k=ORC_VAR_D1;k<ORC_VAR_D1+4;k++){ if (program->vars[k].size > 0) { if (!orc_array_compare (dest_exec[k-ORC_VAR_D1], dest_emul[k-ORC_VAR_D1], flags)) { printf("dest array %d bad\n", k); bad = TRUE; } if (!orc_array_check_out_of_bounds (dest_exec[k-ORC_VAR_D1])) { printf("out of bounds failure\n"); ret = ORC_TEST_FAILED; } } } if (bad) { for(j=0;j<m;j++){ for(i=0;i<n;i++){ orc_uint64 a,b; int l; int line_bad = 0; printf("%2d %2d:", i, j); for(l=ORC_VAR_S1;l<ORC_VAR_S1+8;l++){ if (program->vars[l].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { print_array_val_float (src[l-ORC_VAR_S1], i, j); } else { print_array_val_hex (src[l-ORC_VAR_S1], i, j); } } } printf(" ->"); for(l=ORC_VAR_D1;l<ORC_VAR_D1+4;l++){ if (program->vars[l].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { a = print_array_val_float (dest_emul[l-ORC_VAR_D1], i, j); b = print_array_val_float (dest_exec[l-ORC_VAR_D1], i, j); if (!float_compare (dest_emul[l-ORC_VAR_D1], dest_exec[l-ORC_VAR_D1], i, j) != 0) { line_bad = TRUE; } } else { a = print_array_val_hex (dest_emul[l-ORC_VAR_D1], i, j); b = print_array_val_hex (dest_exec[l-ORC_VAR_D1], i, j); if (a != b) { line_bad = TRUE; } } } } if (line_bad) { printf(" *"); } printf("\n"); } } ret = ORC_TEST_FAILED; } if (have_acc) { if (acc_emul != acc_exec) { for(j=0;j<m;j++){ for(i=0;i<n;i++){ printf("%2d %2d:", i, j); for(k=0;k<ORC_N_VARIABLES;k++){ if (program->vars[k].name == NULL) continue; if (program->vars[k].vartype == ORC_VAR_TYPE_SRC && program->vars[k].size > 0) { if (flags & ORC_TEST_FLAGS_FLOAT) { print_array_val_float (src[k-ORC_VAR_S1], i, j); } else { print_array_val_signed (src[k-ORC_VAR_S1], i, j); } } } printf(" -> acc\n"); } } printf("acc %d %d\n", acc_emul, acc_exec); ret = ORC_TEST_FAILED; } } if (ret == ORC_TEST_FAILED) { printf("%s", orc_program_get_asm_code (program)); } for(i=0;i<4;i++){ if (dest_exec[i]) orc_array_free (dest_exec[i]); if (dest_emul[i]) orc_array_free (dest_emul[i]); } for(i=0;i<8;i++){ if (src[i]) orc_array_free (src[i]); } orc_executor_free (ex); out: orc_program_reset (program); return ret; }
/** * 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 ()); }
OrcTestResult orc_test_gcc_compile (OrcProgram *p) { char cmd[200]; char *base; char source_filename[100]; char obj_filename[100]; char dis_filename[100]; char dump_filename[100]; char dump_dis_filename[100]; int ret; FILE *file; OrcCompileResult result; OrcTarget *target; unsigned int flags; base = "temp-orc-test"; sprintf(source_filename, "%s-source.s", base); sprintf(obj_filename, "%s.o", base); sprintf(dis_filename, "%s-source.dis", base); sprintf(dump_filename, "%s-dump.bin", base); sprintf(dump_dis_filename, "%s-dump.dis", base); target = orc_target_get_default (); flags = orc_target_get_default_flags (target); flags |= ORC_TARGET_CLEAN_COMPILE; if (strcmp (orc_target_get_name (target), "sse") == 0) { flags |= ORC_TARGET_SSE_SHORT_JUMPS; } if (strcmp (orc_target_get_name (target), "mmx") == 0) { flags |= ORC_TARGET_MMX_SHORT_JUMPS; } result = orc_program_compile_full (p, target, flags); if (ORC_COMPILE_RESULT_IS_FATAL(result)) { return ORC_TEST_FAILED; } if (!ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { return ORC_TEST_INDETERMINATE; } fflush (stdout); file = fopen (source_filename, "w"); fprintf(file, "%s", orc_program_get_asm_code (p)); fclose (file); file = fopen (dump_filename, "w"); ret = fwrite(p->orccode->code, p->orccode->code_size, 1, file); fclose (file); #if defined(HAVE_POWERPC) sprintf (cmd, "gcc -Wa,-mregnames -Wall -c %s -o %s", source_filename, obj_filename); #else sprintf (cmd, "gcc -Wall -c %s -o %s", source_filename, obj_filename); #endif ret = system (cmd); if (ret != 0) { ORC_ERROR ("gcc failed"); printf("%s\n", orc_program_get_asm_code (p)); return ORC_TEST_FAILED; } #if 0 sprintf (cmd, "objdump -dr %s | sed 's/^[ 0-9a-f]*:/XXX:/' >%s", obj_filename, dis_filename); #else sprintf (cmd, "objdump -dr %s >%s", obj_filename, dis_filename); #endif ret = system (cmd); if (ret != 0) { ORC_ERROR ("objdump failed"); return ORC_TEST_FAILED; } sprintf (cmd, "objcopy -I binary " #ifdef HAVE_I386 "-O elf32-i386 -B i386 " #elif defined(HAVE_AMD64) "-O elf64-x86-64 -B i386 " #elif defined(HAVE_POWERPC) "-O elf32-powerpc -B powerpc " #else /* FIXME */ #endif "--rename-section .data=.text " "--redefine-sym _binary_temp_orc_test_dump_bin_start=%s " "%s %s", p->name, dump_filename, obj_filename); ret = system (cmd); if (ret != 0) { printf("objcopy failed\n"); return ORC_TEST_FAILED; } #if 0 sprintf (cmd, "objdump -Dr %s | sed 's/^[ 0-9a-f]*:/XXX:/' >%s", obj_filename, dump_dis_filename); #else sprintf (cmd, "objdump -Dr %s >%s", obj_filename, dump_dis_filename); #endif ret = system (cmd); if (ret != 0) { printf("objdump failed\n"); return ORC_TEST_FAILED; } sprintf (cmd, "diff -u %s %s", dis_filename, dump_dis_filename); ret = system (cmd); if (ret != 0) { printf("diff failed\n"); return ORC_TEST_FAILED; } remove (source_filename); remove (obj_filename); remove (dis_filename); remove (dump_filename); remove (dump_dis_filename); return ORC_TEST_OK; }
int main (int argc, char *argv[]) { int i; OrcProgram **programs; const char *filename = NULL; orc_init (); orc_test_init (); for(i=1;i<argc;i++){ if (strcmp(argv[i], "--help") == 0) { printf("Usage:\n"); printf(" orc-bugreport [file.orc]\n"); printf("\n"); printf("Options:\n"); printf(" --help Show help options\n"); printf(" --verbose Increase debugging messages\n"); printf("\n"); printf("Environment Variables:\n"); printf(" ORC_DEBUG=<LEVEL> Set debugging level\n"); printf(" ORC_CODE=[KEYWORDS,...] Modify code generation\n"); printf(" General keywords:\n"); printf(" backup Always use backup function\n"); printf(" debug Generate debuggable code (useful for backtraces on i386)\n"); printf(" SSE keywords:\n"); printf(" -sse2 Disable SSE2\n"); printf(" -sse3 Disable SSE3\n"); printf(" -ssse3 Disable SSEE3\n"); printf(" -sse41 Disable SSE4.1\n"); printf(" -sse42 Disable SSE4.2\n"); printf(" -sse4a Disable SSE4a\n"); printf(" -sse5 Disable SSE5\n"); printf("\n"); exit (0); } filename = argv[i]; } printf("Orc " VERSION " - integrated testing tool\n"); printf("Active backend: %s\n", orc_target_get_name(orc_target_get_default())); { int level1, level2, level3; orc_get_data_cache_sizes(&level1, &level2, &level3); printf("L1 cache: %d\n", level1); printf("L2 cache: %d\n", level2); printf("L3 cache: %d\n", level3); } { int family, model, stepping; orc_get_cpu_family_model_stepping (&family, &model, &stepping); printf("Family/Model/Stepping: %d/%d/%d\n", family, model, stepping); printf("CPU name: %s\n", orc_get_cpu_name ()); } { int i; int flags = orc_target_get_default_flags (orc_target_get_default()); printf("Compiler options: "); for(i=0;i<32;i++){ if (flags & (1<<i)) { printf("%s ", orc_target_get_flag_name (orc_target_get_default(), i)); } } printf("\n"); } if (filename) { int n; int ret; char *code; code = read_file (filename); if (!code) { printf("orc-bugreport: could not read file %s\n", filename); exit(1); } printf("Parsing %s\n", filename); n = orc_parse (code, &programs); for(i=0;i<n;i++){ ret = orc_test_compare_output_full (programs[i], 0); if (!ret) { printf("FAIL: %s\n", programs[i]->name); error = TRUE; } } } else { printf("Opcode test:\n"); test_opcodes(); } if (error) { printf("Errors detected. Please send entire output to [email protected].\n"); return 1; } else { printf("No errors detected.\n"); return 0; } }