void Compiler::handle_ik_cf(const JInst& jinst) { switch(jinst.opcode) { case OPCODE_IFNULL: case OPCODE_IFNONNULL: case OPCODE_IFEQ: case OPCODE_IFNE: case OPCODE_IFLT: case OPCODE_IFGE: case OPCODE_IFGT: case OPCODE_IFLE: gen_if(jinst.opcode, jinst.get_target(0)); break; case OPCODE_IF_ACMPEQ: case OPCODE_IF_ACMPNE: case OPCODE_IF_ICMPEQ: case OPCODE_IF_ICMPNE: case OPCODE_IF_ICMPLT: case OPCODE_IF_ICMPGE: case OPCODE_IF_ICMPGT: case OPCODE_IF_ICMPLE: gen_if_icmp(jinst.opcode, jinst.get_target(0)); break; case OPCODE_GOTO: case OPCODE_GOTO_W: gen_goto(jinst.get_target(0)); break; case OPCODE_JSR: case OPCODE_JSR_W: gen_jsr(jinst.get_target(0)); break; case OPCODE_RET: gen_ret(jinst.op0); break; case OPCODE_TABLESWITCH: case OPCODE_LOOKUPSWITCH: gen_switch(jinst); break; default: assert(false); break; } }
/** * begin a function * called from "parse", this routine tries to make a function out * of what follows * modified version. p.l. woods */ newfunc() { char n[NAMESIZE]; int idx, type; fexitlab = getlabel(); if (!symname(n)) { error("illegal function or declaration"); kill(); return; } if (idx = findglb(n)) { if (symbol_table[idx].identity != FUNCTION) multidef(n); else if (symbol_table[idx].offset == FUNCTION) multidef(n); else symbol_table[idx].offset = FUNCTION; } else add_global(n, FUNCTION, CINT, FUNCTION, PUBLIC); if (!match("(")) error("missing open paren"); output_string(n); output_label_terminator(); newline(); local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments() == 0) { // K&R style argument declaration while (!match(")")) { if (symname(n)) { if (findloc(n)) multidef(n); else { add_local(n, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } stkp = 0; argtop = argstk; while (argstk) { if (type = get_type()) { getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }
void newfunc_typed(int storage, char *n, int type) { int idx; SYMBOL *symbol; char an[NAMESIZE]; fexitlab = getlabel(); if ((idx = find_global(n)) > -1) { symbol = &symbol_table[idx]; if (symbol->identity != FUNCTION) multidef(n); } else { /* extern implies global scope */ idx = add_global(n, FUNCTION, CINT, 0, storage == EXTERN ? PUBLIC : storage); symbol = &symbol_table[idx]; } local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; argstk = 0; // ANSI style argument declaration if (doAnsiArguments()) { if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; } else { // K&R style argument declaration while (!match(")")) { if (symname(an)) { if (find_locale(an) > -1) multidef(an); else { /* FIXME: struct */ add_local(an, 0, 0, argstk, AUTO); argstk = argstk + INTSIZE; } } else { error("illegal argument name"); junk(); } blanks(); if (!streq(line + lptr, ")")) { if (!match(",")) error("expected comma"); } if (endst()) break; } if (storage == EXTERN) { need_semicolon(); return; } /* No body .. just a definition */ if (match(";")) return; stkp = 0; argtop = argstk; while (argstk) { if ((type = get_type()) != -1) { notvoid(type); getarg(type); need_semicolon(); } else { error("wrong number args"); break; } } } if (symbol->offset == FUNCTION) multidef(n); symbol->offset = FUNCTION; output_string(n); output_label_terminator(); newline(); gen_prologue(); statement(YES); print_label(fexitlab); output_label_terminator(); newline(); gen_epilogue(); gen_modify_stack(0); gen_ret(); stkp = 0; local_table_index = NUMBER_OF_GLOBALS; //locptr = STARTLOC; }
static void ast_gen_r(struct ast *a) { int bpid_1, bpid_2; vm_label_t label; struct value *v; if (a == NULL) return; a->label = gptr; switch (a->type) { case AST_LOCAL: gen_push_local(a->u.local.index, a->u.local.upcount); break; case AST_VALUE: gen_push_value(a->u.value.value); if (a->u.value.value->type == VALUE_CLOSURE) { gen_set_activation(); gen_jmp_bp(&bpid_1); a->u.value.value->v.k->label = gptr; ast_gen_r(a->u.value.value->v.k->ast); gen_ret(); backpatch(bpid_1); } break; case AST_BUILTIN: if (a->u.builtin.bi->index == INDEX_BUILTIN_STORE) { struct ast *lvalue; lvalue = ast_find_local(a); gen_cow_local(lvalue->u.local.index, lvalue->u.local.upcount); } ast_gen_r(a->u.builtin.right); if (a->u.builtin.bi->arity == -1) { v = value_new_integer(ast_count_args(a->u.builtin.right)); value_deregister(v); gen_push_value(v); } gen_builtin(a->u.builtin.bi); break; case AST_APPLY: ast_gen_r(a->u.apply.right); ast_gen_r(a->u.apply.left); gen_apply(); break; case AST_ROUTINE: ast_gen_r(a->u.routine.body); break; case AST_ARG: ast_gen_r(a->u.arg.left); ast_gen_r(a->u.arg.right); break; case AST_STATEMENT: ast_gen_r(a->u.statement.left); ast_gen_r(a->u.statement.right); break; case AST_ASSIGNMENT: assert(a->u.assignment.left != NULL); assert(a->u.assignment.left->type == AST_LOCAL); ast_gen_r(a->u.assignment.right); if (a->u.assignment.defining) { /* XXX */ /* gen_init_local(a->u.assignment.left->u.local.index, a->u.assignment.left->u.local.upcount); */ } else { gen_pop_local(a->u.assignment.left->u.local.index, a->u.assignment.left->u.local.upcount); } break; case AST_CONDITIONAL: ast_gen_r(a->u.conditional.test); gen_jz_bp(&bpid_1); ast_gen_r(a->u.conditional.yes); if (a->u.conditional.no != NULL) gen_jmp_bp(&bpid_2); backpatch(bpid_1); if (a->u.conditional.no != NULL) { ast_gen_r(a->u.conditional.no); backpatch(bpid_2); } break; case AST_WHILE_LOOP: label = gptr; ast_gen_r(a->u.while_loop.test); gen_jz_bp(&bpid_1); ast_gen_r(a->u.while_loop.body); gen_jmp(label); backpatch(bpid_1); break; case AST_RETR: ast_gen_r(a->u.retr.body); gen_ret(); break; } }