aboutsummaryrefslogtreecommitdiff
path: root/src/tilde_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-18 18:58:56 +0100
committergingerBill <bill@gingerbill.org>2023-07-18 18:58:56 +0100
commit3535d16c3a9f2a16b420f34777cbbc56ccadfd5d (patch)
tree05286559556a4e7234e8ed6805696d66c7c4a27b /src/tilde_expr.cpp
parent7f4efa90c8259d119e177c58fa150977136b4e86 (diff)
Implement Ternary If Expression
Diffstat (limited to 'src/tilde_expr.cpp')
-rw-r--r--src/tilde_expr.cpp106
1 files changed, 101 insertions, 5 deletions
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);