From 3535d16c3a9f2a16b420f34777cbbc56ccadfd5d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 18 Jul 2023 18:58:56 +0100 Subject: [PATCH] Implement Ternary If Expression --- src/tilde/tb.lib | Bin 4141318 -> 4141318 bytes src/tilde_expr.cpp | 106 ++++++++++++++++++++++++++++++++++++++++++--- src/tilde_proc.cpp | 12 ++--- 3 files changed, 108 insertions(+), 10 deletions(-) diff --git a/src/tilde/tb.lib b/src/tilde/tb.lib index 60b197014b052b35a050f74c6cb556a834fc7250..84dba790bc3cd681685ebba1d9071e6ca4bec85e 100644 GIT binary patch delta 298 zcmZpB^oJ3I8(J8*Fo{`lmh9S=aypWMA!a%wr=9qAGb^S~Da<9iwzX@|XKL4;&)lv( zpQT-UK5M)7e71J&`Rwi5^EukJ=X17e&*y5_p3mK`J)fstdp>Ww_I$o}?fLxe+Vch4 zwdV`AYtI*I*Pbuju03C*U3cZ)J_cZ;%UcZ;%YcZ;%WcZ;%acZ;%VcZ;&!?iOWt;2Hpc5NU}3 delta 298 zcmZpB^oJ3I8(J8*Fo{`lK8@L$aypWMA!a%wr=9qAGb^S~Da_Aewzg}}XKL4;&)lv( zpQT-UK5M)7e71J&`Rwi5^EukJ=X17e&*y5_p3mK`J)fstdp>Ww_I$o}?fLxe+Vch4 zwdV`AYtI*I*Pbuju03C*U3%;Wz+5!WxL%i%I?550J3puzyJUM diff --git a/src/tilde_expr.cpp b/src/tilde_expr.cpp index 63b1feb6e..351ee7b45 100644 --- a/src/tilde_expr.cpp +++ b/src/tilde_expr.cpp @@ -799,6 +799,9 @@ gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t) { } TB_DataType st = cg_data_type(src); + if (value.kind == cgValue_Value && !TB_IS_VOID_TYPE(value.node->dt)) { + st = value.node->dt; + } TB_DataType dt = cg_data_type(t); if (is_type_integer(src) && is_type_integer(dst)) { @@ -1751,10 +1754,9 @@ gb_internal cgValue cg_build_binary_expr(cgProcedure *p, Ast *expr) { } if (left.node == nullptr) left = cg_build_expr(p, be->left); if (right.node == nullptr) right = cg_build_expr(p, be->right); - GB_PANIC("TODO(bill): cg_emit_comp"); - // cgValue cmp = cg_emit_comp(p, be->op.kind, left, right); - // Type *type = default_type(tv.type); - // return cg_emit_conv(p, cmp, type); + cgValue cmp = cg_emit_comp(p, be->op.kind, left, right); + Type *type = default_type(tv.type); + return cg_emit_conv(p, cmp, type); } case Token_CmpAnd: @@ -1824,6 +1826,60 @@ gb_internal cgValue cg_build_binary_expr(cgProcedure *p, Ast *expr) { return {}; } +gb_internal cgValue cg_build_cond(cgProcedure *p, Ast *cond, TB_Node *true_block, TB_Node *false_block) { + cond = unparen_expr(cond); + + GB_ASSERT(cond != nullptr); + GB_ASSERT(true_block != nullptr); + GB_ASSERT(false_block != nullptr); + + // Use to signal not to do compile time short circuit for consts + cgValue no_comptime_short_circuit = {}; + + switch (cond->kind) { + case_ast_node(ue, UnaryExpr, cond); + if (ue->op.kind == Token_Not) { + cgValue cond_val = cg_build_cond(p, ue->expr, false_block, true_block); + return cond_val; + // if (cond_val.value && LLVMIsConstant(cond_val.value)) { + // return cg_const_bool(p->module, cond_val.type, LLVMConstIntGetZExtValue(cond_val.value) == 0); + // } + // return no_comptime_short_circuit; + } + case_end; + + case_ast_node(be, BinaryExpr, cond); + if (be->op.kind == Token_CmpAnd) { + TB_Node *block = tb_inst_region(p->func); + tb_inst_set_region_name(block, -1, "cmp.and"); + cg_build_cond(p, be->left, block, false_block); + tb_inst_set_control(p->func, block); + cg_build_cond(p, be->right, true_block, false_block); + return no_comptime_short_circuit; + } else if (be->op.kind == Token_CmpOr) { + TB_Node *block = tb_inst_region(p->func); + tb_inst_set_region_name(block, -1, "cmp.or"); + cg_build_cond(p, be->left, true_block, block); + tb_inst_set_control(p->func, block); + cg_build_cond(p, be->right, true_block, false_block); + return no_comptime_short_circuit; + } + case_end; + } + + cgValue v = {}; + if (cg_is_expr_untyped_const(cond)) { + v = cg_expr_untyped_const_to_typed(p, cond, t_llvm_bool); + } else { + v = cg_build_expr(p, cond); + } + + v = cg_emit_conv(p, v, t_llvm_bool); + + tb_inst_if(p->func, v.node, true_block, false_block); + + return v; +} gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr); gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr) { @@ -1994,7 +2050,47 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) { case_ast_node(te, TernaryIfExpr, expr); - GB_PANIC("TODO(bill): TernaryIfExpr"); + cgValue incoming_values[2] = {}; + TB_Node *incoming_regions[2] = {}; + + TB_Node *then = tb_inst_region(p->func); + TB_Node *done = tb_inst_region(p->func); + TB_Node *else_ = tb_inst_region(p->func); + tb_inst_set_region_name(then, -1, "if.then"); + tb_inst_set_region_name(done, -1, "if.done"); + tb_inst_set_region_name(else_, -1, "if.else"); + + cg_build_cond(p, te->cond, then, else_); + tb_inst_set_control(p->func, then); + + Type *type = default_type(type_of_expr(expr)); + + incoming_values[0] = cg_emit_conv(p, cg_build_expr(p, te->x), type); + incoming_regions[0] = tb_inst_get_control(p->func); + + tb_inst_goto(p->func, done); + tb_inst_set_control(p->func, else_); + + incoming_values[1] = cg_emit_conv(p, cg_build_expr(p, te->y), type); + incoming_regions[1] = tb_inst_get_control(p->func); + + tb_inst_goto(p->func, done); + tb_inst_set_control(p->func, done); + + GB_ASSERT(incoming_values[0].kind == cgValue_Value || + incoming_values[0].kind == cgValue_Addr); + GB_ASSERT(incoming_values[0].kind == incoming_values[1].kind); + cgValue res = {}; + res.kind = incoming_values[0].kind; + res.type = type; + TB_DataType dt = cg_data_type(type); + if (res.kind == cgValue_Addr) { + dt = TB_TYPE_PTR; + } + res.node = tb_inst_incomplete_phi(p->func, dt, done, 2); + tb_inst_add_phi_operand(p->func, res.node, incoming_regions[0], incoming_values[0].node); + tb_inst_add_phi_operand(p->func, res.node, incoming_regions[1], incoming_values[1].node); + return res; case_end; case_ast_node(te, TernaryWhenExpr, expr); diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 85219ae44..b3ab0b778 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -244,11 +244,13 @@ gb_internal void cg_procedure_end(cgProcedure *p) { } // if (p->name == "main") { if (p->name == "bug.main") { - TB_Arena *arena = tb_default_arena(); - defer (arena->free(arena)); - TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena); - defer (tb_funcopt_exit(opt)); - tb_funcopt_print(opt); + // TB_Arena *arena = tb_default_arena(); + // defer (arena->free(arena)); + // TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena); + // defer (tb_funcopt_exit(opt)); + // tb_funcopt_print(opt); + + tb_function_print(p->func, tb_default_print_callback, stdout); } tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST); }