📄 output.cc
字号:
static const char * nondag_management = "\#define CVMJIT_JCS_STATE_MASK(v) v\n\#define CVMJIT_JCS_STATE_MATCHED 0x0\n\#define CVMJIT_DID_SEMANTIC_ACTION(p) (CVM_FALSE)\n"; static const char * prologue ="\nint\n\%s( %s p, CVMJITCompilationContext* con)\n\{\n\ %s l = 255, r = 255, result;\n\ %s left_p, right_p;\n\ int opcode, n_operands;\n\#ifdef CVMJIT_JCS_MATCH_DAG\n\ int stateno;\n\#endif\n\ struct %s * top_state;\n\ INITIALIZE_MATCH_STACK;\n\ new_node:\n\#ifdef CVMJIT_JCS_MATCH_DAG\n\ stateno = %s(p);\n\ if (stateno >= CVMJIT_JCS_STATE_MATCHED){\n\ goto skip_match;\n\ }\n\#endif\n\ opcode = %s(con, p);\n\ switch( opcode ){\n"; static const char * binarycase =" left_p = %s(p);\n\ right_p = %s(p);\n\ MATCH_PUSH( p, opcode, left_p, right_p, 0, 2 );\n\ break;\n"; static const char * unarycase =" left_p = %s(p);\n\ right_p = NULL;\n\ MATCH_PUSH( p, opcode, left_p, NULL, 0, 1 );\n\ break;\n\ default:\n\ goto assign_state; /* leaves need not worry */\n\ }\n\ top_state = GET_MATCH_STACK_TOP;\n\ continue_processing:\n\ if ( top_state->which_submatch < top_state->n_submatch ){\n\ p = top_state->subtrees[top_state->which_submatch++];\n\ goto new_node;\n\ }\n\ /* done with subtrees, go assign state.*/\n\ MATCH_POP( p, opcode, left_p, right_p, n_operands )\n\ switch ( n_operands ){\n\ case 2:\n\ r = CVMJIT_JCS_STATE_MASK(%s( right_p ));\n\ /* FALLTHRU */\n\ case 1:\n\ l = CVMJIT_JCS_STATE_MASK(%s( left_p ));\n\ }\n\ assign_state:\n\ /* IN THE FUTURE, DO THIS ALL DIFFERENT */\n\ /* now use appropriate transition function */\n\ switch ( opcode ){\n"; static const char * switch_end =" default:\n\#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT)\n\ con->errNode = p;\n\#endif\n\ return -1;\n\ }\n"; static const char * err_check =" if (result == 0){\n\#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT)\n\ con->errNode = p;\n\#endif\n\ return -1;\n\ }\n"; static const char * epilogue =" %s(p, result|CVMJIT_JCS_STATE_MATCHED);\n\#ifdef CVMJIT_JCS_MATCH_DAG\n\ skip_match:\n\#endif\n\ if ( MATCH_STACK_EMPTY ){\n\ return 0;\n\ }\n\ top_state = GET_MATCH_STACK_TOP;\n\ goto continue_processing;\n\}\n\n"; static const char * switch_label = "\tcase %s:\n\t\tresult = "; static const char * finish_transition = ";\n\t\tbreak;\n"; if (is_dag){ fprintf(output, dag_management, setfn, getfn, getfn ); }else{ fprintf(output, nondag_management); } fprintf(output, prologue, matchname, nodetype, statetype, nodetype, match_state_name, getfn, opfn); // write out names of all binary operators while ( (symp = s_i.next() ) != 0){ if (symp->type() == symbol::binaryop) fprintf( output, "\tcase %s:\n", symp->name() ); } fprintf(output, binarycase, leftfn, rightfn); // write out names of all unary operators s_i = all_symbols; while ( (symp = s_i.next() ) != 0){ if (symp->type() == symbol::unaryop) fprintf( output, "\tcase %s:\n", symp->name() ); } fprintf(output, unarycase, leftfn, getfn, getfn); s_i = all_symbols; while ( (symp = s_i.next() ) != 0){ switch (symp->functional_type()){ case symbol::binaryop: fprintf( output, switch_label, symp->name()); fprintf(output, transition_name_template, symp->name()); print_mapped_subscript( symp->name(), "l", "l", output ); print_mapped_subscript( symp->name(), "r", "r", output ); fprintf(output, finish_transition ); break; case symbol::unaryop: fprintf( output, switch_label, symp->name()); fprintf(output, transition_name_template, symp->name()); if (symp->direct_map_transitions){ fputs( "[l]", output ); } else { print_mapped_subscript( symp->name(), "l", "l", output ); } fprintf(output, finish_transition ); break; case symbol::rightunaryop: fprintf( output, switch_label, symp->name()); fprintf(output, transition_name_template, symp->name()); if (symp->direct_map_transitions){ fputs( "[r]", output ); } else { print_mapped_subscript( symp->name(), "l", "r", output ); } fprintf(output, finish_transition ); break; case symbol::terminal:{ leaf_transition *lt; fprintf( output, switch_label, symp->name()); switch (symp->type()){ case symbol::terminal: lt = ((terminal_symbol *)symp) -> transitions; break; case symbol::unaryop: lt = (leaf_transition*) ((unary_symbol *)symp) -> transitions; break; case symbol::binaryop: lt = (leaf_transition*) ((binary_symbol *)symp) -> transitions; break; } fprintf(output, "%d", lt->state ); fprintf(output, finish_transition ); break; } case symbol::nonterminal: break; // don't appear in trees. } } fprintf( output, switch_end ); if (!error_folding){ fprintf( output, err_check ); } fprintf( output, epilogue, setfn );}static voidprint_with_substitution( const char * msg, const char * subst, FILE * output ){ char c; while( (c = *(msg++)) != 0 ){ if ((c=='$') && (*msg == '$')){ fputs( subst, output ); msg++; } else { putc( c, output ); } }}static voidprint_dorule( FILE * output ){ rule *rp; rulelist_iterator r_iter; int rule_is_reached; static const char * prologue =" switch( ruleno ){\n\ case 0:\n\#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT)\n\ con->errNode = %s;\n\#endif\n\error_return_branch_island:\n\ return -1;\n"; fprintf( output, prologue, handlename ); r_iter = all_rules; while ( (rp = r_iter.next() ) != 0){ rule_is_reached = rp->get_reached(); if ( ! rule_is_reached ){ fprintf( output, "#ifdef CVM_CG_EXPAND_UNREACHED_RULE\n"); } fprintf( output, " case %d:\n", rp->ruleno() ); fprintf(output, " CVMJITdoStartOfCodegenRuleAction(con, ruleno, \""); rp->print(output, true); fprintf(output, "\", %s);\n", handlename); print_with_substitution( rp->act(), handlename, output ); fprintf(output, "\n CVMJITdoEndOfCodegenRuleAction(con);\n"); fputs(" break;\n", output ); if ( ! rule_is_reached ){ fprintf( output, "#endif /*CVM_CG_EXPAND_UNREACHED_RULE*/\n"); } } fputs(" }\n", output);}static intis_chain_rule(rule *rp){ return rp->get_arity() == 1 && rp->rhs()->node->type() == symbol::nonterminal;}/* * Emit case arms for synthetic and inherited attribute manipulation */static void write_actions( FILE* output, int (rule::*has_action)(), char* (rule::*get_action)(), const char* default_word){ rule *rp; rulelist_iterator r_iter; int * defaults_found = (int*)calloc( sizeof(int), max_rule_arity + 1); int this_arity; int chain_rules_found = 0; int rule_is_reached; r_iter = all_rules; while ( (rp = r_iter.next() ) != 0){ if ( (rp->*has_action)() ){ rule_is_reached = rp->get_reached(); if ( ! rule_is_reached ){ fprintf( output, "#ifdef CVM_CG_EXPAND_UNREACHED_RULE\n"); } fprintf( output, " case %d:\n", rp->ruleno() ); print_with_substitution( (rp->*get_action)(), handlename, output ); fputs("\n break;\n", output ); if ( ! rule_is_reached ){ fprintf( output, "#endif /*CVM_CG_EXPAND_UNREACHED_RULE*/\n"); } } else { defaults_found[ rp->get_arity() ] = 1; } } // now go back and find all the defaults. Sort by arity. // treat unary rules separately, so we can detect chain rules // and give them separate defaults. if (max_rule_arity >= 1 && defaults_found[1]){ r_iter = all_rules; while ( (rp = r_iter.next() ) != 0){ if ( (rp->get_arity() == 1) && !((rp->*has_action)() )){ if (is_chain_rule(rp)){ chain_rules_found += 1; } else { rule_is_reached = rp->get_reached(); if (!rule_is_reached) { fprintf(output, "#ifdef CVM_CG_EXPAND_UNREACHED_RULE\n"); } fprintf( output, "\tcase %d:\n", rp->ruleno() ); if (!rule_is_reached) { fprintf(output, "#endif /*CVM_CG_EXPAND_UNREACHED_RULE*/\n"); } } } } fprintf(output, "\t\tDEFAULT_%s1(con, %s);\n\t\tbreak;\n", default_word, handlename ); } if (chain_rules_found > 0){ r_iter = all_rules; while ( (rp = r_iter.next() ) != 0){ if ( (rp->get_arity() == 1) && !((rp->*has_action)() )){ rule_is_reached = rp->get_reached(); if (!rule_is_reached) { fprintf(output, "#ifdef CVM_CG_EXPAND_UNREACHED_RULE\n"); } if (is_chain_rule(rp)){ fprintf( output, "\tcase %d:\n", rp->ruleno() ); } if (!rule_is_reached) { fprintf(output, "#endif /*CVM_CG_EXPAND_UNREACHED_RULE*/\n"); } } } fprintf(output, "\t\tDEFAULT_%s_CHAIN(con, %s);\n\t\tbreak;\n", default_word, handlename ); } for ( this_arity = 2; this_arity <= max_rule_arity; this_arity ++){ if ( !defaults_found[this_arity]) continue; r_iter = all_rules; while ( (rp = r_iter.next() ) != 0){ if ( (rp->get_arity() == this_arity) && !((rp->*has_action)() )){ rule_is_reached = rp->get_reached(); if (!rule_is_reached) { fprintf(output, "#ifdef CVM_CG_EXPAND_UNREACHED_RULE\n"); } fprintf( output, "\tcase %d:\n", rp->ruleno() ); if (!rule_is_reached) { fprintf(output, "#endif /*CVM_CG_EXPAND_UNREACHED_RULE*/\n"); } } } fprintf(output, "\t\tDEFAULT_%s%d(con, %s);\n\t\tbreak;\n", default_word, this_arity, handlename ); } free(defaults_found); }void do_synthesis(FILE * output){ /* emit code inline to manipulate synthetic attributes. */ const static char * prologue =" switch( ruleno ){\n\ case 0:\n\#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT)\n\ con->errNode = %s;\n\#endif\n\ return -1;\n"; fprintf( output, prologue, handlename ); write_actions(output, &rule::has_synthesis_act, &rule::synthesis_act, "SYNTHESIS"); fprintf(output," }\n"); }void print_inheritance(FILE * output){ /* emit code inline to manipulate inherited attributes. */ const static char * prologue =" switch( ruleno ){\n\ case 0:\n\#if defined(CVM_DEBUG) || defined(CVM_TRACE_JIT)\n\ con->errNode = %s;\n\#endif\n\ goto error_return_branch_island;\n"; if ( !do_attributes){ return; } fprintf( output, prologue, handlename ); write_actions(output, &rule::has_pre_act, &rule::pre_act, "INHERITANCE"); fprintf(output," }\n");}static intprint_action_matrix( FILE *output, FILE *data ){ int ngoals, goalval; symbol *sp; symbollist_iterator s_iter; int n_nonterms = nonterminal_symbols.n(); int i; state *stp; statelist_iterator st_iter; int goalnumber = -1; int gotgoal = 0; /* * first off, print out the goal values. This isn't for us, * but for a human. */ fputs("enum goals { goal_BAD ", output ); ngoals = 0; s_iter = nonterminal_symbols; while( (sp = s_iter.next() ) != 0){ goalval = ((nonterminal_symbol *)sp)->goal_number; ngoals += 1; assert( goalval == ngoals ); fprintf( output, ", goal_%s", sp->name() ); if (!gotgoal){ if (goalname==0 || goalname==sp->name() ){ // first or named one. goalnumber = goalval; gotgoal = 1; } } } fputs(" };\n\n", output ); assert( ngoals == nonterminal_symbols.n() ); /* * now print the actual matrix. * Brute force at its finest */ fprintf( output, "extern const short\t%s[%d][%d];\n", rule_to_use, allstates.n(), ngoals+1 ); fprintf( data, "const short\n%s[%d][%d] = {\n", rule_to_use, allstates.n(), ngoals+1 ); st_iter = allstates; for(int state = 0; (stp = st_iter.next()) != 0; state++) { if ( stp->rules_to_use == 0 ) stp->use_rules(); // for all states... fprintf(data, " /* State %4d */ { 0,", state); // 0th goal for ( i = 0; i < n_nonterms; i++ ){ fprintf( data, " %d,", stp->rules_to_use[i] ); } fputs(" },\n", data ); } fputs("};\n\n", data ); assert( gotgoal ); return goalnumber;}/* * the hard one. * synthesize a routine that, given a subtree and a goal: * 1) figures out which rule we want to apply; * 2) causes appropriate subgoals to be satisfied; * 3) applies the rule's semantic action. * we use the matrix rule_to_use to satisfy 1), * and write lots of yeucchy code to do 2, then * simply call dorule to do 3. We will not try * to factor the code generated, even though it's likely * to be real redundant. *//* * but first, some subroutines & data structs we'll need. */struct subgoal{ path p; nonterminal_symbol *sp; struct subgoal * next; };static voidprint_down_path( FILE * output, path p, const char *ptrname ){ int level = 0; int done = 0; do { switch( p.last_move()){ case path::left: fprintf( output, "%s(", leftfn ); level ++; p.ascend(); break; case path::right: fprintf( output, "%s(", rightfn ); level ++; p.ascend(); break; default: fputs(ptrname, output ); done = 1; break; } } while ( !done );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -