コード例 #1
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
auto_decl(stream, decl) {
    auto sz = decl_var(decl);
    auto offset = frame_off();

    /* Is there an initaliser */
    if ( decl[5] ) {
        auto init = decl[5];
        if ( init[0] == '{}' ) {
            auto j = 0;
            while ( j < init[1] ) {
                expr_code( stream, init[3 + j], 0 );
                save_local( stream, offset + j*4 );
                ++j;
            }

            /* Check for an initialisation list that's not long enough.
             * If it's not, the standard requires zero initialisation of
             * the extra members. C99:6.7.8/21 */
            if ( j < sz/4 ) {
                load_zero( stream );
                while ( j < sz/4 ) {
                    save_local( stream, offset + j*4 );
                    ++j;
                }
            }
        }
        /* Scalar initialisation */
        else {
            expr_code( stream, init, 0 );
            save_local( stream, offset );
        }
    }
}
コード例 #2
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
logical_bin(stream, node) {
    auto l = new_label();

    expr_code( stream, node[3], 0 );
    if ( node[0] == '&&' ) branch_ifz( stream, l );
    else branch_ifnz( stream, l );

    expr_code( stream, node[4], 0 );
    emit_label( stream, l );
    cast_bool( stream );
}
コード例 #3
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
conditional(stream, node) {
    auto l1 = new_label(), l2 = new_label();

    expr_code( stream, node[3], 0 );

    branch_ifz( stream, l1 );
    expr_code( stream, node[4], 0 );
    branch( stream, l2 );
    
    emit_label( stream, l1 );
    expr_code( stream, node[5], 0 );
    emit_label( stream, l2 );
}
コード例 #4
0
WhileNode::WhileNode(methodOop method, MethodInterval* parent, int begin_bci, int next_bci, int cond_offset, 
                     int end_offset)
                     : InlineSendNode(method, parent, begin_bci) {

                       CodeIterator c(method, next_bci + cond_offset + end_offset);
                       switch (c.code()) {
    case Bytecodes::whileTrue_byte: 
    case Bytecodes::whileTrue_word: 
      _cond = true;
      break;
    case Bytecodes::whileFalse_byte:
    case Bytecodes::whileFalse_word:
      _cond = false;
      break;
    default: fatal("expecting while jump");
                       }
                       int jump_end = c.next_bci();

                       if (cond_offset == 0) {
                         _body_code = NULL;
                         _expr_code = MethodIterator::factory->new_MethodInterval(method, this, next_bci, jump_end);
                       } else {
                         int cond_dest = next_bci + cond_offset;
                         _body_code = MethodIterator::factory->new_MethodInterval(method, this, next_bci, cond_dest);
                         _expr_code = MethodIterator::factory->new_MethodInterval(method, this, cond_dest, jump_end);
                       }
                       set_end_bci(expr_code()->end_bci());
}
コード例 #5
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
stmt_code(stream, node, brk, cont, ret) {
    /* Handle the null expression. */
    if ( !node ) return;

    auto op = node[0];

    /* For debugging purposes, put a blank line between each statement. */
    fputs("\n", stream);

    if      ( op == 'dcls' ) declaration( stream, node );

    else if ( op == 'brea' ) branch( stream, brk );
    else if ( op == 'cont' ) branch( stream, cont ); 
    else if ( op == 'retu' ) return_stmt( stream, node, ret );
    else if ( op == 'goto' ) goto_stmt( stream, node );

    else if ( op == 'if'   ) if_stmt( stream, node, brk, cont, ret );
    else if ( op == 'whil' ) while_stmt( stream, node, brk, cont, ret );
    else if ( op == 'for'  ) for_stmt( stream, node, brk, cont, ret );
    else if ( op == 'do'   ) do_stmt( stream, node, brk, cont, ret );
    else if ( op == 'swit' ) switch_stmt( stream, node, brk, cont, ret );
    else if ( op == 'case' 
          ||  op == 'defa' ) case_stmt( stream, node, brk, cont, ret );
    
    else if ( op == ':'    ) label_stmt( stream, node, brk, cont, ret );
    else if ( op == '{}'   ) do_block( stream, node, brk, cont, ret );
    else                     expr_code( stream, node, 0 );
}
コード例 #6
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
switch_stmt(stream, node, brk, cont, ret) {
    auto i = 0, def;
    expr_code( stream, node[3], 0 );
    def = brk = new_label();

    if (node[5][0] != 'swtb')
        int_error("No table for switch statement");

    while ( i < node[5][1] ) {
        auto c = node[5][3 + i++];

        /* Make asm labels for each case label.  We store these as integers 
         * in the unused 3rd operator slot of the case node. */
        c[5] = new_label();

        if (c[0] == 'case')
            /* Case labels have to be integers */
            branch_eq_n( stream, c[3][3], c[5] );
        else 
            def = c[5];
    }
    
    branch( stream, def ); 
    stmt_code( stream, node[4], brk, cont, ret );
    emit_label( stream, brk );
}
コード例 #7
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
unary_post(stream, node, need_lval) {
    auto sz = type_size(node[2]), elt_sz = ptr_inc_sz(node[2]);

    expr_code( stream, node[3], 1 );

    if      ( node[0] == '++' ) postfix_inc( stream, sz,  elt_sz );
    else if ( node[0] == '--' ) postfix_inc( stream, sz, -elt_sz );
    else int_error( "Unknown operator: '%Mc'", node[0] );
}
コード例 #8
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
member_bin(stream, node, need_lval) {
extern stderr;
    expr_code( stream, node[3], node[0] == '.' );

    /* This is a bit of a fudge.  In 'struct foo { int x[2] };', x is an
     * address even though it's not an lvalue, per se. */
    if ( node[2][0] == '[]' ) need_lval = 1;

    /* We've stored the member offset as an integer in node[5] */
    mem_access( stream, node[5], need_lval );
}
コード例 #9
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
binary_op(stream, node, need_lval) {
    auto op = node[0], sz = type_size( node[2] );

    expr_code( stream, node[3], is_assop(op) );
    asm_push( stream );
    expr_code( stream, node[4], 0 );

    if      ( op == '[]'  ) subscript(stream, node, need_lval);
    else if ( op == '*'   ) pop_mult(stream, 0, node[2][5]);
    else if ( op == '/'   ) pop_div(stream, 0, node[2][5]);
    else if ( op == '%'   ) pop_mod(stream, 0, node[2][5]);
    else if ( op == '+'   ) add_op(stream, node, 0, sz);
    else if ( op == '-'   ) add_op(stream, node, 0, sz);
    else if ( op == '<<'  ) pop_lshift(stream, 0);
    else if ( op == '>>'  ) pop_rshift(stream, 0);
    else if ( op == '&'   ) pop_bitand(stream, 0, sz);
    else if ( op == '|'   ) pop_bitor(stream, 0, sz);
    else if ( op == '^'   ) pop_bitxor(stream, 0, sz);

    else if ( op == '='   ) pop_assign(stream, sz);
    else if ( op == '*='  ) pop_mult(stream, 1);
    else if ( op == '/='  ) pop_div(stream, 1);
    else if ( op == '%='  ) pop_mod(stream, 1);
    else if ( op == '+='  ) add_op(stream, node, 1, sz);
    else if ( op == '-='  ) add_op(stream, node, 1, sz);
    else if ( op == '<<=' ) pop_lshift(stream, 1);
    else if ( op == '>>=' ) pop_rshift(stream, 1);
    else if ( op == '&='  ) pop_bitand(stream, 1, sz);
    else if ( op == '|='  ) pop_bitor(stream, 1, sz);
    else if ( op == '^='  ) pop_bitxor(stream, 1, sz);

    else int_error("Unknown operator: '%Mc'", op);

    /* The assignment operators are implemented to return lvalues, but
     * the C standard says they're not lvalues.  (The C++ standard has
     * them as lvalues.)  */
    if ( is_assop(op) )
        dereference(stream, type_size(node[2]), 0);
}
コード例 #10
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
opexpr_code(stream, node, need_lval) {
    auto op = node[0];

    /* Unary prefix operators */
    if ( node[1] == 1 )
        unary_pre( stream, node, need_lval );

    /* Unary postfix operators (marked binary in the tree) */
    else if ( op == '++' || op == '--' )
        unary_post( stream, node, need_lval );

    /* These operators are handled separately because of short-circuiting */
    else if ( op == '&&' || op == '||' )
        logical_bin( stream, node );

    /* And these are because they don't evaluate their second argument */
    else if ( op == '->' || op == '.' )
        member_bin( stream, node, need_lval );
   
    else if ( op == '<' || op == '>' || op == '<=' || op == '>='
              || op == '==' || op == '!=' )
        cmp_op( stream, node );

    else if ( op == ',' ) {
        expr_code( stream, node[3], 0 );
        expr_code( stream, node[4], 0 );
    }

    /* Binary operators */
    else if ( node[1] == 2 )
        binary_op( stream, node, need_lval );

    /* The ternary operator also short-circuits */
    else if ( op == '?:' )
        conditional( stream, node );

    else
        int_error( "Unknown operator: '%Mc'", node[0] );
}
コード例 #11
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
while_stmt(stream, node, brk, cont, ret) {
    cont = new_label();
    emit_label( stream, cont );

    expr_code( stream, node[3], 0 );
    brk = new_label();
    branch_ifz( stream, brk );

    stmt_code( stream, node[4], brk, cont, ret );
    branch( stream, cont );
    emit_label( stream, brk );
}
コード例 #12
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
do_call(stream, node, need_lval) {
    auto args = node[1] - 1, i = args;
    while ( i ) {
        expr_code( stream, node[ 3 + i-- ], 0 );
        asm_push( stream );
    }

    /* If we're calling an identifier that's not local and isn't an lval,
     * it must either be an extern function or an extern array.  The latter
     * would be a syntax error but for the present lack of a type system
     * So we assume it's a function and do a direct call if possible. */
    if ( node[3][0] == 'id' ) {
        auto off, is_lval = lookup_sym( &node[3][3], &off );
        if (!off && !is_lval)
            return asm_call( stream, &node[3][3], args*4 );
    }

    /* And fall back to an indirect call with CALL *%eax. */
    expr_code( stream, node[3], 0 );
    call_ptr( stream, args*4 );
}
コード例 #13
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
do_stmt(stream, node, brk, cont, ret) {
    auto start = new_label();
    emit_label( stream, start );

    cont = new_label();
    brk = new_label();
    
    stmt_code( stream, node[3], brk, cont, ret );

    emit_label( stream, cont );
    expr_code( stream, node[4], 0 );
    branch_ifnz( stream, start );
    emit_label( stream, brk );
}
コード例 #14
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
cmp_op(stream, node) {
    auto op = node[0];

    auto type; /* By this point the types must be compatible */
    if ( node[3][2][0] == '*' ) type = node[3][2];
    else type = usual_conv( node[3][2], node[4][2] );

    auto is_unsgn = type[5];
    auto sz = type_size(type);

    expr_code( stream, node[3], 0 );
    promote( stream, is_unsgn, type_size( node[3][2] ), sz );
    asm_push( stream );
    expr_code( stream, node[4], 0 );
    promote( stream, is_unsgn, type_size( node[4][2] ), sz );

    if      ( op == '<'   ) pop_lt(stream, sz, is_unsgn);
    else if ( op == '>'   ) pop_gt(stream, sz, is_unsgn);
    else if ( op == '<='  ) pop_le(stream, sz, is_unsgn);
    else if ( op == '>='  ) pop_ge(stream, sz, is_unsgn);
    else if ( op == '=='  ) pop_eq(stream, sz);
    else if ( op == '!='  ) pop_ne(stream, sz);
}
コード例 #15
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
for_stmt(stream, node, brk, cont, ret) {
    if (node[3])
        expr_code( stream, node[3], 0 );

    auto start = new_label();
    emit_label( stream, start );

    brk = new_label();
    if (node[4]) {
        expr_code( stream, node[4], 0 );
        branch_ifz( stream, brk );
    }

    cont = new_label();
    stmt_code( stream, node[6], brk, cont, ret );
    
    emit_label( stream, cont );
    if (node[5])
        expr_code( stream, node[5], 0 );

    branch( stream, start );
    emit_label( stream, brk );
}
コード例 #16
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
if_stmt(stream, node, brk, cont, ret) {
    auto l1 = new_label(), l2 = l1;

    expr_code( stream, node[3], 0 );
    
    branch_ifz( stream, l1 );
    stmt_code( stream, node[4], brk, cont, ret );

    if ( node[5] ) {
        l2 = new_label();
        branch( stream, l2 );
        emit_label( stream, l1 );
        stmt_code( stream, node[5], brk, cont, ret );
    }

    emit_label( stream, l2 );
}
コード例 #17
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
unary_pre(stream, node, need_lval) {
    auto op = node[0];
    auto op_needs_lv = op == '++' || op == '--' || op == '&';
    auto sz = type_size(node[2]);
    expr_code( stream, node[3], op_needs_lv );

    if ( op == '+'  ) {
        /* Arrays degrade to pointers. */
        auto src_sz;
        if ( node[3][2][0] == '[]' ) src_sz = 4;
        else src_sz = type_size(node[3][2]);
        promote(stream, node[2][5], src_sz, sz);
    }
    else if ( op == '-'  ) arith_neg(stream);
    else if ( op == '~'  ) bit_not(stream);
    else if ( op == '!'  ) logic_not(stream);
    else if ( op == '&'  ) ;
    else if ( op == '*'  ) dereference(stream, sz, need_lval);
    else if ( op == '++' ) increment(stream, sz,  ptr_inc_sz(node[2]) );
    else if ( op == '--' ) increment(stream, sz, -ptr_inc_sz(node[2]) );
    else int_error("Unknown operator: '%Mc'", op);
}
コード例 #18
0
ファイル: codegen.c プロジェクト: ras52/bootstrap
static
return_stmt(stream, node, ret) {
    if ( node[3] ) expr_code( stream, node[3], 0 );
    branch( stream, ret );
}