Browse Source

Implement Ternary If Expression

gingerBill 2 years ago
parent
commit
3535d16c3a
3 changed files with 108 additions and 10 deletions
  1. BIN
      src/tilde/tb.lib
  2. 101 5
      src/tilde_expr.cpp
  3. 7 5
      src/tilde_proc.cpp

BIN
src/tilde/tb.lib


+ 101 - 5
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);

+ 7 - 5
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);
 }