#include "config.h" #define ORC_ENABLE_UNSTABLE_API #include #include #include #include #include #include #include static char * read_file (const char *filename); void output_code (OrcProgram *p, FILE *output); void output_code_header (OrcProgram *p, FILE *output); void output_code_test (OrcProgram *p, FILE *output); void output_code_backup (OrcProgram *p, FILE *output); void output_code_no_orc (OrcProgram *p, FILE *output); void output_code_assembly (OrcProgram *p, FILE *output); void output_machine_code (OrcProgram *p, FILE *output); void output_code_execute (OrcProgram *p, FILE *output, int is_inline); void output_program_generation (OrcProgram *p, FILE *output, int is_inline); void output_init_function (FILE *output); static const char * my_basename (const char *s); int verbose = 0; int error = 0; int compat; int n_programs; OrcProgram **programs; int use_inline = FALSE; int use_code = FALSE; int use_lazy_init = FALSE; int use_backup = TRUE; int use_internal = FALSE; const char *init_function = NULL; const char *decorator = NULL; char *target = NULL; #define ORC_VERSION(a,b,c,d) ((a)*1000000 + (b)*10000 + (c)*100 + (d)) #define REQUIRE(a,b,c,d) do { \ if (ORC_VERSION((a),(b),(c),(d)) > compat) { \ fprintf(stderr, "Feature used that is incompatible with --compat in program %s\n", p->name); \ exit (1); \ } \ } while (0) typedef enum { MODE_IMPL, MODE_HEADER, MODE_TEST, MODE_ASSEMBLY, MODE_BINARY, MODE_PARSE } OrcMode; OrcMode mode = MODE_IMPL; void help (void) { fprintf(stderr, "Usage:\n"); fprintf(stderr, " orcc [OPTION...] INPUT_FILE\n"); fprintf(stderr, "\n"); fprintf(stderr, "Help Options:\n"); fprintf(stderr, " -h, --help Show help options\n"); fprintf(stderr, "\n"); fprintf(stderr, "Application Options:\n"); fprintf(stderr, " -v, --verbose Output more information\n"); fprintf(stderr, " -o, --output FILE Write output to FILE\n"); fprintf(stderr, " --implementation Produce C code implementing functions\n"); fprintf(stderr, " --header Produce C header for functions\n"); fprintf(stderr, " --test Produce test code for functions\n"); fprintf(stderr, " --assembly Produce assembly code for functions\n"); fprintf(stderr, " --binary Produce raw machine code for functions\n"); fprintf(stderr, " --include FILE Add #include to code\n"); fprintf(stderr, " --target TARGET Generate assembly for TARGET\n"); fprintf(stderr, " --compat VERSION Generate code compatible with Orc version VERSION\n"); fprintf(stderr, " --inline Generate inline functions in header\n"); fprintf(stderr, " --no-inline Do not generate inline functions in header\n"); fprintf(stderr, " --internal Mark functions in header for internal visibility\n"); fprintf(stderr, " --no-internal Do not mark functions in header for internal visibility\n"); fprintf(stderr, " --decorator DECORATOR Decorate functions in header with DECORATOR\n"); fprintf(stderr, " --init-function FUNCTION Generate initialization function\n"); fprintf(stderr, " --lazy-init Do Orc compile at function execution\n"); fprintf(stderr, " --no-backup Do not generate backup functions\n"); fprintf(stderr, "\n"); exit (0); } int main (int argc, char *argv[]) { const char *orc_version; char *code; int i; char *output_file = NULL; char *input_file = NULL; char *include_file = NULL; char *compat_version = VERSION; FILE *output; OrcParseError **errors = NULL; int n_errors = 0; orc_init (); orc_version = orc_version_string (); if (strcmp (orc_version, VERSION) != 0) { fprintf (stderr, "WARNING: unexpected liborc library version %s is being " "picked up by %s, which is version %s. This might be because orc was " "installed from source and is also installed via packages, and liborc " "from the wrong prefix is used. Check your system setup.\n", orc_version, argv[0], VERSION); exit(1); } for(i=1;i= ORC_VERSION(0,4,11,1)) { use_code = TRUE; } if (output_file == NULL) { switch (mode) { case MODE_IMPL: output_file = "out.c"; break; case MODE_HEADER: output_file = "out.h"; break; case MODE_TEST: output_file = "out_test.c"; break; case MODE_ASSEMBLY: case MODE_BINARY: output_file = "out.s"; break; case MODE_PARSE: output_file = NULL; break; } } code = read_file (input_file); if (!code) { fprintf(stderr, "Could not read input file: %s\n", input_file); exit(1); } orc_parse_code (code, &programs, &n_programs, &errors, &n_errors); free(code); if (n_errors > 0) { int i; for (i=0;isource, errors[i]->line_number, errors[i]->text); } orc_parse_error_freev (errors); exit (1); } if (programs == NULL) { if (verbose) { fprintf(stderr, "no programs found\n"); } exit(1); } if (verbose) { fprintf(stderr, "%i program%s parsed\n", n_programs, (n_programs > 1) ?"s" :""); } if (mode == MODE_PARSE) { exit (0); } if (init_function == NULL) { init_function = orc_parse_get_init_function (programs[0]); } if (init_function == NULL) { use_lazy_init = TRUE; } output = fopen (output_file, "w"); if (!output) { fprintf(stderr, "Could not write output file: %s\n", output_file); exit(1); } fprintf(output, "\n"); fprintf(output, "/* autogenerated from %s */\n", my_basename(input_file)); fprintf(output, "\n"); if (mode == MODE_IMPL) { fprintf(output, "#ifdef HAVE_CONFIG_H\n"); fprintf(output, "#include \"config.h\"\n"); fprintf(output, "#endif\n"); if (include_file) { fprintf(output, "#include <%s>\n", include_file); } fprintf(output, "\n"); fprintf(output, "%s", orc_target_c_get_typedefs ()); fprintf(output, "\n"); fprintf(output, "#ifndef DISABLE_ORC\n"); fprintf(output, "#include \n"); fprintf(output, "#endif\n"); for(i=0;i\n", include_file); } fprintf(output, "\n"); fprintf(output, "#ifdef __cplusplus\n"); fprintf(output, "extern \"C\" {\n"); fprintf(output, "#endif\n"); fprintf(output, "\n"); if (init_function) { fprintf(output, "void %s (void);\n", init_function); fprintf(output, "\n"); } fprintf(output, "\n"); if (!use_inline) { fprintf(output, "\n"); fprintf(output, "%s", orc_target_c_get_typedefs ()); for(i=0;i\n"); fprintf(output, "\n"); for(i=0;i\n"); fprintf(output, "#include \n"); fprintf(output, "#include \n"); fprintf(output, "#include \n"); if (include_file) { fprintf(output, "#include <%s>\n", include_file); } fprintf(output, "\n"); fprintf(output, "%s", orc_target_c_get_typedefs ()); fprintf(output, "#include \n"); fprintf(output, "#include \n"); fprintf(output, "%s", orc_target_get_asm_preamble ("c")); fprintf(output, "\n"); if (use_backup) { for(i=0;iname); output_code_backup (programs[i], output); } } fprintf(output, "\n"); fprintf(output, "static int quiet = 0;\n"); fprintf(output, "static int benchmark = 0;\n"); fprintf(output, "\n"); fprintf(output, "static void help (const char *argv0)\n"); fprintf(output, "{\n"); fprintf(output, " fprintf(stderr, \"Usage:\\n\");\n"); fprintf(output, " fprintf(stderr, \" %%s [OPTION]\\n\", argv0);\n"); fprintf(output, " fprintf(stderr, \"Help Options:\\n\");\n"); fprintf(output, " fprintf(stderr, \" -h, --help Show help options\\n\");\n"); fprintf(output, " fprintf(stderr, \"Application Options:\\n\");\n"); fprintf(output, " fprintf(stderr, \" -b, --benchmark Run benchmark and show results\\n\");\n"); fprintf(output, " fprintf(stderr, \" -q, --quiet Don't output anything except on failures\\n\");\n"); fprintf(output, "\n"); fprintf(output, " exit(0);\n"); fprintf(output, "}\n"); fprintf(output, "\n"); fprintf(output, "int\n"); fprintf(output, "main (int argc, char *argv[])\n"); fprintf(output, "{\n"); fprintf(output, " int error = FALSE;\n"); fprintf(output, " int i;\n"); fprintf(output, "\n"); fprintf(output, " orc_test_init ();\n"); fprintf(output, "\n"); fprintf(output, " for(i=1;iname, t->name); ORC_ASSERT (l > 0); FILE *output = fopen (output_file, "wb"); if (!output) { fprintf (stderr, "Could not write output file: %s\n", output_file); break; } output_machine_code (programs[i], output); fclose (output); } if (error) { remove (output_file); } } } for(i=0;ibackup_name : p->name); need_comma = FALSE; for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { if (need_comma) fprintf(output, ", "); if (var->type_name) { fprintf(output, "%s * ORC_RESTRICT %s", orcify_typename(var->type_name), varnames[ORC_VAR_D1 + i]); } else { fprintf(output, "orc_uint%d * ORC_RESTRICT %s", var->size*8, varnames[ORC_VAR_D1 + i]); } if (p->is_2d) { fprintf(output, ", int %s_stride", varnames[ORC_VAR_D1 + i]); } need_comma = TRUE; } } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_A1 + i]; if (var->size) { if (need_comma) fprintf(output, ", "); if (var->type_name) { fprintf(output, "%s * ORC_RESTRICT %s", orcify_typename(var->type_name), varnames[ORC_VAR_A1 + i]); } else { fprintf(output, "orc_uint%d * ORC_RESTRICT %s", var->size*8, varnames[ORC_VAR_A1 + i]); } need_comma = TRUE; } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { if (need_comma) fprintf(output, ", "); if (var->type_name) { fprintf(output, "const %s * ORC_RESTRICT %s", orcify_typename(var->type_name), varnames[ORC_VAR_S1 + i]); } else { fprintf(output, "const orc_uint%d * ORC_RESTRICT %s", var->size*8, varnames[ORC_VAR_S1 + i]); } if (p->is_2d) { fprintf(output, ", int %s_stride", varnames[ORC_VAR_S1 + i]); } need_comma = TRUE; } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_P1 + i]; if (var->size) { if (need_comma) fprintf(output, ", "); switch (var->param_type) { case ORC_PARAM_TYPE_INT: fprintf(output, "int %s", varnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_FLOAT: REQUIRE(0,4,5,1); fprintf(output, "float %s", varnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_INT64: REQUIRE(0,4,7,1); fprintf(output, "orc_int64 %s", varnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_DOUBLE: REQUIRE(0,4,7,1); fprintf(output, "double %s", varnames[ORC_VAR_P1 + i]); break; default: ORC_ASSERT(0); } need_comma = TRUE; } } if (p->constant_n == 0) { if (need_comma) fprintf(output, ", "); fprintf(output, "int n"); need_comma = TRUE; } if (p->is_2d && p->constant_m == 0) { if (need_comma) fprintf(output, ", "); fprintf(output, "int m"); } fprintf(output, ")"); } void output_executor_backup_call (OrcProgram *p, FILE *output) { OrcVariable *var; int i; fprintf(output, " %s (", p->backup_name); for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { fprintf(output, "ex->arrays[%s], ", enumnames[ORC_VAR_D1 + i]); if (p->is_2d) { fprintf(output, "ex->params[%s], ", enumnames[ORC_VAR_D1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { fprintf(output, "ex->arrays[%s], ", enumnames[ORC_VAR_S1 + i]); if (p->is_2d) { fprintf(output, " ex->params[%s], ", enumnames[ORC_VAR_S1 + 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: fprintf(output, "ex->params[%s],", enumnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_FLOAT: fprintf(output, "((orc_union32 * )&ex->params[%s])->f, ", enumnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_INT64: fprintf(output, "(ex->params[%s] & 0xffffffff) | ((orc_uint64)(ex->params[%s]) << 32), ", enumnames[ORC_VAR_P1 + i], enumnames[ORC_VAR_T1 + i]); break; case ORC_PARAM_TYPE_DOUBLE: /* FIXME */ break; default: ORC_ASSERT(0); } } } if (p->constant_n) { fprintf(output, "%d", p->constant_n); } else { fprintf(output, "ex->n"); } if (p->is_2d) { if (p->constant_m) { fprintf(output, ", %d", p->constant_m); } else { fprintf(output, ", ORC_EXECUTOR_M(ex)"); } } fprintf(output, ");\n"); } void output_backup_call (OrcProgram *p, FILE *output) { OrcVariable *var; int i; fprintf(output, " %s (", p->backup_name); for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { fprintf(output, "%s, ", varnames[ORC_VAR_D1 + i]); if (p->is_2d) { fprintf(output, "%s_stride, ", varnames[ORC_VAR_D1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { fprintf(output, "%s, ", varnames[ORC_VAR_S1 + i]); if (p->is_2d) { fprintf(output, "%s_stride, ", varnames[ORC_VAR_S1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_P1 + i]; if (var->size) { fprintf(output, "%s, ", varnames[ORC_VAR_P1 + i]); } } if (p->constant_n) { fprintf(output, "%d", p->constant_n); } else { fprintf(output, "n"); } if (p->is_2d) { if (p->constant_m) { fprintf(output, ", %d", p->constant_m); } else { fprintf(output, ", m"); } } fprintf(output, ");\n"); } void output_code_header (OrcProgram *p, FILE *output) { if(use_internal) { fprintf(output, "ORC_INTERNAL void "); } else if (decorator != NULL) { fprintf(output, "%s void ", decorator); } else { fprintf(output, "void "); } output_prototype (p, output, 0); fprintf(output, ";\n"); if (p->backup_name && mode != MODE_TEST) { fprintf(output, "void "); output_prototype (p, output, 1); fprintf(output, ";\n"); } } void output_code_backup (OrcProgram *p, FILE *output) { fprintf(output, "static void\n"); if (compat < ORC_VERSION(0,4,7,1)) { fprintf(output, "_backup_%s (OrcExecutor * ex)\n", p->name); } else { fprintf(output, "_backup_%s (OrcExecutor * ORC_RESTRICT ex)\n", p->name); } fprintf(output, "{\n"); if (p->backup_name && mode != MODE_TEST) { output_executor_backup_call (p, output); } else { OrcCompileResult result; result = orc_program_compile_full (p, orc_target_get_by_name("c"), ORC_TARGET_C_BARE); if (ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { fprintf(output, "%s\n", orc_program_get_asm_code (p)); } else { fprintf(stderr, "Failed to compile backup code for '%s'\n", p->name); error = TRUE; } } fprintf(output, "}\n"); fprintf(output, "\n"); } void output_code_no_orc (OrcProgram *p, FILE *output) { fprintf(output, "void\n"); output_prototype (p, output, 0); fprintf(output, "{\n"); if (p->backup_name && mode != MODE_TEST) { output_backup_call (p, output); } else { OrcCompileResult result; result = orc_program_compile_full (p, orc_target_get_by_name("c"), ORC_TARGET_C_BARE | ORC_TARGET_C_NOEXEC); if (ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { fprintf(output, "%s\n", orc_program_get_asm_code (p)); } else { fprintf(stderr, "Failed to compile no orc for '%s'\n", p->name); error = TRUE; } } fprintf(output, "}\n"); fprintf(output, "\n"); } void output_code (OrcProgram *p, FILE *output) { fprintf(output, "\n"); fprintf(output, "/* %s */\n", p->name); fprintf(output, "#ifdef DISABLE_ORC\n"); output_code_no_orc (p, output); fprintf(output, "#else\n"); if (use_backup) { output_code_backup (p, output); } output_code_execute (p, output, FALSE); fprintf(output, "#endif\n"); fprintf(output, "\n"); } void output_code_execute (OrcProgram *p, FILE *output, int is_inline) { OrcVariable *var; int i; if (!use_lazy_init) { const char *storage; if (is_inline) { storage = "extern "; } else { if (use_inline) { storage = ""; } else { storage = "static "; } } if (use_code) { fprintf(output, "%sOrcCode *_orc_code_%s;\n", storage, p->name); } else { fprintf(output, "%sOrcProgram *_orc_program_%s;\n", storage, p->name); } } if (is_inline) { fprintf(output, "static inline void\n"); } else { fprintf(output, "void\n"); } output_prototype (p, output, 0); fprintf(output, "\n"); fprintf(output, "{\n"); fprintf(output, " OrcExecutor _ex, *ex = &_ex;\n"); if (!use_lazy_init) { if (use_code) { fprintf(output, " OrcCode *c = _orc_code_%s;\n", p->name); } else { fprintf(output, " OrcProgram *p = _orc_program_%s;\n", p->name); } } else { fprintf(output, " static OrcOnce once = ORC_ONCE_INIT;\n"); if (use_code) { fprintf(output, " OrcCode *c;\n"); } else { fprintf(output, " OrcProgram *p;\n"); } } fprintf(output, " OrcExecutorFunc func = NULL;\n"); fprintf(output, "\n"); if (use_lazy_init) { if (use_code) { fprintf(output, " if (!orc_once_enter (&once, (void **) &c)) {\n"); fprintf(output, " OrcProgram *p;\n"); } else { fprintf(output, " if (!orc_once_enter (&once, (void **) &p)) {\n"); } fprintf(output, "\n"); output_program_generation (p, output, is_inline); fprintf(output, "\n"); if (target) { fprintf(output, " orc_program_compile_for_target (p, orc_target_get_by_name (\"%s\"));\n", target); } else { fprintf(output, " orc_program_compile (p);\n"); } if (use_code) { fprintf(output, " c = orc_program_take_code (p);\n"); fprintf(output, " orc_program_free (p);\n"); fprintf(output, " orc_once_leave (&once, c);\n"); } else { fprintf(output, " orc_once_leave (&once, p);\n"); } fprintf(output, " }\n"); } if (use_code) { fprintf(output, " ex->arrays[ORC_VAR_A2] = c;\n"); fprintf(output, " ex->program = 0;\n"); } else { fprintf(output, " ex->program = p;\n"); } fprintf(output, "\n"); if (p->constant_n) { fprintf(output, " ex->n = %d;\n", p->constant_n); } else { fprintf(output, " ex->n = n;\n"); } if (p->is_2d) { if (p->constant_m) { fprintf(output, " ORC_EXECUTOR_M(ex) = %d;\n", p->constant_m); } else { fprintf(output, " ORC_EXECUTOR_M(ex) = m;\n"); } } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { fprintf(output, " ex->arrays[%s] = %s;\n", enumnames[ORC_VAR_D1 + i], varnames[ORC_VAR_D1 + i]); if (p->is_2d) { fprintf(output, " ex->params[%s] = %s_stride;\n", enumnames[ORC_VAR_D1 + i], varnames[ORC_VAR_D1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { fprintf(output, " ex->arrays[%s] = (void *)%s;\n", enumnames[ORC_VAR_S1 + i], varnames[ORC_VAR_S1 + i]); if (p->is_2d) { fprintf(output, " ex->params[%s] = %s_stride;\n", enumnames[ORC_VAR_S1 + i], varnames[ORC_VAR_S1 + 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: fprintf(output, " ex->params[%s] = %s;\n", enumnames[ORC_VAR_P1 + i], varnames[ORC_VAR_P1 + i]); break; case ORC_PARAM_TYPE_FLOAT: REQUIRE(0,4,5,1); fprintf(output, " {\n"); fprintf(output, " orc_union32 tmp;\n"); fprintf(output, " tmp.f = %s;\n", varnames[ORC_VAR_P1 + i]); fprintf(output, " ex->params[%s] = tmp.i;\n", enumnames[ORC_VAR_P1 + i]); fprintf(output, " }\n"); break; case ORC_PARAM_TYPE_INT64: REQUIRE(0,4,7,1); fprintf(output, " {\n"); fprintf(output, " orc_union64 tmp;\n"); fprintf(output, " tmp.i = %s;\n", varnames[ORC_VAR_P1 + i]); fprintf(output, " ex->params[%s] = ((orc_uint64) tmp.i) & 0xffffffff;\n", enumnames[ORC_VAR_P1 + i]); fprintf(output, " ex->params[%s] = ((orc_uint64) tmp.i) >> 32;\n", enumnames[ORC_VAR_T1 + i]); fprintf(output, " }\n"); break; case ORC_PARAM_TYPE_DOUBLE: REQUIRE(0,4,5,1); fprintf(output, " {\n"); fprintf(output, " orc_union64 tmp;\n"); fprintf(output, " tmp.f = %s;\n", varnames[ORC_VAR_P1 + i]); fprintf(output, " ex->params[%s] = ((orc_uint64) tmp.i) & 0xffffffff;\n", enumnames[ORC_VAR_P1 + i]); fprintf(output, " ex->params[%s] = ((orc_uint64) tmp.i) >> 32;\n", enumnames[ORC_VAR_T1 + i]); fprintf(output, " }\n"); break; default: ORC_ASSERT(0); } } } fprintf(output, "\n"); if (use_code) { fprintf(output, " func = c->exec;\n"); } else { fprintf(output, " func = p->code_exec;\n"); } fprintf(output, " func (ex);\n"); for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_A1 + i]; if (var->size) { fprintf(output, " *%s = orc_executor_get_accumulator (ex, %s);\n", varnames[ORC_VAR_A1 + i], enumnames[ORC_VAR_A1 + i]); } } fprintf(output, "}\n"); } void 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;ilength;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 (use_backup && !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;ilength;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 orc_bytecode_free (bytecode); 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", p->constant_n); } if (p->n_multiple != 0) { REQUIRE(0,4,14,1); fprintf(output, " orc_program_set_n_multiple (p, %d);\n", p->n_multiple); } if (p->n_minimum != 0) { REQUIRE(0,4,14,1); fprintf(output, " orc_program_set_n_minimum (p, %d);\n", p->n_minimum); } if (p->n_maximum != 0) { REQUIRE(0,4,14,1); fprintf(output, " orc_program_set_n_maximum (p, %d);\n", p->n_maximum); } if (p->is_2d) { fprintf(output, " orc_program_set_2d (p);\n"); if (p->constant_m != 0) { fprintf(output, " orc_program_set_constant_m (p, %d);\n", p->constant_m); } } fprintf(output, " orc_program_set_name (p, \"%s\");\n", p->name); if (use_backup && !is_inline) { fprintf(output, " orc_program_set_backup_function (p, _backup_%s);\n", p->name); } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { if (var->alignment != var->size) { REQUIRE(0,4,14,1); fprintf(output, " orc_program_add_destination_full (p, %d, \"%s\", 0, %d);\n", var->size, varnames[ORC_VAR_D1 + i], var->alignment); } else { fprintf(output, " orc_program_add_destination (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_D1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { if (var->alignment != var->size) { REQUIRE(0,4,14,1); fprintf(output, " orc_program_add_source_full (p, %d, \"%s\", 0, %d);\n", var->size, varnames[ORC_VAR_S1 + i], var->alignment); } else { fprintf(output, " orc_program_add_source (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_S1 + i]); } } } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_A1 + i]; if (var->size) { fprintf(output, " orc_program_add_accumulator (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_A1 + i]); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_C1 + i]; if (var->size == 0) continue; if (var->size <= 4) { fprintf(output, " orc_program_add_constant (p, %d, 0x%08x, \"%s\");\n", var->size, (int)var->value.i, varnames[ORC_VAR_C1 + i]); } else if (var->size > 4) { REQUIRE(0,4,8,1); fprintf(output, " orc_program_add_constant_int64 (p, %d, 0x%08x%08xULL, \"%s\");\n", var->size, (orc_uint32)(((orc_uint64)var->value.i)>>32), (orc_uint32)(var->value.i), varnames[ORC_VAR_C1 + i]); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_P1 + i]; if (var->size) { const char *suffix = NULL; switch (var->param_type) { case ORC_PARAM_TYPE_INT: suffix=""; break; case ORC_PARAM_TYPE_FLOAT: REQUIRE(0,4,5,1); suffix="_float"; break; case ORC_PARAM_TYPE_INT64: REQUIRE(0,4,7,1); suffix="_int64"; break; case ORC_PARAM_TYPE_DOUBLE: REQUIRE(0,4,7,1); suffix="_double"; break; default: ORC_ASSERT(0); } fprintf(output, " orc_program_add_parameter%s (p, %d, \"%s\");\n", suffix, var->size, varnames[ORC_VAR_P1 + i]); } } for(i=0;i<16;i++){ var = &p->vars[ORC_VAR_T1 + i]; if (var->size) { fprintf(output, " orc_program_add_temporary (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_T1 + i]); } } fprintf(output, "\n"); for(i=0;in_insns;i++){ OrcInstruction *insn = p->insns + i; if (compat < ORC_VERSION(0,4,6,1)) { if (insn->flags) { REQUIRE(0,4,6,1); } if (p->vars[insn->src_args[1]].size != 0) { fprintf(output, " orc_program_append (p, \"%s\", %s, %s, %s);\n", insn->opcode->name, enumnames[insn->dest_args[0]], enumnames[insn->src_args[0]], enumnames[insn->src_args[1]]); } else { fprintf(output, " orc_program_append_ds (p, \"%s\", %s, %s);\n", insn->opcode->name, enumnames[insn->dest_args[0]], enumnames[insn->src_args[0]]); } } else { int args[4] = { 0, 0, 0, 0 }; int n_args = 0; if (insn->opcode->dest_size[0] != 0) { args[n_args++] = insn->dest_args[0]; } if (insn->opcode->dest_size[1] != 0) { args[n_args++] = insn->dest_args[1]; } if (insn->opcode->src_size[0] != 0) { args[n_args++] = insn->src_args[0]; } if (insn->opcode->src_size[1] != 0) { args[n_args++] = insn->src_args[1]; } if (insn->opcode->src_size[2] != 0) { args[n_args++] = insn->src_args[2]; } fprintf(output, " orc_program_append_2 (p, \"%s\", %d, %s, %s, %s, %s);\n", insn->opcode->name, insn->flags, enumnames[args[0]], enumnames[args[1]], enumnames[args[2]], enumnames[args[3]]); } } if (ORC_VERSION(0,4,16,1) <= compat) { fprintf(output, "#endif\n"); } } void output_init_function (FILE *output) { int i; fprintf(output, "void\n"); fprintf(output, "%s (void)\n", init_function); fprintf(output, "{\n"); if (!use_lazy_init) { fprintf(output, "#ifndef DISABLE_ORC\n"); for(i=0;iname); fprintf(output, " OrcProgram *p;\n"); fprintf(output, "\n"); output_program_generation (programs[i], output, FALSE); fprintf(output, "\n"); fprintf(output, " orc_program_compile (p);\n"); fprintf(output, "\n"); if (use_code) { fprintf(output, " _orc_code_%s = orc_program_take_code (p);\n", programs[i]->name); fprintf(output, " orc_program_free (p);\n"); } else { fprintf(output, " _orc_program_%s = p;\n", programs[i]->name); } fprintf(output, " }\n"); } fprintf(output, "#endif\n"); } fprintf(output, "}\n"); fprintf(output, "\n"); } void output_code_test (OrcProgram *p, FILE *output) { OrcVariable *var; int i; fprintf(output, " /* %s */\n", p->name); fprintf(output, " {\n"); fprintf(output, " OrcProgram *p = NULL;\n"); fprintf(output, " int ret;\n"); fprintf(output, " int flags = ORC_TEST_SKIP_RESET;"); fprintf(output, "\n"); fprintf(output, " if (!quiet)"); fprintf(output, " printf (\"%s:\\n\");\n", p->name); fprintf(output, " p = orc_program_new ();\n"); if (p->constant_n != 0) { fprintf(output, " orc_program_set_constant_n (p, %d);\n", p->constant_n); } if (p->is_2d) { fprintf(output, " orc_program_set_2d (p);\n"); if (p->constant_m != 0) { fprintf(output, " orc_program_set_constant_m (p, %d);\n", p->constant_m); } } fprintf(output, " orc_program_set_name (p, \"%s\");\n", p->name); if (use_backup) { fprintf(output, " orc_program_set_backup_function (p, _backup_%s);\n", p->name); } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_D1 + i]; if (var->size) { fprintf(output, " orc_program_add_destination (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_D1 + i]); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_S1 + i]; if (var->size) { fprintf(output, " orc_program_add_source (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_S1 + i]); } } for(i=0;i<4;i++){ var = &p->vars[ORC_VAR_A1 + i]; if (var->size) { fprintf(output, " orc_program_add_accumulator (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_A1 + i]); } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_C1 + i]; if (var->size) { if (var->size < 8) { fprintf(output, " orc_program_add_constant (p, %d, 0x%08x, \"%s\");\n", var->size, (int)var->value.i, varnames[ORC_VAR_C1 + i]); } else { fprintf(output, " orc_program_add_constant_int64 (p, %d, " "0x%08x%08xULL, \"%s\");\n", var->size, (orc_uint32)(((orc_uint64)var->value.i)>>32), (orc_uint32)(var->value.i), varnames[ORC_VAR_C1 + i]); } } } for(i=0;i<8;i++){ var = &p->vars[ORC_VAR_P1 + i]; if (var->size) { const char *suffix = NULL; switch (var->param_type) { case ORC_PARAM_TYPE_INT: suffix=""; break; case ORC_PARAM_TYPE_FLOAT: REQUIRE(0,4,5,1); suffix="_float"; break; case ORC_PARAM_TYPE_INT64: REQUIRE(0,4,7,1); suffix="_int64"; break; case ORC_PARAM_TYPE_DOUBLE: REQUIRE(0,4,7,1); suffix="_double"; break; default: ORC_ASSERT(0); } fprintf(output, " orc_program_add_parameter%s (p, %d, \"%s\");\n", suffix, var->size, varnames[ORC_VAR_P1 + i]); } } for(i=0;i<16;i++){ var = &p->vars[ORC_VAR_T1 + i]; if (var->size) { fprintf(output, " orc_program_add_temporary (p, %d, \"%s\");\n", var->size, varnames[ORC_VAR_T1 + i]); } } fprintf(output, "\n"); for(i=0;in_insns;i++){ OrcInstruction *insn = p->insns + i; if (compat < ORC_VERSION(0,4,6,1)) { if (insn->flags) { REQUIRE(0,4,6,1); } if (p->vars[insn->src_args[1]].size != 0) { fprintf(output, " orc_program_append (p, \"%s\", %s, %s, %s);\n", insn->opcode->name, enumnames[insn->dest_args[0]], enumnames[insn->src_args[0]], enumnames[insn->src_args[1]]); } else { fprintf(output, " orc_program_append_ds (p, \"%s\", %s, %s);\n", insn->opcode->name, enumnames[insn->dest_args[0]], enumnames[insn->src_args[0]]); } } else { int args[4] = { 0, 0, 0, 0 }; int n_args = 0; if (insn->opcode->dest_size[0] != 0) { args[n_args++] = insn->dest_args[0]; } if (insn->opcode->dest_size[1] != 0) { args[n_args++] = insn->dest_args[1]; } if (insn->opcode->src_size[0] != 0) { args[n_args++] = insn->src_args[0]; } if (insn->opcode->src_size[1] != 0) { args[n_args++] = insn->src_args[1]; } if (insn->opcode->src_size[2] != 0) { args[n_args++] = insn->src_args[2]; } fprintf(output, " orc_program_append_2 (p, \"%s\", %d, %s, %s, %s, %s);\n", insn->opcode->name, insn->flags, enumnames[args[0]], enumnames[args[1]], enumnames[args[2]], enumnames[args[3]]); } } fprintf(output, "\n"); if (compat >= ORC_VERSION(0,4,7,1)) { fprintf(output, " if (benchmark) {\n"); fprintf(output, " printf (\" cycles (emulate) : %%g\\n\",\n"); fprintf(output, " orc_test_performance_full (p, ORC_TEST_FLAGS_EMULATE, NULL));\n"); fprintf(output, " }\n"); fprintf(output, "\n"); } if (use_backup) { fprintf(output, " ret = orc_test_compare_output_full (p, ORC_TEST_FLAGS_BACKUP | flags);\n"); fprintf(output, " if (ret == ORC_TEST_INDETERMINATE) {\n"); fprintf(output, " printf (\" backup function : COMPILE FAILED (%%s)\\n\", p->error_msg);\n"); fprintf(output, " } else if (!ret) {\n"); fprintf(output, " error = TRUE;\n"); fprintf(output, " printf (\" backup function : FAILED\\n\");\n"); fprintf(output, " } else if (!quiet) {\n"); fprintf(output, " printf (\" backup function : PASSED\\n\");\n"); fprintf(output, " }\n"); fprintf(output, "\n"); if (compat >= ORC_VERSION(0,4,7,1)) { fprintf(output, " if (benchmark) {\n"); fprintf(output, " orc_program_reset (p);"); fprintf(output, " printf (\" cycles (backup) : %%g\\n\",\n"); fprintf(output, " orc_test_performance_full (p, ORC_TEST_FLAGS_BACKUP, NULL));\n"); fprintf(output, " }\n"); fprintf(output, "\n"); } } fprintf(output, " orc_program_reset (p);"); fprintf(output, " ret = orc_test_compare_output_full (p, flags);\n"); fprintf(output, " if (ret == ORC_TEST_INDETERMINATE && !quiet) {\n"); fprintf(output, " printf (\" compiled function: COMPILE FAILED (%%s)\\n\", p->error_msg);\n"); fprintf(output, " } else if (!ret) {\n"); fprintf(output, " error = TRUE;\n"); fprintf(output, " printf (\" compiled function: FAILED\\n\");\n"); fprintf(output, " } else if (!quiet) {\n"); fprintf(output, " printf (\" compiled function: PASSED\\n\");\n"); fprintf(output, " }\n"); fprintf(output, "\n"); if (compat >= ORC_VERSION(0,4,7,1)) { fprintf(output, " if (benchmark) {\n"); fprintf(output, " orc_program_reset (p);"); fprintf(output, " printf (\" cycles (compiled): %%g\\n\",\n"); fprintf(output, " orc_test_performance_full (p, 0, NULL));\n"); fprintf(output, " }\n"); } fprintf(output, "\n"); fprintf(output, " orc_program_free (p);\n"); fprintf(output, " }\n"); fprintf(output, "\n"); } void output_code_assembly (OrcProgram *p, FILE *output) { fprintf(output, "/* %s */\n", p->name); /* output_prototype (p, output); */ { OrcCompileResult result; OrcTarget *t = orc_target_get_by_name(target); result = orc_program_compile_full (p, t, orc_target_get_default_flags (t)); if (ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { fprintf(output, "%s\n", orc_program_get_asm_code (p)); } else { fprintf(stderr, "Failed to compile assembly for '%s'\n", p->name); error = TRUE; } } fprintf(output, "\n"); } void output_machine_code (OrcProgram *p, FILE *output) { OrcTarget *const t = orc_target_get_by_name(target); const OrcCompileResult result = orc_program_compile_for_target (p, t); if (ORC_COMPILE_RESULT_IS_SUCCESSFUL(result)) { fwrite (p->orccode->code, sizeof(unsigned char), p->orccode->code_size, output); } else { fprintf(stderr, "Failed to compile assembly for '%s'\n", p->name); error = TRUE; } } static const char * my_basename (const char *s) { const char *ret = s; const char *t; t = s; while (t[0] != 0) { if (t[0] == '/') ret = t+1; t++; } return ret; }