int main(int argc, char* argv[]){ int pos = 5; int val = 3; generate_function("my_func", SIZE, pos, val); return 0; }
void generate ( node_t *root ) { if ( root == NULL ) return; switch ( root->type ) { case PROGRAM_N: //Generate data head printf(DATA_HEAD); //Generate unique labels for strings generate_data_segment(root); //Create an entry point printf(TEXT_HEAD, root->children[0]->children[0]->entry->label ); for (int i=0; i<root->n_children; i++ ) { generate(root->children[i]); } break; case FUNCTION_LIST_N: ; for (int i=0; i<root->n_children; i++ ) { generate(root->children[i]); } break; case FUNCTION_N: generate_function(root); generate(root->children[2]); break; case BLOCK_N: for (int i=0; i<root->n_children; i++ ) { generate(root->children[i]); } break; case DECLARATION_LIST_N: for (int i=0; i<root->n_children; i++ ) { generate(root->children[i]); } break; case DECLARATION_N: generate_declaration(root); break; case STATEMENT_LIST_N: for (int i=0; i<root->n_children; i++ ) { generate(root->children[i]); } break; case ASSIGNMENT_STATEMENT_N: assign_bound_name(root); break; case RETURN_STATEMENT_N: //The result is also an expression generate_expression(root->children[0]); printf("\t pushl %%eax \t /*Push of the final result*/\n"); printf("\t ret \t /*Return control*/\n"); break; case PRINT_STATEMENT_N: break; case NULL_STATEMENT_N: /* A proper implementation of the CONTINUE statement is more * trouble than it is worth at this point; since it is not the * most central of features, we skip it. * (Of course, if you really want to make one...) */ printf ( "\t/* CONTINUE */\n" ); break; case IF_STATEMENT_N: break; case WHILE_STATEMENT_N: break; case EXPRESSION_N: case INTEGER_N: case VARIABLE_N: generate_expression(root); break; default: fprintf ( stderr, "Warning: did not generate assembly for '%s'\n", root->type); break; } }
static code_block *generate_block(code_block *parent, block_statement *block, block_iter iter, void *iter_data) { for (symbol_entry *c = block->class_head; c; c = c->next) { generate_class_stub(parent->system, c->classtype); } for (symbol_entry *f = block->function_head; f; f = f->next) { generate_function_stub(parent->system, f->function); } for (symbol_entry *c = block->class_head; c; c = c->next) { generate_class(parent->system, c->classtype); } for (symbol_entry *f = block->function_head; f; f = f->next) { generate_function(parent->system, f->function); } for (statement *node = block->body; node; node = node->next) { switch (node->type) { case S_BLOCK: { code_block *body = fork_block(parent); body = generate_block(body, (block_statement*) node, NULL, NULL); parent = rejoin_block(parent, body); } break; case S_BREAK: case S_CONTINUE: generate_control(parent, (control_statement*) node); parent = NULL; break; case S_DEFINE: parent = generate_define(parent, (define_statement*) node); break; case S_LET: parent = generate_let(parent, (let_statement*) node); break; case S_DO_WHILE: case S_WHILE: parent = generate_loop(parent, (loop_statement*) node); break; case S_EXPRESSION: { expression_statement *express = (expression_statement*) node; parent = generate_expression(parent, express->value); } break; case S_IF: parent = generate_if(parent, (if_statement*) node); break; case S_RETURN: generate_return(parent, (return_statement*) node); parent = NULL; break; // already processed case S_CLASS: case S_FUNCTION: case S_TYPEDEF: break; } // most recently processed statement terminates abruptly if (parent == NULL) { if (node->next) { fprintf(stderr, "not reachable\n"); } return NULL; } if (iter != NULL) { iter(parent, iter_data); } } return parent; }
void i_generate_node (parse_node_t * expr) { if (!expr) return; if (expr->line && expr->line != line_being_generated) switch_to_line(expr->line); switch (expr->kind) { case NODE_FUNCTION: { unsigned short num; /* In the following we know that this function wins all the */ /* rest - Sym */ num = FUNCTION_TEMP(expr->v.number)->u.index; FUNC(num)->address = generate_function(FUNC(num), expr->r.expr, expr->l.number); break; } case NODE_TERNARY_OP: i_generate_node(expr->l.expr); expr = expr->r.expr; case NODE_BINARY_OP: i_generate_node(expr->l.expr); /* fall through */ case NODE_UNARY_OP: i_generate_node(expr->r.expr); /* fall through */ case NODE_OPCODE: end_pushes(); ins_byte(expr->v.number); break; case NODE_TERNARY_OP_1: i_generate_node(expr->l.expr); expr = expr->r.expr; /* fall through */ case NODE_BINARY_OP_1: i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); end_pushes(); ins_byte(expr->v.number); ins_byte(expr->type); break; case NODE_UNARY_OP_1: i_generate_node(expr->r.expr); /* fall through */ case NODE_OPCODE_1: if (expr->v.number == F_LOCAL) { if (try_to_push(PUSH_LOCAL, expr->l.number)) break; } else if (expr->v.number == F_GLOBAL) { if (try_to_push(PUSH_GLOBAL, expr->l.number)) break; } end_pushes(); ins_byte(expr->v.number); ins_byte(expr->l.number); break; case NODE_OPCODE_2: end_pushes(); ins_byte(expr->v.number); ins_byte(expr->l.number); if (expr->v.number == F_LOOP_COND_NUMBER) #if SIZEOF_LONG == 8 ins_long(expr->r.number); #else ins_int(expr->r.number); #endif else ins_byte(expr->r.number); break; case NODE_RETURN: { int n; n = foreach_depth; end_pushes(); while (n--) ins_byte(F_EXIT_FOREACH); if (expr->r.expr) { i_generate_node(expr->r.expr); end_pushes(); ins_byte(F_RETURN); } else ins_byte(F_RETURN_ZERO); break; } case NODE_STRING: if (try_to_push(PUSH_STRING, expr->v.number)) break; if (expr->v.number <= 0xff) { ins_byte(F_SHORT_STRING); ins_byte(expr->v.number); } else { ins_byte(F_STRING); ins_short(expr->v.number); } break; case NODE_REAL: end_pushes(); ins_byte(F_REAL); ins_real(expr->v.real); break; case NODE_NUMBER: write_number(expr->v.number); break; case NODE_LAND_LOR: i_generate_node(expr->l.expr); i_generate_forward_branch(expr->v.number); i_generate_node(expr->r.expr); if (expr->l.expr->kind == NODE_BRANCH_LINK) i_update_forward_branch_links(expr->v.number,expr->l.expr); else i_update_forward_branch("&& or ||"); break; case NODE_BRANCH_LINK: i_generate_node(expr->l.expr); end_pushes(); ins_byte(0); expr->v.number = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); break; case NODE_CALL_2: generate_expr_list(expr->r.expr); end_pushes(); ins_byte(expr->v.number); ins_byte(expr->l.number >> 16); ins_short(expr->l.number & 0xffff); ins_byte((expr->r.expr ? expr->r.expr->kind : 0)); break; case NODE_CALL_1: generate_expr_list(expr->r.expr); end_pushes(); if (expr->v.number == F_CALL_FUNCTION_BY_ADDRESS) { expr->l.number = comp_def_index_map[expr->l.number]; } ins_byte(expr->v.number); ins_short(expr->l.number); ins_byte((expr->r.expr ? expr->r.expr->kind : 0)); break; case NODE_CALL: generate_expr_list(expr->r.expr); end_pushes(); ins_byte(expr->v.number); ins_short(expr->l.number); break; case NODE_TWO_VALUES: i_generate_node(expr->l.expr); i_generate_node(expr->r.expr); break; case NODE_CONTROL_JUMP: { int kind = expr->v.number; end_pushes(); ins_byte(F_BRANCH); expr->v.expr = branch_list[kind]; expr->l.number = CURRENT_PROGRAM_SIZE; ins_short(0); branch_list[kind] = expr; break; } case NODE_PARAMETER: { int which = expr->v.number + current_num_values; if (try_to_push(PUSH_LOCAL, which)) break; ins_byte(F_LOCAL); ins_byte(which); break; } case NODE_PARAMETER_LVALUE: end_pushes(); ins_byte(F_LOCAL_LVALUE); ins_byte(expr->v.number + current_num_values); break; case NODE_IF: i_generate_if_branch(expr->v.expr, 0); i_generate_node(expr->l.expr); if (expr->r.expr) { i_generate_else(); i_generate_node(expr->r.expr); } i_update_forward_branch("if"); break; case NODE_LOOP: i_generate_loop(expr->type, expr->v.expr, expr->l.expr, expr->r.expr); break; case NODE_FOREACH: { int tmp = 0; i_generate_node(expr->v.expr); end_pushes(); ins_byte(F_FOREACH); if (expr->l.expr->v.number == F_GLOBAL_LVALUE) tmp |= FOREACH_RIGHT_GLOBAL; else if (expr->l.expr->v.number == F_REF_LVALUE) tmp |= FOREACH_REF; if (expr->r.expr) { if (tmp & FOREACH_RIGHT_GLOBAL) tmp = (tmp & ~FOREACH_RIGHT_GLOBAL) | FOREACH_LEFT_GLOBAL; tmp |= FOREACH_MAPPING; if (expr->r.expr->v.number == F_GLOBAL_LVALUE) tmp |= FOREACH_RIGHT_GLOBAL; else if (expr->r.expr->v.number == F_REF_LVALUE) tmp |= FOREACH_REF; } ins_byte(tmp); ins_byte(expr->l.expr->l.number); if (expr->r.expr) ins_byte(expr->r.expr->l.number); } break; case NODE_CASE_NUMBER: case NODE_CASE_STRING: if (expr->v.expr) { parse_node_t *other = expr->v.expr; expr->v.number = 1; other->l.expr = expr->l.expr; other->v.number = CURRENT_PROGRAM_SIZE; expr->l.expr = other; } else { expr->v.number = CURRENT_PROGRAM_SIZE; } end_pushes(); break; case NODE_DEFAULT: expr->v.number = CURRENT_PROGRAM_SIZE; end_pushes(); break; case NODE_SWITCH_STRINGS: case NODE_SWITCH_NUMBERS: case NODE_SWITCH_DIRECT: case NODE_SWITCH_RANGES: { long addr, last_break; parse_node_t *sub = expr->l.expr; parse_node_t *save_switch_breaks = branch_list[CJ_BREAK_SWITCH]; i_generate_node(sub); branch_list[CJ_BREAK_SWITCH] = 0; end_pushes(); ins_byte(F_SWITCH); addr = CURRENT_PROGRAM_SIZE; /* all these are addresses in here are relative to addr now, * which is also the value of pc in f_switch(). Note that * addr is one less than it was in older drivers. */ ins_byte(0xff); /* kind of table */ ins_short(0); /* address of table */ ins_short(0); /* end of table */ ins_short(0); /* default address */ i_generate_node(expr->r.expr); if (expr->v.expr && expr->v.expr->kind == NODE_DEFAULT) { upd_short(addr + 5, expr->v.expr->v.number - addr, "switch"); expr->v.expr = expr->v.expr->l.expr; } else { upd_short(addr + 5, CURRENT_PROGRAM_SIZE - addr, "switch"); } /* just in case the last case doesn't have a break */ end_pushes(); ins_byte(F_BRANCH); last_break = CURRENT_PROGRAM_SIZE; ins_short(0); /* build table */ upd_short(addr + 1, CURRENT_PROGRAM_SIZE - addr, "switch"); #ifdef BINARIES if (pragmas & PRAGMA_SAVE_BINARY) { if (expr->kind == NODE_SWITCH_STRINGS) { short sw; sw = addr - 1; add_to_mem_block(A_PATCH, (char *)&sw, sizeof sw); } } #endif if (expr->kind == NODE_SWITCH_DIRECT) { parse_node_t *pn = expr->v.expr; while (pn) { ins_rel_short(pn->v.number - addr); pn = pn->l.expr; } ins_int(expr->v.expr->r.number); mem_block[A_PROGRAM].block[addr] = (char)0xfe; } else { int table_size = 0; int power_of_two = 1; int i = 0; parse_node_t *pn = expr->v.expr; while (pn) { if (expr->kind == NODE_SWITCH_STRINGS) { if (pn->r.number) { INS_POINTER((POINTER_INT) PROG_STRING(pn->r.number)); } else INS_POINTER((POINTER_INT)0); } else INS_POINTER((POINTER_INT)pn->r.expr); if (pn->v.number == 1) ins_short(1); else ins_rel_short(pn->v.number - addr); pn = pn->l.expr; table_size += 1; } while ((power_of_two<<1) <= table_size) { power_of_two <<= 1; i++; } if (expr->kind != NODE_SWITCH_STRINGS) mem_block[A_PROGRAM].block[addr] = (char)(0xf0+i); else mem_block[A_PROGRAM].block[addr] = (char)(i*0x10+0x0f); } i_update_branch_list(branch_list[CJ_BREAK_SWITCH], "switch break"); branch_list[CJ_BREAK_SWITCH] = save_switch_breaks; upd_short(last_break, CURRENT_PROGRAM_SIZE - last_break, "switch break"); upd_short(addr+3, CURRENT_PROGRAM_SIZE - addr, "switch"); break; } case NODE_CATCH: { int addr; end_pushes(); ins_byte(F_CATCH); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); ins_byte(F_END_CATCH); upd_short(addr, CURRENT_PROGRAM_SIZE - addr, "catch"); break; } case NODE_TIME_EXPRESSION: { end_pushes(); ins_byte(F_TIME_EXPRESSION); i_generate_node(expr->r.expr); ins_byte(F_END_TIME_EXPRESSION); break; } case NODE_LVALUE_EFUN: i_generate_node(expr->l.expr); generate_lvalue_list(expr->r.expr); break; case NODE_FUNCTION_CONSTRUCTOR: if (expr->r.expr) { generate_expr_list(expr->r.expr); end_pushes(); ins_byte(F_AGGREGATE); ins_short(expr->r.expr->kind); } else { end_pushes(); ins_byte(F_CONST0); } end_pushes(); ins_byte(F_FUNCTION_CONSTRUCTOR); ins_byte(expr->v.number & 0xff); switch (expr->v.number & 0xff) { case FP_SIMUL: ins_short(expr->v.number >> 8); break; case FP_LOCAL: ins_short(comp_def_index_map[expr->v.number >> 8]); break; case FP_EFUN: ins_short(predefs[expr->v.number >> 8].token); break; case FP_FUNCTIONAL: case FP_FUNCTIONAL | FP_NOT_BINDABLE: { int addr, save_current_num_values = current_num_values; ins_byte(expr->v.number >> 8); addr = CURRENT_PROGRAM_SIZE; ins_short(0); current_num_values = expr->r.expr ? expr->r.expr->kind : 0; i_generate_node(expr->l.expr); current_num_values = save_current_num_values; end_pushes(); ins_byte(F_RETURN); upd_short(addr, CURRENT_PROGRAM_SIZE - addr - 2, "function pointer"); break; } } break; case NODE_ANON_FUNC: { int addr; int save_fd = foreach_depth; foreach_depth = 0; end_pushes(); ins_byte(F_FUNCTION_CONSTRUCTOR); if (expr->v.number & 0x10000) ins_byte(FP_ANONYMOUS | FP_NOT_BINDABLE); else ins_byte(FP_ANONYMOUS); ins_byte(expr->v.number & 0xff); ins_byte(expr->l.number); addr = CURRENT_PROGRAM_SIZE; ins_short(0); i_generate_node(expr->r.expr); upd_short(addr, CURRENT_PROGRAM_SIZE - addr - 2, "function pointer"); foreach_depth = save_fd; break; } case NODE_EFUN: { int novalue_used = expr->v.number & NOVALUE_USED_FLAG; int f = expr->v.number & ~NOVALUE_USED_FLAG; generate_expr_list(expr->r.expr); end_pushes(); if (f < ONEARG_MAX) { ins_byte(f); } else { /* max_arg == -1 must use F_EFUNV so that varargs expansion works*/ if (expr->l.number < 4 && instrs[f].max_arg != -1) ins_byte(F_EFUN0 + expr->l.number); else { ins_byte(F_EFUNV); ins_byte(expr->l.number); } ins_byte(f - ONEARG_MAX); } if (novalue_used) { /* the value of a void efun was used. Put in a zero. */ ins_byte(F_CONST0); } break; } default: fatal("Unknown node %i in i_generate_node.\n", expr->kind); }
void main_cuc (char *filename) { int i, j; char tmp1[256]; char filename_cut[256]; #if 0 /* Select prefix, based on binary program name */ for (i = 0; i < sizeof (filename_cut); i++) { if (isalpha (filename[i])) filename_cut[i] = filename[i]; else { filename_cut[i] = '\0'; break; } } #else strcpy (filename_cut, "cu"); #endif PRINTF ("Entering OpenRISC Custom Unit Compiler command prompt\n"); PRINTF ("Using profile file \"%s\" and memory profile file \"%s\".\n", config.sim.prof_fn, config.sim.mprof_fn); sprintf (tmp1, "%s.log", filename_cut); PRINTF ("Analyzing. (log file \"%s\").\n", tmp1); assert (flog = fopen (tmp1, "wt+")); /* Loads in the specified timings table */ PRINTF ("Using timings from \"%s\" at %s\n", config.cuc.timings_fn, generate_time_pretty (tmp1, config.sim.clkcycle_ps)); load_timing_table (config.cuc.timings_fn); runtime.cuc.cycle_duration = 1000. * config.sim.clkcycle_ps; PRINTF ("Multicycle logic %s, bursts %s, %s memory order.\n", config.cuc.no_multicycle ? "OFF" : "ON", config.cuc.enable_bursts ? "ON" : "OFF", config.cuc.memory_order == MO_NONE ? "no" : config.cuc.memory_order == MO_WEAK ? "weak" : config.cuc.memory_order == MO_STRONG ? "strong" : "exact"); prof_set (1, 0); assert (prof_acquire (config.sim.prof_fn) == 0); if (config.cuc.calling_convention) PRINTF ("Assuming OpenRISC standard calling convention.\n"); /* Try all functions except "total" */ for (i = 0; i < prof_nfuncs - 1; i++) { long orig_time; unsigned long start_addr, end_addr; orig_time = prof_func[i].cum_cycles; start_addr = prof_func[i].addr; /* Extract the function from the binary */ sprintf (tmp1, "%s.bin", prof_func[i].name); end_addr = extract_function (tmp1, start_addr); log ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name, start_addr, end_addr); PRINTF ("Testing function %s (%08lx - %08lx)\n", prof_func[i].name, start_addr, end_addr); func[i] = analyse_function (prof_func[i].name, orig_time, start_addr, end_addr, config.cuc.memory_order, prof_func[i].calls); func_v[i] = 0; } set_func_deps (); while (1) { char *s; wait_command: PRINTF ("(cuc) "); fflush (stdout); wait_command_empty: s = fgets (tmp1, sizeof tmp1, stdin); usleep (100); if (!s) goto wait_command_empty; for (s = tmp1; *s != '\0' && *s != '\n' && *s != '\r'; s++); *s = '\0'; /* quit command */ if (strcmp (tmp1, "q") == 0 || strcmp (tmp1, "quit") == 0) { /* Delete temporary files */ for (i = 0; i < prof_nfuncs - 1; i++) { sprintf (tmp1, "%s.bin", prof_func[i].name); log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK"); sprintf (tmp1, "%s.bin.bb", prof_func[i].name); log ("Deleting temporary file %s %s\n", tmp1, remove (tmp1) ? "FAILED" : "OK"); } break; /* profile command */ } else if (strcmp (tmp1, "p") == 0 || strcmp (tmp1, "profile") == 0) { int ntime = 0; int size = 0; PRINTF ("-----------------------------------------------------------------------------\n"); PRINTF ("|function name |calls|avg cycles |old%%| max. f. | impr. f.| options |\n"); PRINTF ("|--------------------+-----+------------+----+----------|---------+---------|\n"); for (j = 0; j < prof_nfuncs; j++) { int bestcyc = 0, besti = 0; char tmp[100]; for (i = 0; i < prof_nfuncs; i++) if (prof_func[i].cum_cycles > bestcyc) { bestcyc = prof_func[i].cum_cycles; besti = i; } i = besti; PRINTF ("|%-20s|%5li|%12.1f|%3.0f%%| ", strstrip (tmp, prof_func[i].name, 20), prof_func[i].calls, ((double) prof_func[i].cum_cycles / prof_func[i].calls), (100. * prof_func[i].cum_cycles / prof_cycles)); if (func[i]) { double f = 1.0; if (func_v[i]) { int nt = calc_cycles (func[i]); int s = calc_size (func[i]); f = 1. * func[i]->orig_time / nt; ntime += nt; size += s; } else ntime += prof_func[i].cum_cycles; PRINTF ("%8.1f |%8.1f | %-8s|\n", 1.f * prof_func[i].cum_cycles / func[i]->timings.new_time, f, format_func_options (tmp, func[i])); } else { PRINTF (" N/A | N/A | N/A |\n"); ntime += prof_func[i].cum_cycles; } prof_func[i].cum_cycles = -prof_func[i].cum_cycles; } for (i = 0; i < prof_nfuncs; i++) prof_func[i].cum_cycles = -prof_func[i].cum_cycles; PRINTF ("-----------------------------------------------------------------------------\n"); PRINTF ("Total %i cycles (was %i), total added gates = %i. Speed factor %.1f\n", ntime, prof_cycles, size, 1. * prof_cycles / ntime); /* debug command */ } else if (strncmp (tmp1, "d", 1) == 0 || strncmp (tmp1, "debug", 5) == 0) { sscanf (tmp1, "%*s %i", &cuc_debug); if (cuc_debug < 0) cuc_debug = 0; if (cuc_debug > 9) cuc_debug = 9; /* generate command */ } else if (strcmp (tmp1, "g") == 0 || strcmp (tmp1, "generate") == 0) { /* check for function dependencies */ for (i = 0; i < prof_nfuncs; i++) if (func[i]) func[i]->tmp = func_v[i]; for (i = 0; i < prof_nfuncs; i++) if (func[i]) for (j = 0; j < func[i]->nfdeps; j++) if (!func[i]->fdeps[j] || !func[i]->fdeps[j]->tmp) { PRINTF ("Function %s must be selected for translation (required by %s)\n", prof_func[j].name, prof_func[i].name); goto wait_command; } for (i = 0; i < prof_nfuncs; i++) if (func[i] && func_v[i]) generate_function (func[i], prof_func[i].name, filename_cut); generate_main (prof_nfuncs, func, filename_cut); /* list command */ } else if (strcmp (tmp1, "l") == 0 || strcmp (tmp1, "list") == 0) { /* check for function dependencies */ for (i = 0; i < prof_nfuncs; i++) if (func_v[i]) { PRINTF ("%s\n", prof_func[i].name); } /* selectall command */ } else if (strcmp (tmp1, "sa") == 0 || strcmp (tmp1, "selectall") == 0) { int f; for (f = 0; f < prof_nfuncs; f++) if (func[f]) { func_v[f] = 1; PRINTF ("Function %s selected for translation.\n", prof_func[f].name); } /* select command */ } else if (strncmp (tmp1, "s", 1) == 0 || strncmp (tmp1, "select", 6) == 0) { char tmp[50], ch; int p, o, b, f; p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch); if (p < 1) PRINTF ("Invalid parameters.\n"); else { /* Check if we have valid option */ for (f = 0; f < prof_nfuncs; f++) if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break; if (f < prof_nfuncs) { if (p == 1) { if (func[f]) { func_v[f] = 1; PRINTF ("Function %s selected for translation.\n", prof_func[f].name); } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name); } else { if (!func_v[f]) PRINTF ("Function %s not yet selected for translation.\n", prof_func[f].name); if (p < 3) goto invalid_option; for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++); if (!option_char[o]) goto invalid_option; if (b < 0 || b >= func[f]->num_bb) goto invalid_option; if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option; /* select an option */ func[f]->bb[b].selected_tim = o; if (func[f]->bb[b].tim[o].nshared) { PRINTF ("Option has shared instructions: "); print_shared (func[f], func[f]->bb[b].tim[o].shared, func[f]->bb[b].tim[o].nshared); PRINTF ("\n"); } goto wait_command; invalid_option: PRINTF ("Invalid option.\n"); } } else PRINTF ("Invalid function.\n"); } /* unselect command */ } else if (strncmp (tmp1, "u", 1) == 0 || strncmp (tmp1, "unselect", 8) == 0) { char tmp[50], ch; int p, o, b, f; p = sscanf (tmp1, "%*s %s %i%c", tmp, &b, &ch); if (p < 1) PRINTF ("Invalid parameters.\n"); else { /* Check if we have valid option */ for (f = 0; f < prof_nfuncs; f++) if (strcmp (prof_func[f].name, tmp) == 0 && func[f]) break; if (f < prof_nfuncs) { if (p == 1) { if (func[f]) { func_v[f] = 0; PRINTF ("Function %s unselected for translation.\n", prof_func[f].name); } else PRINTF ("Function %s not suitable for translation.\n", prof_func[f].name); } else { if (p < 3) goto invalid_option; for (o = 0; option_char[o] != '\0' && option_char[o] != ch; o++); if (!option_char[o]) goto invalid_option; if (b < 0 || b >= func[f]->num_bb) goto invalid_option; if (o < 0 || o >= func[f]->bb[b].ntim) goto invalid_option; /* select an option */ func[f]->bb[b].selected_tim = -1; } } else PRINTF ("Invalid function.\n"); } /* options command */ } else if (strcmp (tmp1, "o") == 0 || strcmp (tmp1, "options") == 0) { int any = 0; PRINTF ("Available options:\n"); for (i = 0; i < prof_nfuncs; i++) if (func[i]) { options_cmd (i, func[i]); any = 1; } if (any) PRINTF ("-----------------------------------------------------------------------------\n"); else PRINTF ("Sorry. No available options.\n"); /* Ignore empty string */ } else if (strcmp (tmp1, "") == 0) { /* help command */ } else { if (strcmp (tmp1, "h") != 0 && strcmp (tmp1, "help") != 0) PRINTF ("Unknown command.\n"); PRINTF ("OpenRISC Custom Unit Compiler command prompt\n"); PRINTF ("Available commands:\n"); PRINTF (" h | help displays this help\n"); PRINTF (" q | quit returns to or1ksim prompt\n"); PRINTF (" p | profile displays function profiling\n"); PRINTF (" d | debug # sets debug level (0-9)\n"); PRINTF (" o | options displays available options\n"); PRINTF (" s | select func [option] selects an option/function\n"); PRINTF (" u | unselect func [option] unselects an option/function\n"); PRINTF (" g | generate generates verilog file\n"); PRINTF (" l | list displays selected functions\n"); } } /* Dispose memory */ for (i = 0; i < prof_nfuncs - 1; i++) if (func[i]) free_func (func[i]); fclose (flog); }
static void generate_component(component comp, fncode fn) { clist args; set_lineno(comp->lineno, fn); switch (comp->vclass) { case c_assign: { ulong offset; bool is_static; variable_class vclass = env_lookup(comp->u.assign.symbol, &offset, false, true, &is_static); component val = comp->u.assign.value; if (val->vclass == c_closure) { /* Defining a function, give it a name */ if (vclass == global_var) val->u.closure->varname = comp->u.assign.symbol; else { char *varname = allocate(fnmemory(fn), strlen(comp->u.assign.symbol) + 7); sprintf(varname, "local-%s", comp->u.assign.symbol); val->u.closure->varname = varname; } } if (is_static) { ins1(op_recall + vclass, offset, fn); generate_component(comp->u.assign.value, fn); mexecute(g_symbol_set, NULL, 2, fn); break; } generate_component(comp->u.assign.value, fn); set_lineno(comp->lineno, fn); if (vclass == global_var) massign(offset, comp->u.assign.symbol, fn); else ins1(op_assign + vclass, offset, fn); /* Note: varname becomes a dangling pointer when fnmemory(fn) is deallocated, but it is never used again so this does not cause a problem. */ break; } case c_vref: case c_recall: { bool is_vref = comp->vclass == c_vref; ulong offset; bool is_static; variable_class vclass = env_lookup(comp->u.recall, &offset, true, is_vref, &is_static); if (is_static) { assert(vclass != global_var); ins1(op_recall + vclass, offset, fn); ulong gidx = is_vref ? g_make_symbol_ref : g_symbol_get; mexecute(gidx, NULL, 1, fn); break; } if (vclass != global_var) ins1((is_vref ? op_vref : op_recall) + vclass, offset, fn); else if (is_vref) { if (!mwritable(offset, comp->u.recall)) return; ins_constant(makeint(offset), fn); } else mrecall(offset, comp->u.recall, fn); if (is_vref) mexecute(g_make_variable_ref, "make_variable_ref", 1, fn); break; } case c_constant: ins_constant(make_constant(comp->u.cst), fn); break; case c_closure: { uword idx; idx = add_constant(generate_function(comp->u.closure, false, fn), fn); if (idx < ARG1_MAX) ins1(op_closure_code1, idx, fn); else ins2(op_closure_code2, idx, fn); break; } case c_block: generate_block(comp->u.blk, fn); break; case c_labeled: start_block(comp->u.labeled.name, fn); generate_component(comp->u.labeled.expression, fn); end_block(fn); break; case c_exit: generate_component(comp->u.labeled.expression, fn); if (!exit_block(comp->u.labeled.name, fn)) { if (!comp->u.labeled.name) log_error("no loop to exit from"); else log_error("no block labeled %s", comp->u.labeled.name); } break; case c_execute: { uword count; generate_args(comp->u.execute->next, fn, &count); set_lineno(comp->lineno, fn); generate_execute(comp->u.execute->c, count, fn); break; } case c_builtin: args = comp->u.builtin.args; switch (comp->u.builtin.fn) { case b_if: { block cb = new_codeblock(fnmemory(fn), NULL, new_clist(fnmemory(fn), args->next->c, new_clist(fnmemory(fn), component_undefined, NULL)), NULL, NULL, -1); generate_if(args->c, new_component(fnmemory(fn), args->next->c->lineno, c_block, cb), component_undefined, fn); break; } case b_ifelse: generate_if(args->c, args->next->c, args->next->next->c, fn); break; case b_sc_and: case b_sc_or: generate_if(comp, component_true, component_false, fn); break; case b_while: generate_while(args->c, args->next->c, fn); break; case b_loop: { label loop = new_label(fn); env_start_loop(); set_label(loop, fn); start_block(NULL, fn); generate_component(args->c, fn); branch(op_loop1, loop, fn); end_block(fn); env_end_loop(); adjust_depth(1, fn); break; } case b_add: case b_subtract: case b_ref: case b_set: case b_bitor: case b_bitand: case b_not: case b_eq: case b_ne: case b_lt: case b_le: case b_ge: case b_gt: { uword count; assert(comp->u.builtin.fn < last_builtin); generate_args(args, fn, &count); set_lineno(comp->lineno, fn); ins0(builtin_ops[comp->u.builtin.fn], fn); break; } default: { uword count; assert(comp->u.builtin.fn < last_builtin); generate_args(args, fn, &count); set_lineno(comp->lineno, fn); mexecute(builtin_functions[comp->u.builtin.fn], NULL, count, fn); break; } } break; default: abort(); } }
: ""); const char *nicename = (f->body->nicename ? f->body->nicename : ""); compile_level = seclev; erred = false; env_reset(); fncode top = new_fncode(true); env_push(NULL, top); /* Environment must not be totally empty */ block body = new_toplevel_codeblock(fnmemory(top), f->statics, f->body); function func = new_function(fnmemory(top), TYPESET_ANY, sl, NULL, new_component(fnmemory(top), 0, c_block, body), body->lineno, filename, nicename); func->varname = "top-level"; struct icode *cc = generate_function(func, true, top); GCPRO1(cc); generate_fncode(top, NULL, NULL, NULL, NULL, 0, NULL, TYPESET_ANY, seclev); uword dummy; env_pop(&dummy); delete_fncode(top); UNGCPRO(); if (erred) return NULL; return alloc_closure0(&cc->code); } struct call_info { value f, *result;
void generate_component(component comp, const char *mlabel, bool discard, fncode fn) { clist args; switch (comp->vclass) { case c_assign: { u16 offset; mtype t; variable_class vclass = env_lookup(comp->l, comp->u.assign.symbol, &offset, &t, FALSE); component val = comp->u.assign.value; if (val->vclass == c_closure) { /* Defining a function, give it a name */ if (vclass == global_var) val->u.closure->varname = comp->u.assign.symbol; else { char *varname = allocate(fnmemory(fn), strlen(comp->u.assign.symbol) + 7); sprintf(varname, "local-%s", comp->u.assign.symbol); val->u.closure->varname = varname; } } generate_component(comp->u.assign.value, NULL, FALSE, fn); if (t != stype_any) ins0(OPmscheck4 + t, fn); if (vclass == global_var) massign(comp->l, offset, comp->u.assign.symbol, fn); else if (vclass == closure_var) ins1(OPmwritec, offset, fn); else ins1(OPmwritel, offset, fn); /* Note: varname becomes a dangling pointer when fnmemory(fn) is deallocated, but it is never used again so this does not cause a problem. */ break; } case c_recall: scompile_recall(comp->l, comp->u.recall, fn); break; case c_constant: ins_constant(make_constant(comp->u.cst, FALSE, fn), fn); break; case c_scheme: scheme_compile_mgc(comp->l, make_constant(comp->u.cst, TRUE, fn), discard, fn); discard = FALSE; break; case c_closure: generate_function(comp->u.closure, fn); break; case c_block: generate_block(comp->u.blk, discard, fn); discard = FALSE; break; case c_decl: { vlist decl, next; /* declare variables one at a time (any x = y, y = 2; is an error) */ for (decl = comp->u.decls; decl; decl = next) { next = decl->next; decl->next = NULL; env_declare(decl); generate_decls(decl, fn); } generate_component(component_undefined, NULL, FALSE, fn); break; } case c_labeled: { start_block(comp->u.labeled.name, FALSE, discard, fn); generate_component(comp->u.labeled.expression, comp->u.labeled.name, discard, fn); end_block(fn); discard = FALSE; break; } case c_exit: { bool discard_exit; label exitlab = exit_block(comp->u.labeled.name, FALSE, &discard_exit, fn); if (comp->u.labeled.expression != component_undefined && discard_exit) warning(comp->l, "break result is ignored"); generate_component(comp->u.labeled.expression, NULL, discard_exit, fn); if (exitlab) branch(OPmba3, exitlab, fn); else { if (!comp->u.labeled.name) log_error(comp->l, "No loop to exit from"); else log_error(comp->l, "No block labeled %s", comp->u.labeled.name); } /* Callers expect generate_component to increase stack depth by 1 */ if (discard_exit) adjust_depth(1, fn); break; } case c_continue: { bool discard_exit; /* Meaningless for continue blocks */ label exitlab = exit_block(comp->u.labeled.name, TRUE, &discard_exit, fn); if (exitlab) branch(OPmba3, exitlab, fn); else { if (comp->u.labeled.name[0] == '<') log_error(comp->l, "No loop to continue"); else log_error(comp->l, "No loop labeled %s", comp->u.labeled.name); } /* Callers expect generate_component to increase stack depth by 1 (*/ adjust_depth(1, fn); break; } case c_execute: { u16 count; generate_args(comp->u.execute->next, fn, &count); generate_execute(comp->u.execute->c, count, fn); break; } case c_builtin: args = comp->u.builtin.args; switch (comp->u.builtin.fn) { case b_if: generate_if(args->c, args->next->c, NULL, TRUE, fn); generate_component(component_undefined, NULL, FALSE, fn); break; case b_ifelse: generate_if(args->c, args->next->c, args->next->next->c, discard, fn); discard = FALSE; break; case b_sc_and: case b_sc_or: generate_if(comp, component_true, component_false, discard, fn); discard = FALSE; break; case b_while: enter_loop(fn); generate_while(args->c, args->next->c, mlabel, discard, fn); exit_loop(fn); discard = FALSE; break; case b_dowhile: enter_loop(fn); generate_dowhile(args->c, args->next->c, mlabel, discard, fn); exit_loop(fn); discard = FALSE; break; case b_for: enter_loop(fn); generate_for(args->c, args->next->c, args->next->next->c, args->next->next->next->c, mlabel, discard, fn); exit_loop(fn); discard = FALSE; break; default: { u16 count; assert(comp->u.builtin.fn < last_builtin); generate_args(args, fn, &count); ins0(builtin_ops[comp->u.builtin.fn], fn); break; } case b_cons: { u16 count; u16 goffset; mtype t; assert(comp->u.builtin.fn < last_builtin); generate_args(args, fn, &count); goffset = global_lookup(fnglobals(fn), builtin_functions[comp->u.builtin.fn], &t); mexecute(comp->l, goffset, NULL, count, fn); break; } } break; default: assert(0); } if (discard) ins0(OPmpop, fn); }
void Compiler::compile_builder(jit::Context& ctx, LLVMState* ls, JITMethodInfo& info, jit::Builder& work) { llvm::Function* func = info.function(); if(!work.generate_body()) { function_ = NULL; // This is too noisy to report // llvm::outs() << "not supported yet.\n"; return; } // Hook up the return pad and return phi. work.generate_hard_return(); if(ls->jit_dump_code() & cSimple) { llvm::outs() << "[[[ LLVM Simple IR ]]]\n"; llvm::outs() << *func << "\n"; } std::vector<BasicBlock*> to_remove; bool Broken = false; for(Function::iterator I = func->begin(), E = func->end(); I != E; ++I) { if(I->empty()) { BasicBlock& bb = *I; // No one jumps to it.... if(llvm::pred_begin(&bb) == llvm::pred_end(&bb)) { to_remove.push_back(&bb); } else { llvm::outs() << "Basic Block is empty and used!\n"; } } else if(!I->back().isTerminator()) { llvm::errs() << "Basic Block does not have terminator!\n"; llvm::errs() << *I << "\n"; llvm::errs() << "\n"; Broken = true; } } for(std::vector<BasicBlock*>::iterator i = to_remove.begin(); i != to_remove.end(); ++i) { (*i)->eraseFromParent(); } if(Broken or llvm::verifyFunction(*func, PrintMessageAction)) { llvm::outs() << "ERROR: complication error detected.\n"; llvm::outs() << "ERROR: Please report the above message and the\n"; llvm::outs() << " code below to http://github.com/rubinius/rubinius/issues\n"; llvm::outs() << *func << "\n"; function_ = NULL; return; } ls->passes()->run(*func); if(ls->jit_dump_code() & cOptimized) { llvm::outs() << "[[[ LLVM Optimized IR: " << ls->symbol_cstr(info.method()->name()) << " ]]]\n"; llvm::outs() << *func << "\n"; } function_ = func; generate_function(ls); // Inject the RuntimeData objects used into the original CompiledMethod // Do this way after we've validated the IR so things are consistent. ctx.runtime_data_holder()->set_function(func, mci_->address(), mci_->size()); info.method()->set_jit_data(ctx.runtime_data_holder()); ls->shared().om->add_code_resource(ctx.runtime_data_holder()); }
string gen_code(string file, tThread * main) { debugf("generating code\n"); int i; string fname = strdup(file); // .c string fname2 = strdup(file); // .h string ext = strdup(".c"); string ext2 = strdup(".h"); strcat(fname, ext); strcat(fname2, ext2); out= fopen(fname, "w"); hout = fopen(fname2, "w"); fprintf(out, "#include <eve.h>\n#include <stdlib.h>\n#include <string.h>\n"); for(i=0; i<included_files_count; i++) { fprintf(out, "#include <%s.h>\n", included_files[i]); fprintf(hout, "#include <%s.h>\n", included_files[i]); } fprintf(out, "#include \"%s\"\n", fname2); // generating types in hout (.h) fprintf(hout, "\n/* data types */\n", fname2); for (i = BASIC_TYPES_COUNT-1; i<global_types_count; i++) { if (global_types[i].type_kind == __ctype) continue; if((global_types[i].type_kind == __none) || (global_types[i].type_kind == __array)) { fprintf(hout, "typedef %s ", global_types[i].pointerto); if(global_types[i].pointer) { fprintf(hout, " *"); } fprintf(hout, " %s;\n", global_types[i].name); } else if (global_types[i].type_kind == __enum) { fprintf(hout, "typedef enum %s{\n", global_types[i].name); int j = 0; for(; j<global_types[i].ecount; j++) { fprintf(hout, "%s, ", global_types[i].enums[j]); } fprintf(hout, "\n}%s;\n", global_types[i].name); } else if (global_types[i].type_kind == __pclass) // next type is class, generate it automatically { fprintf(hout, "struct %s;\n", global_types[i+1].class_info.name); // generate next type. fprintf(hout, "typedef struct %s * %s;\n", global_types[i].pointerto, global_types[i].name); fprintf(hout, "typedef struct %s{\n", global_types[i+1].class_info.name); int j = 0; for(; j<global_types[i+1].class_info.vcount; j++) { fprintf(hout, "%s %s;\n", global_types[i+1].class_info.variables[j].type, global_types[i+1].class_info.variables[j].name); } fprintf(hout, "\n}%s;\n", global_types[i+1].class_info.name); for(j = 0; j < global_types[i+1].class_info.mcount; j++) { generate_function(global_types[i+1].class_info.methodes[j], 1); } // next type already generate! i++; } } // generating global variables fprintf(hout, "\n/* global variables */\n", fname2); for (i=0; i < main->vcount; i++) { if (main->vars[i].mod != _none) fprintf(hout, "%s ", mod_to_str(main->vars[i].mod)); fprintf(hout, "%s ", main->vars[i].type); fprintf(hout, "%s;\n", main->vars[i].name); } for (i=0; i < global_functions_count; i++) { if(!global_functions[i]->cdef) generate_function(global_functions[i], 0); } fclose(out); fclose(hout); free(ext); free(ext2); free(fname2); return fname; }