Implement Ternary If Expression

This commit is contained in:
gingerBill
2023-07-18 18:58:56 +01:00
parent 7f4efa90c8
commit 3535d16c3a
3 changed files with 108 additions and 10 deletions

View File

@@ -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);