Răsfoiți Sursa

Fix `any` type and casting to `any`; Fix `switch` statement

gingerBill 5 ani în urmă
părinte
comite
f83e1b8b0a
1 a modificat fișierele cu 69 adăugiri și 64 ștergeri
  1. 69 64
      src/llvm_backend.cpp

+ 69 - 64
src/llvm_backend.cpp

@@ -239,7 +239,7 @@ lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) {
 	Type *tag_type = union_tag_type(ut);
 
 	lbValue tag_ptr = {};
-	tag_ptr.value = LLVMBuildStructGEP2(p->builder, lb_type(p->module, type_deref(u.type)), u.value, 2, "");
+	tag_ptr.value = LLVMBuildStructGEP(p->builder, u.value, 2, "");
 	tag_ptr.type = alloc_type_pointer(tag_type);
 	return tag_ptr;
 }
@@ -475,7 +475,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
 			{
 				LLVMTypeRef type = LLVMStructCreateNamed(ctx, "..any");
 				LLVMTypeRef fields[2] = {
-					LLVMPointerType(lb_type(m, t_rawptr), 0),
+					lb_type(m, t_rawptr),
 					lb_type(m, t_typeid),
 				};
 				LLVMStructSetBody(type, fields, 2, false);
@@ -2174,9 +2174,6 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 	case_end;
 
 	case_ast_node(ss, SwitchStmt, node);
-		if (true) {
-			return;
-		}
 		if (ss->init != nullptr) {
 			lb_build_stmt(p, ss->init);
 		}
@@ -2259,7 +2256,6 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 				lb_emit_if(p, cond, body, next_cond);
 				lb_start_block(p, next_cond);
 			}
-			lb_emit_jump(p, body);
 			lb_start_block(p, body);
 
 			lb_push_target_list(p, ss->label, done, nullptr, fall);
@@ -2269,7 +2265,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 			lb_pop_target_list(p);
 
 			lb_emit_jump(p, done);
-			p->curr_block = next_cond;
+			lb_start_block(p, next_cond);
 		}
 
 		if (default_block != nullptr) {
@@ -2282,6 +2278,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 			lb_close_scope(p, lbDeferExit_Default, default_block);
 			lb_pop_target_list(p);
 		}
+
 		lb_emit_jump(p, done);
 		lb_start_block(p, done);
 	case_end;
@@ -3403,9 +3400,18 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 
 	if (LLVMIsConstant(value.value)) {
 		if (is_type_any(dst)) {
-			lbAddr default_value = lb_add_local_generated(p, default_type(src_type), false);
+			Type *st = default_type(src_type);
+			lbAddr default_value = lb_add_local_generated(p, st, false);
 			lb_addr_store(p, default_value, value);
-			return lb_emit_conv(p, lb_addr_load(p, default_value), t_any);
+			lbValue data = lb_emit_conv(p, default_value.addr, t_rawptr);
+			lbValue id = lb_typeid(m, st);
+
+			lbAddr res = lb_add_local_generated(p, t, false);
+			lbValue a0 = lb_emit_struct_ep(p, res.addr, 0);
+			lbValue a1 = lb_emit_struct_ep(p, res.addr, 1);
+			lb_emit_store(p, a0, data);
+			lb_emit_store(p, a1, id);
+			return lb_addr_load(p, res);
 		} else if (dst->kind == Type_Basic) {
 			if (src->Basic.kind == Basic_string && dst->Basic.kind == Basic_cstring) {
 				// TODO(bill): This is kind of a hack
@@ -3721,7 +3727,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 	if (is_type_pointer(src) && is_type_pointer(dst)) {
 		lbValue res = {};
 		res.type = t;
-		res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(m, t), "");
+		res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
 		return res;
 	}
 
@@ -3731,7 +3737,7 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 	if (is_type_proc(src) && is_type_proc(dst)) {
 		lbValue res = {};
 		res.type = t;
-		res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(m, t), "");
+		res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
 		return res;
 	}
 
@@ -3739,73 +3745,67 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 	if (is_type_pointer(src) && is_type_proc(dst)) {
 		lbValue res = {};
 		res.type = t;
-		res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(m, t), "");
+		res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
 		return res;
 	}
 	// proc -> pointer
 	if (is_type_proc(src) && is_type_pointer(dst)) {
 		lbValue res = {};
 		res.type = t;
-		res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(m, t), "");
+		res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(m, t), "");
 		return res;
 	}
 
 
-#if 0
 
 	// []byte/[]u8 <-> string
 	if (is_type_u8_slice(src) && is_type_string(dst)) {
-		lbValue elem = ir_slice_elem(p, value);
-		lbValue len  = ir_slice_len(p, value);
-		return ir_emit_string(p, elem, len);
+		return lb_emit_transmute(p, value, t);
 	}
 	if (is_type_string(src) && is_type_u8_slice(dst)) {
-		lbValue elem = ir_string_elem(p, value);
-		lbValue elem_ptr = lb_add_local_generated(p, ir_type(elem), false);
-		lb_emit_store(p, elem_ptr, elem);
-
-		lbValue len  = ir_string_len(p, value);
-		lbValue slice = ir_add_local_slice(p, t, elem_ptr, v_zero, len);
-		return lb_emit_load(p, slice);
+		return lb_emit_transmute(p, value, t);
 	}
 
 	if (is_type_array(dst)) {
 		Type *elem = dst->Array.elem;
 		lbValue e = lb_emit_conv(p, value, elem);
 		// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
-		lbValue v = lb_add_local_generated(p, t, false);
+		lbAddr v = lb_add_local_generated(p, t, false);
 		isize index_count = cast(isize)dst->Array.count;
 
-		for (i32 i = 0; i < index_count; i++) {
-			lbValue elem = ir_emit_array_epi(p, v, i);
+		for (isize i = 0; i < index_count; i++) {
+			lbValue elem = lb_emit_array_epi(p, v.addr, i);
 			lb_emit_store(p, elem, e);
 		}
-		return lb_emit_load(p, v);
+		return lb_addr_load(p, v);
 	}
 
 	if (is_type_any(dst)) {
-		lbValue result = lb_add_local_generated(p, t_any, true);
-
 		if (is_type_untyped_nil(src)) {
-			return lb_emit_load(p, result);
+			return lb_const_nil(p->module, t);
+		}
+		if (is_type_untyped_undef(src)) {
+			return lb_const_undef(p->module, t);
 		}
 
+		lbAddr result = lb_add_local_generated(p, t, true);
+
 		Type *st = default_type(src_type);
 
-		lbValue data = ir_address_from_load_or_generate_local(p, value);
-		GB_ASSERT_MSG(is_type_pointer(ir_type(data)), type_to_string(ir_type(data)));
+		lbValue data = lb_address_from_load_or_generate_local(p, value);
+		GB_ASSERT_MSG(is_type_pointer(data.type), "%s", type_to_string(data.type));
 		GB_ASSERT_MSG(is_type_typed(st), "%s", type_to_string(st));
 		data = lb_emit_conv(p, data, t_rawptr);
 
-
 		lbValue id = lb_typeid(p->module, st);
+		lbValue any_data = lb_emit_struct_ep(p, result.addr, 0);
+		lbValue any_id   = lb_emit_struct_ep(p, result.addr, 1);
 
-		lb_emit_store(p, lb_emit_struct_ep(p, result, 0), data);
-		lb_emit_store(p, lb_emit_struct_ep(p, result, 1), id);
+		lb_emit_store(p, any_data, data);
+		lb_emit_store(p, any_id,   id);
 
-		return lb_emit_load(p, result);
+		return lb_addr_load(p, result);
 	}
-#endif
 
 	if (is_type_untyped(src)) {
 		if (is_type_string(src) && is_type_string(dst)) {
@@ -3915,6 +3915,11 @@ lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
 		return res;
 	}
 
+	if (is_type_pointer(src) && is_type_pointer(dst)) {
+		res.value = LLVMBuildPointerCast(p->builder, value.value, lb_type(p->module, t), "");
+		return res;
+	}
+
 	if (lb_is_type_aggregate(src) || lb_is_type_aggregate(dst)) {
 		lbValue s = lb_address_from_load_or_generate_local(p, value);
 		lbValue d = lb_emit_transmute(p, s, alloc_type_pointer(t));
@@ -3997,60 +4002,59 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
 	}
 
 	if (is_type_struct(t)) {
-		result_type = alloc_type_pointer(t->Struct.fields[index]->type);
+		result_type = t->Struct.fields[index]->type;
 	} else if (is_type_union(t)) {
 		GB_ASSERT(index == -1);
-		// return ir_emit_union_tag_ptr(p, s);
-		GB_PANIC("ir_emit_union_tag_ptr");
+		return lb_emit_union_tag_ptr(p, s);
 	} else if (is_type_tuple(t)) {
 		GB_ASSERT(t->Tuple.variables.count > 0);
-		result_type = alloc_type_pointer(t->Tuple.variables[index]->type);
+		result_type = t->Tuple.variables[index]->type;
 	} else if (is_type_complex(t)) {
 		Type *ft = base_complex_elem_type(t);
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(ft); break;
-		case 1: result_type = alloc_type_pointer(ft); break;
+		case 0: result_type = ft; break;
+		case 1: result_type = ft; break;
 		}
 	} else if (is_type_quaternion(t)) {
 		Type *ft = base_complex_elem_type(t);
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(ft); break;
-		case 1: result_type = alloc_type_pointer(ft); break;
-		case 2: result_type = alloc_type_pointer(ft); break;
-		case 3: result_type = alloc_type_pointer(ft); break;
+		case 0: result_type = ft; break;
+		case 1: result_type = ft; break;
+		case 2: result_type = ft; break;
+		case 3: result_type = ft; break;
 		}
 	} else if (is_type_slice(t)) {
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(alloc_type_pointer(t->Slice.elem)); break;
-		case 1: result_type = alloc_type_pointer(t_int); break;
+		case 0: result_type = alloc_type_pointer(t->Slice.elem); break;
+		case 1: result_type = t_int; break;
 		}
 	} else if (is_type_string(t)) {
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(t_u8_ptr); break;
-		case 1: result_type = alloc_type_pointer(t_int);    break;
+		case 0: result_type = t_u8_ptr; break;
+		case 1: result_type = t_int;    break;
 		}
 	} else if (is_type_any(t)) {
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(t_rawptr); break;
-		case 1: result_type = alloc_type_pointer(t_typeid); break;
+		case 0: result_type = t_rawptr; break;
+		case 1: result_type = t_typeid; break;
 		}
 	} else if (is_type_dynamic_array(t)) {
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(alloc_type_pointer(t->DynamicArray.elem)); break;
-		case 1: result_type = t_int_ptr;       break;
-		case 2: result_type = t_int_ptr;       break;
-		case 3: result_type = t_allocator_ptr; break;
+		case 0: result_type = alloc_type_pointer(t->DynamicArray.elem); break;
+		case 1: result_type = t_int;       break;
+		case 2: result_type = t_int;       break;
+		case 3: result_type = t_allocator; break;
 		}
 	} else if (is_type_map(t)) {
 		init_map_internal_types(t);
-		Type *itp = alloc_type_pointer(t->Map.internal_type);
+		Type *itp = (t->Map.internal_type);
 		s = lb_emit_transmute(p, s, itp);
 
 		Type *gst = t->Map.internal_type;
 		GB_ASSERT(gst->kind == Type_Struct);
 		switch (index) {
-		case 0: result_type = alloc_type_pointer(gst->Struct.fields[0]->type); break;
-		case 1: result_type = alloc_type_pointer(gst->Struct.fields[1]->type); break;
+		case 0: result_type = gst->Struct.fields[0]->type; break;
+		case 1: result_type = gst->Struct.fields[1]->type; break;
 		}
 	} else if (is_type_array(t)) {
 		return lb_emit_array_epi(p, s, index);
@@ -4061,8 +4065,8 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) {
 	GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index);
 
 	lbValue res = {};
-	res.value = LLVMBuildStructGEP2(p->builder, lb_type(p->module, type_deref(s.type)), s.value, cast(unsigned)index, "");
-	res.type = result_type;
+	res.value = LLVMBuildStructGEP(p->builder, s.value, cast(unsigned)index, "");
+	res.type = alloc_type_pointer(result_type);
 	return res;
 }
 
@@ -7739,7 +7743,8 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da
 		if (entry_index <= 0) {
 			continue;
 		}
-		gb_printf_err("%s @ %td | %.*s\n", type_to_string(t), entry_index, LIT(type_strings[t->kind]));
+
+		// gb_printf_err("%s @ %td | %.*s\n", type_to_string(t), entry_index, LIT(type_strings[t->kind
 
 		lbValue tag = {};
 		lbValue ti_ptr = lb_emit_array_epi(p, lb_global_type_info_data.addr, cast(i32)entry_index);