int main(int argc, char *argv[]) { int i, j, hibound; for(i=0; i<256; i++) mt[i]=-1; for(i=0; i<NUM_TERMS; i++) opgen(tval[i], i, -1, 0); while(tail<256) { maxcost++; hibound=tail; for(i=0; i<hibound; i++) if(q[i].cost+COST_NOT<=maxcost) { opgen(i, 0, 3, q[i].cost+COST_NOT); if(q[i].cost+5<=maxcost) for(j=0; j<i && q[i].cost+q[j].cost+COST_OP<=maxcost; j++) { opgen(i, j, 0, q[i].cost+q[j].cost+COST_OP); opgen(i, j, 1, q[i].cost+q[j].cost+COST_OP); opgen(i, j, 2, q[i].cost+q[j].cost+COST_OP); } } } printf("/* This file is automatically generated. Do not edit. */\n"); printf("\n#include \"blitter.h\"\n\nstatic sparc_instr minstor[] = {\n"); minpos=0; for(i=0; i<256; i++) { printf(" /* %02x */\n", i); mtpos[i]=minpos; genexp(mt[i], 4, 0x60); printf(" 0,\n"); minpos++; } printf("};\n\nsparc_instr *minterms[] = {"); for(i=0; i<256; i++) { if(!(i&3)) printf("\n "); printf("&minstor[%d], ", mtpos[i]); } printf("\n};\n\n"); return 0; }
void DefUseChain<Node>:: build( AstInterface& fa, ReachingDefinitionAnalysis& r, AliasAnalysisInterface& alias, FunctionSideEffectInterface* f) { std::vector <Node*> defvec; const ReachingDefinitionGenerator* g = r.get_generator(); StmtSideEffectCollect collect(f); std::map<AstNodePtr, Node*> defmap; const ReachingDefinitionBase& base = g->get_base(); for (ReachingDefinitionBase::iterator p = base.begin(); p != base.end(); ++p) { std::pair<AstNodePtr,AstNodePtr> cur = base.get_ref(p); if (DebugDefUseChain()) std::cerr << "creating def node : " << AstToString(cur.first) << " : " << AstToString(cur.second) << std::endl; Node* n = CreateNode( fa, cur.first, cur.second, true); assert(n != 0); defvec.push_back(n); defmap[cur.first] = n; } for (ReachingDefinitionAnalysis::NodeIterator p = r.GetNodeIterator(); !p.ReachEnd(); ++p) { ReachingDefNode* cur = *p; if (DebugDefUseChain()) { std::cerr << "processing CFG node : "; cur->write(std::cerr); } ReachingDefinitions in = cur->get_entry_defs(); if (DebugDefUseChain()) { std::cerr << "Reaching definitions: \n"; DumpDefSet(defvec,in); std::cerr << std::endl; } ProcessUseInfo<Node> opread( this, defvec, g, alias,fa, in); ProcessGenInfo<Node> opgen( this, defvec, g, alias, fa, defmap, in); ProcessKillInfo<Node> opkill( this, defvec, g, alias, fa, defmap, in); std::list <AstNodePtr>& stmts = cur->GetStmts(); for (std::list<AstNodePtr>::iterator p = stmts.begin(); p != stmts.end(); ++p) { AstNodePtr cur = *p; if (DebugDefUseChain()) std::cerr << "processing stmt : " << AstToString(cur) << std::endl; collect(fa, cur, &opgen, &opread, &opkill); } } if (DebugDefUseChain()) { std::cerr << "\nfinished building def-use chain:\n"; std::cerr << GraphToString(*this); } }
void ygen_emit::codegen_function( yssa_function* function ) { ygen_program* p = add_program( function ); // Every program has one hidden parameter, the function object. assert( p->stackcount == 0 ); p->stackcount += 1; // Extract all constants. for ( size_t i = 0; i < function->ops.size(); ++i ) { yssa_opinst* op = function->ops.at( i ); switch ( op->opcode ) { case YL_GLOBAL: case YL_SETGLOBAL: case YL_KEY: case YL_SETKEY: case YL_DELKEY: { symkey k( op->key ); auto i = p->strvals.find( k ); if ( i != p->strvals.end() ) { // Upgrade to key, in case value was used earlier as string. ygen_value& value = p->values.at( i->second ); value.kind = YGEN_KEY; value.string->iskey = true; } else { size_t index = p->values.size(); ygen_value value; value.kind = YGEN_KEY; value.string = add_string( k ); value.string->iskey = true; p->values.push_back( value ); p->strvals.emplace( k, index ); } break; } case YL_NUMBER: { if ( ! p->numvals.count( op->number ) ) { size_t index = p->values.size(); ygen_value value; value.kind = YGEN_NUMBER; value.number = op->number; p->values.push_back( value ); p->numvals.emplace( op->number, index ); } break; } case YL_STRING: { symkey k( op->string->string, op->string->length ); if ( ! p->strvals.count( k ) ) { size_t index = p->values.size(); ygen_value value; value.kind = YGEN_STRING; value.string = add_string( k ); p->values.push_back( value ); p->strvals.emplace( k, index ); } break; } case YL_FUNCTION: { if ( ! p->funvals.count( op->function ) ) { size_t index = p->values.size(); ygen_value value; value.kind = YGEN_PROGRAM; value.program = add_program( op->function ); p->values.push_back( value ); p->funvals.emplace( op->function, index ); } break; } default: break; } } // And sort the values. std::vector< size_t > sorted; sorted.reserve( p->values.size() ); for ( size_t i = 0; i < p->values.size(); ++i ) { sorted.push_back( i ); } std::sort ( sorted.begin(), sorted.end(), [=]( size_t a, size_t b ) { const ygen_value& aval = p->values.at( a ); const ygen_value& bval = p->values.at( b ); if ( aval.kind < bval.kind ) return true; if ( aval.kind != bval.kind ) return false; switch ( aval.kind ) { case YGEN_KEY: case YGEN_STRING: return strcmp( aval.string->text, bval.string->text ) < 0; case YGEN_NUMBER: return aval.number < bval.number; case YGEN_PROGRAM: return a < b; } } ); // Construct each block. std::vector< size_t > indexes; std::vector< std::pair< size_t, size_t > > jumps; for ( size_t i = 0; i < function->blocks.size(); ++i ) { yssa_block* block = function->blocks.at( i ).get(); // Compile each op in block. size_t count = 0; for ( size_t i = block->lstart; i < block->lfinal; i += count ) { // Ops should be in sequential block order, with no gaps. assert( indexes.size() == i ); // 'count' SSA ops map to one or more VM ops. size_t opindex = p->ops.size(); count = opgen( p, i ); indexes.insert( indexes.end(), count, opindex ); } // Find next block. yssa_block* next_block = nullptr; if ( i + 1 < function->blocks.size() ) { next_block = function->blocks.at( i + 1 ).get(); } // Compile jumps. if ( block->test ) { assert( block->next ); assert( block->fail ); assert( block->test->r != yl_opinst::NOVAL ); unsigned r = block->test->r; yl_opcode jmpt; yl_opcode jmpf; if ( block->test->opcode != YSSA_ITEREACH ) { jmpt = YL_JMPT; jmpf = YL_JMPF; } else { jmpt = YL_JMPV; jmpf = YL_JMPN; } if ( block->next == next_block ) { size_t index = p->ops.size(); p->ops.emplace_back( jmpf, r, (signed)0 ); p->slocs.push_back( block->test->sloc ); jumps.emplace_back( index, block->fail->lstart ); } else if ( block->fail == next_block ) { size_t index = p->ops.size(); p->ops.emplace_back( jmpt, r, (signed)0 ); p->slocs.push_back( block->test->sloc ); jumps.emplace_back( index, block->next->lstart ); } else { size_t index = p->ops.size(); p->ops.emplace_back( jmpt, r, (signed)0 ); p->slocs.push_back( block->test->sloc ); jumps.emplace_back( index, block->next->lstart ); index = p->ops.size(); p->ops.emplace_back( YL_JMP, 0, (signed)0 ); p->slocs.push_back( block->test->sloc ); jumps.emplace_back( index, block->fail->lstart ); } } else if ( block->next && block->next != next_block ) { size_t index = p->ops.size(); p->ops.emplace_back( YL_JMP, 0, (signed)0 ); p->slocs.push_back( block->ops.size() ? block->ops.back()->sloc : -1 ); jumps.emplace_back( index, block->next->lstart ); } } indexes.push_back( p->ops.size() ); // Fix up jumps. for ( auto jump : jumps ) { size_t index = jump.first; size_t target = indexes.at( jump.second ); signed j = (signed)target - (signed)( index + 1 ); yl_opinst& op = p->ops.at( index ); op = yl_opinst( op.opcode(), op.r(), j ); } // Construct xframes. for ( size_t i = 0; i < function->blocks.size(); ++i ) { yssa_block* block = function->blocks.at( i ).get(); // Skip blocks without exception handlers. if ( ! block->xchandler ) { continue; } // Construct xframe. yl_xframe xf; xf.start = (unsigned)indexes.at( block->lstart ); xf.end = (unsigned)indexes.at( block->lfinal ); xf.close_upvals = block->xchandler->xclocalups; xf.close_iterators = block->xchandler->xcitercount; xf.handler = (unsigned)indexes.at( block->xchandler->lstart ); // Check if we can just extend the previous xframe. if ( p->xframes.size() && p->xframes.back().end == xf.start && p->xframes.back().handler == xf.handler ) { yl_xframe& merge = p->xframes.back(); assert( merge.close_upvals == xf.close_upvals ); assert( merge.close_iterators == xf.close_iterators ); merge.end = xf.end; continue; } // Otherwise add it. p->xframes.push_back( xf ); } // The first n debugvars are the names of upvals. for ( size_t i = 0; i < function->upnames.size(); ++i ) { p->debugvars.push_back( nullptr ); } // Construct debug information for variables. std::unordered_set< yssa_variable* > variables; for ( size_t i = 0; i < function->ops.size(); ++i ) { yssa_opinst* op = function->ops.at( i ); if ( op->has_associated() || ! op->variable ) { continue; } yssa_variable* v = op->variable; if ( variables.count( v ) ) { continue; } unsigned varindex = (unsigned)p->debugvars.size(); p->debugvars.push_back( v ); variables.insert( v ); for ( yssa_live_range* live = v->live; live; live = live->next ) { ygen_debugspan span; span.varindex = varindex; span.start = (unsigned)indexes.at( live->start ); span.end = (unsigned)indexes.at( live->final ); if ( p->debugspans.size() && p->debugspans.back().varindex == varindex && p->debugspans.back().end == span.start ) { p->debugspans.back().end = span.end; continue; } p->debugspans.push_back( span ); } } std::sort ( p->debugspans.begin(), p->debugspans.end(), []( const ygen_debugspan& a, const ygen_debugspan& b ) { if ( a.start < b.start ) return true; if ( a.start == b.start && a.end < b.end ) return true; return false; } ); }