int main(int argc, char **argv) { //No checks, make sure the parameters are OK, otherwise SEGFAULT! if (argc < 6) return printf("%s [outfile.dot] [graph name] [reg file] [x86 file] [stack file] [postfix expression]\n", argv[0]), 0; hashtab h; hashtab_init(&h, hash_2, 20); insert(&h, "ln"); insert(&h, "log"); insert(&h, "exp"); insert(&h, "cos"); insert(&h, "sin"); insert(&h, "tan"); insert(&h, "cosh"); insert(&h, "sinh"); insert(&h, "acos"); insert(&h, "asin"); insert(&h, "cotan"); tree t = build(argv[6], &h); printf("Expr : "); print_expr(t); printf("\n\n"); printf("Tree :\n"); print_tree(t); //Fictional register machine code generation gen_reg_asm_code(argv[3], t); //x86 machine code generation gen_x86_asm_code(argv[4], t); //Stack machine code generation gen_stack_code(argv[5], t); printf("\nParallel sub expressions : \n"); leaf *l; lstack *s = get_par_subtrees(t); //Write the AST with some nice colors write_tree_dot(argv[1], argv[2], t, s); while (lpop(s, &l)) print_tree(l), printf("\n"); lstack_free(s); hashtab_free(&h); return 0; }
// do a depth-first or breadth-first search in state space up to specified depth // bfs: boolean flag if to do a breadth-first seach (depth_max is ignored in this case) // buffer_len: size of state buffer // hash_entries, hash_retries: parameters of hash table to finf duplicate states // graph_out: if != NULL state graph will be output to this tream in graphviz dot format // print_hex: if to print states in hex // ini_state: state to start simulation at (or NULL to use default) void search (nipsvm_bytecode_t *bytecode, int bfs, unsigned int depth_max, unsigned long buffer_len, unsigned long hash_entries, unsigned long hash_retries, FILE *graph_out, int print_hex, nipsvm_state_t *ini_state) // extern { char *p_buffer, *p_buf; t_hashtab hashtab; unsigned long buf_len; nipsvm_state_t *state; st_search_context ctx; struct timeval time_start, time_end, time_diff; double us_state; // allocate buffer for states p_buffer = (char *)malloc( buffer_len ); if( p_buffer == NULL ) rt_err( "out of memory (state buffer for search)" ); p_buf = p_buffer; buf_len = buffer_len; // allocate hash table hashtab = hashtab_new( hash_entries, hash_retries ); if( hashtab == NULL ) rt_err( "out of memory (hash table)" ); // tell user to wait if( bfs ) printf( "doing breadth-first search, please wait...\n" ); else printf( "doing depth-first search up to depth %u, please wait...\n", depth_max ); // remember start time gettimeofday( &time_start, NULL ); // set up context for successor state generation nipsvm_init (&ctx.nipsvm, bytecode, &search_succ_cb, &search_err_cb); // get initial state if( ini_state == NULL ) { ini_state = nipsvm_initial_state (&ctx.nipsvm); } // insert initial state into table { size_t sz = nipsvm_state_size (ini_state); state = nipsvm_state_copy (sz, ini_state, &p_buf, &buf_len); hashtab_insert (hashtab, sz, ini_state); } // set up rest of context for search ctx.depth_max = depth_max; ctx.depth_reached = 0; ctx.state_cnt = 0; ctx.transition_cnt = 0; ctx.n_atomic_steps = 0; ctx.max_state_size = 0; ctx.p_buf = p_buf; ctx.buf_len = buf_len; ctx.hashtab = hashtab; ctx.error = 0; ctx.graph_out = graph_out; ctx.graph_out_pred = state; ctx.print_hex = print_hex; // start search if( bfs ) search_internal_bfs( state, &ctx ); else search_internal_dfs_to_depth( state, 0, &ctx ); nipsvm_finalize (&ctx.nipsvm); // update pointer and length of state buffer p_buf = ctx.p_buf; buf_len = ctx.buf_len; // remember end time gettimeofday( &time_end, NULL ); // get time difference time_diff.tv_usec = time_end.tv_usec - time_start.tv_usec; time_diff.tv_sec = time_end.tv_sec - time_start.tv_sec; if( time_diff.tv_usec < 0 ) { time_diff.tv_usec += 1000000; time_diff.tv_sec--; } // get time per state (in microseconds) us_state = ((double)time_diff.tv_sec * 1000000.0 + (double)time_diff.tv_usec) / (double)ctx.state_cnt; // print statistics table_statistics_t t_stats; table_statistics (hashtab, &t_stats); unsigned long used_buffer_space = buffer_len - buf_len; double table_fill_ratio = 100.0 * (double)t_stats.entries_used / (double)t_stats.entries_available; double state_memory_fill_ratio = 100.0 * (double)used_buffer_space / (double)buffer_len; printf( "\n" ); if( bfs ) printf( "breadth-first search %s:\n", ctx.error ? "aborted" : "completed" ); else printf( "depth-first search up to depth %u %s:\n", depth_max, ctx.error ? "aborted" : "completed" ); printf( " states visited: %lu\n", ctx.state_cnt ); printf( " transitions visited: %lu\n", ctx.transition_cnt ); printf( " atomic steps: %lu\n", ctx.n_atomic_steps ); printf( " maximum state size: %u\n", ctx.max_state_size ); if( ! bfs ) printf( " reached depth: %u\n", ctx.depth_reached ); printf( " total time: %lu.%06lu s\n" " time per state: %f us\n", time_diff.tv_sec, (unsigned long)time_diff.tv_usec, us_state ); printf( "\n" ); printf( "state memory statistics:\n" ); printf( " total: %0.2fMB\n", buffer_len / 1048576.0 ); printf( " used: %0.2fMB (%0.1f%%)\n", used_buffer_space / 1048576.0, state_memory_fill_ratio ); printf( "\n" ); printf( "state table statistics:\n" " memory usage: %0.2fMB\n", t_stats.memory_size / 1048576.0 ); printf( " buckets used/available: %lu/%lu (%0.1f%%)\n", t_stats.entries_used, t_stats.entries_available, table_fill_ratio ); printf( " max. no. of retries: %lu\n", t_stats.max_retries ); printf( " conflicts (resolved): %lu\n", t_stats.conflicts ); // free state buffer and hash table free( p_buffer ); hashtab_free( hashtab ); }