static ir_expr_t un_ex(tr_expr_t expr) { switch (expr->kind) { case TR_EX: return expr->u.ex; case TR_NX: return ir_eseq_expr(expr->u.nx, ir_const_expr(0)); case TR_CX: { temp_t tmp = temp(); tmp_label_t t = tmp_label(); tmp_label_t f = tmp_label(); fill_patch(expr->u.cx.trues, t); fill_patch(expr->u.cx.falses, f); return ir_eseq_expr( ir_seq_stmt(vlist( 5, ir_move_stmt(ir_tmp_expr(tmp), ir_const_expr(1)), expr->u.cx.stmt, ir_label_stmt(f), ir_move_stmt(ir_tmp_expr(tmp), ir_const_expr(0)), ir_label_stmt(t))), ir_tmp_expr(tmp)); } } assert(0); return NULL; }
tr_expr_t tr_record_expr(list_t fields, int size) { ir_expr_t addr = ir_tmp_expr(temp()); ir_expr_t alloc = fr_external_call( "_Alloc", list(ir_const_expr(size * FR_WORD_SIZE), NULL)); list_t p, q = NULL, r = NULL; int i; for (p = fields, i = 0; p; p = p->next, i++) { tr_expr_t field = p->data; ir_expr_t offset = ir_binop_expr(IR_PLUS, addr, ir_const_expr(FR_WORD_SIZE * i)); ir_stmt_t stmt = ir_move_stmt(ir_mem_expr(offset), un_ex(field)); list_t next = list(stmt, NULL); if (q) { r->next = next; r = next; } else q = r = next; } return tr_ex( ir_eseq_expr( ir_seq_stmt(list(ir_move_stmt(addr, alloc), q)), addr)); }
tr_expr_t tr_field_var(tr_expr_t record, int index) { return tr_ex(ir_mem_expr(ir_binop_expr( IR_PLUS, un_ex(record), ir_binop_expr(IR_MUL, ir_const_expr(index), ir_const_expr(FR_WORD_SIZE))))); }
tr_expr_t tr_string_rel_expr(int op, tr_expr_t left, tr_expr_t right) { ir_expr_t expr = fr_external_call("_CompareString", list(left, list(right, NULL))); ir_stmt_t stmt = ir_cjump_stmt(op, expr, ir_const_expr(0), NULL, NULL); return tr_cx(list(&stmt->u.cjump.t, NULL), list(&stmt->u.cjump.f, NULL), stmt); }
tr_expr_t tr_simple_var(tr_access_t access, tr_level_t level) { ir_expr_t fp = ir_tmp_expr(fr_fp()); return tr_ex(fr_expr(access->access, fp)); #if 0 while (level != access->level) { fr_access_t fr_access = tr_static_link(level)->access; fp = ir_mem_expr(ir_binop_expr( IR_PLUS, fp, ir_const_expr(fr_offset(fr_access)))); level = level->parent; } return tr_ex(ir_mem_expr(ir_binop_expr( IR_PLUS, fp, ir_const_expr(fr_offset(access->access))))); #endif }
tr_expr_t tr_call_expr(tr_level_t level, tmp_label_t label, list_t args) { ir_expr_t func = ir_name_expr(label); ir_expr_t fp = ir_const_expr(fr_offset( tr_static_link(level)->access)); list_t l_args = list(fp, NULL); list_t l_next = l_args; for (; args; args = args->next) l_next = l_next->next = list(un_ex(args->data), NULL); return tr_ex(ir_call_expr(func, l_args)); }
ir_expr_t fr_expr(fr_access_t access, ir_expr_t frame_ptr) { switch (access->kind) { case FR_IN_FRAME: return ir_mem_expr(ir_binop_expr( IR_PLUS, ir_const_expr(access->u.offset), frame_ptr)); case FR_IN_REG: return ir_tmp_expr(access->u.reg); default: assert(0); } }
tr_expr_t tr_for_expr(tr_access_t access, tr_expr_t low, tr_expr_t high, tr_expr_t body) { ir_expr_t var = fr_expr(access->access, ir_tmp_expr(fr_fp())); tmp_label_t start = tmp_label(); tmp_label_t loop = tmp_label(); tmp_label_t done = tmp_label(); ir_stmt_t cond = ir_cjump_stmt(IR_LE, var, un_ex(high), loop, done); return tr_nx(ir_seq_stmt(vlist( 7, ir_move_stmt(var, un_ex(low)), ir_label_stmt(start), cond, ir_label_stmt(loop), un_nx(body), ir_move_stmt(var, ir_binop_expr(IR_PLUS, var, ir_const_expr(1))), ir_label_stmt(done)))); }
static cx_t un_cx(tr_expr_t expr) { cx_t cx; switch (expr->kind) { case TR_EX: cx.stmt = ir_cjump_stmt( IR_EQ, expr->u.ex, ir_const_expr(0), NULL, NULL); cx.trues = list(&(cx.stmt->u.cjump.t), NULL); cx.falses = list(&(cx.stmt->u.cjump.f), NULL); return cx; case TR_NX: assert(0); case TR_CX: return expr->u.cx; } assert(0); return cx; }
tr_expr_t tr_num_expr(int num) { return tr_ex(ir_const_expr(num)); }