예제 #1
0
파일: blitgen.c 프로젝트: grubba/LMTAE
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;
}
예제 #2
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);
  }
}
예제 #3
0
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;
        }
    );
}