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 ); } } }
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 ); }
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 ); }
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()); }
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 ); }
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 ); }
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] ); }
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 ); }
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); }
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] ); }
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 ); }
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 ); }
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 ); }
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); }
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 ); }
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 ); }
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); }
static return_stmt(stream, node, ret) { if ( node[3] ) expr_code( stream, node[3], 0 ); branch( stream, ret ); }