Browse Source

Begin work for `bit_set[...; [N]T]` (not working)

gingerBill 1 year ago
parent
commit
1e37eaf54d

+ 2 - 0
src/build_settings.cpp

@@ -440,6 +440,8 @@ struct BuildContext {
 	bool   cached;
 	bool   cached;
 	BuildCacheData build_cache_data;
 	BuildCacheData build_cache_data;
 
 
+	bool internal_no_inline;
+
 	bool   no_threaded_checker;
 	bool   no_threaded_checker;
 
 
 	bool   show_debug_messages;
 	bool   show_debug_messages;

+ 5 - 1
src/check_expr.cpp

@@ -9947,10 +9947,14 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
 		}
 		}
 		Type *et = base_type(t->BitSet.elem);
 		Type *et = base_type(t->BitSet.elem);
 		isize field_count = 0;
 		isize field_count = 0;
-		if (et->kind == Type_Enum) {
+		if (et != nullptr && et->kind == Type_Enum) {
 			field_count = et->Enum.fields.count;
 			field_count = et->Enum.fields.count;
 		}
 		}
 
 
+		if (is_type_array(bit_set_to_int(t))) {
+			is_constant = false;
+		}
+
 		if (cl->elems[0]->kind == Ast_FieldValue) {
 		if (cl->elems[0]->kind == Ast_FieldValue) {
 			error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed");
 			error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed");
 			is_constant = false;
 			is_constant = false;

+ 4 - 17
src/check_type.cpp

@@ -939,22 +939,6 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam
 	enum_type->Enum.max_value_index = max_value_index;
 	enum_type->Enum.max_value_index = max_value_index;
 }
 }
 
 
-gb_internal bool is_valid_bit_field_backing_type(Type *type) {
-	if (type == nullptr) {
-		return false;
-	}
-	type = base_type(type);
-	if (is_type_untyped(type)) {
-		return false;
-	}
-	if (is_type_integer(type)) {
-		return true;
-	}
-	if (type->kind == Type_Array) {
-		return is_type_integer(type->Array.elem);
-	}
-	return false;
-}
 
 
 gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Type *named_type, Ast *node) {
 gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Type *named_type, Ast *node) {
 	ast_node(bf, BitFieldType, node);
 	ast_node(bf, BitFieldType, node);
@@ -1268,11 +1252,14 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t
 		Type *t = default_type(lhs.type);
 		Type *t = default_type(lhs.type);
 		if (bs->underlying != nullptr) {
 		if (bs->underlying != nullptr) {
 			Type *u = check_type(c, bs->underlying);
 			Type *u = check_type(c, bs->underlying);
+			// if (!is_valid_bit_field_backing_type(u)) {
 			if (!is_type_integer(u)) {
 			if (!is_type_integer(u)) {
 				gbString ts = type_to_string(u);
 				gbString ts = type_to_string(u);
 				error(bs->underlying, "Expected an underlying integer for the bit set, got %s", ts);
 				error(bs->underlying, "Expected an underlying integer for the bit set, got %s", ts);
 				gb_string_free(ts);
 				gb_string_free(ts);
-				return;
+				if (!is_valid_bit_field_backing_type(u)) {
+					return;
+				}
 			}
 			}
 			type->BitSet.underlying = u;
 			type->BitSet.underlying = u;
 		}
 		}

+ 2 - 0
src/llvm_backend_const.cpp

@@ -434,6 +434,8 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi
 		}
 		}
 	}
 	}
 
 
+	GB_ASSERT(!is_type_array(original_type));
+
 	LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((sz+7)/8), cast(u64 *)rop);
 	LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((sz+7)/8), cast(u64 *)rop);
 	if (big_int_is_neg(a)) {
 	if (big_int_is_neg(a)) {
 		value = LLVMConstNeg(value);
 		value = LLVMConstNeg(value);

+ 95 - 25
src/llvm_backend_expr.cpp

@@ -296,12 +296,6 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu
 		GB_ASSERT(vector_type0 == vector_type1);
 		GB_ASSERT(vector_type0 == vector_type1);
 		LLVMTypeRef vector_type = vector_type0;
 		LLVMTypeRef vector_type = vector_type0;
 
 
-		LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), "");
-		LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), "");
-		LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, "");
-		LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, "");
-		LLVMValueRef z = nullptr;
-
 		Type *integral_type = base_type(elem_type);
 		Type *integral_type = base_type(elem_type);
 		if (is_type_simd_vector(integral_type)) {
 		if (is_type_simd_vector(integral_type)) {
 			integral_type = core_array_type(integral_type);
 			integral_type = core_array_type(integral_type);
@@ -311,8 +305,18 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu
 			case Token_Add: op = Token_Or;     break;
 			case Token_Add: op = Token_Or;     break;
 			case Token_Sub: op = Token_AndNot; break;
 			case Token_Sub: op = Token_AndNot; break;
 			}
 			}
+			Type *u = bit_set_to_int(type);
+			if (is_type_array(u)) {
+				return false;
+			}
 		}
 		}
 
 
+		LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), "");
+		LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), "");
+		LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, "");
+		LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, "");
+		LLVMValueRef z = nullptr;
+
 		if (is_type_float(integral_type)) {
 		if (is_type_float(integral_type)) {
 			switch (op) {
 			switch (op) {
 			case Token_Add:
 			case Token_Add:
@@ -1286,6 +1290,14 @@ handle_op:;
 		case Token_Add: op = Token_Or;     break;
 		case Token_Add: op = Token_Or;     break;
 		case Token_Sub: op = Token_AndNot; break;
 		case Token_Sub: op = Token_AndNot; break;
 		}
 		}
+		Type *u = bit_set_to_int(type);
+		if (is_type_array(u)) {
+			lhs.type = u;
+			rhs.type = u;
+			res = lb_emit_arith(p, op, lhs, rhs, u);
+			res.type = type;
+			return res;
+		}
 	}
 	}
 
 
 	Type *integral_type = type;
 	Type *integral_type = type;
@@ -1441,6 +1453,7 @@ gb_internal lbValue lb_build_binary_in(lbProcedure *p, lbValue left, lbValue rig
 			GB_ASSERT(are_types_identical(left.type, key_type));
 			GB_ASSERT(are_types_identical(left.type, key_type));
 
 
 			Type *it = bit_set_to_int(rt);
 			Type *it = bit_set_to_int(rt);
+
 			left = lb_emit_conv(p, left, it);
 			left = lb_emit_conv(p, left, it);
 			if (is_type_different_to_arch_endianness(it)) {
 			if (is_type_different_to_arch_endianness(it)) {
 				left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
 				left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it));
@@ -2054,6 +2067,26 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
 		}
 		}
 	}
 	}
 
 
+	// bit_set <-> backing type
+	if (is_type_bit_set(src)) {
+		Type *backing = bit_set_to_int(src);
+		if (are_types_identical(backing, dst)) {
+			lbValue res = {};
+			res.type = t;
+			res.value = value.value;
+			return res;
+		}
+	}
+	if (is_type_bit_set(dst)) {
+		Type *backing = bit_set_to_int(dst);
+		if (are_types_identical(src, backing)) {
+			lbValue res = {};
+			res.type = t;
+			res.value = value.value;
+			return res;
+		}
+	}
+
 
 
 	// Pointer <-> uintptr
 	// Pointer <-> uintptr
 	if (is_type_pointer(src) && is_type_uintptr(dst)) {
 	if (is_type_pointer(src) && is_type_uintptr(dst)) {
@@ -2951,13 +2984,32 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind,
 	case Type_Pointer:
 	case Type_Pointer:
 	case Type_MultiPointer:
 	case Type_MultiPointer:
 	case Type_Proc:
 	case Type_Proc:
-	case Type_BitSet:
 		if (op_kind == Token_CmpEq) {
 		if (op_kind == Token_CmpEq) {
 			res.value = LLVMBuildIsNull(p->builder, x.value, "");
 			res.value = LLVMBuildIsNull(p->builder, x.value, "");
 		} else if (op_kind == Token_NotEq) {
 		} else if (op_kind == Token_NotEq) {
 			res.value = LLVMBuildIsNotNull(p->builder, x.value, "");
 			res.value = LLVMBuildIsNotNull(p->builder, x.value, "");
 		}
 		}
 		return res;
 		return res;
+	case Type_BitSet:
+		{
+			Type *u = bit_set_to_int(bt);
+			if (is_type_array(u)) {
+				auto args = array_make<lbValue>(permanent_allocator(), 2);
+				lbValue lhs = lb_address_from_load_or_generate_local(p, x);
+				args[0] = lb_emit_conv(p, lhs, t_rawptr);
+				args[1] = lb_const_int(p->module, t_int, type_size_of(t));
+				lbValue val = lb_emit_runtime_call(p, "memory_compare_zero", args);
+				lbValue res = lb_emit_comp(p, op_kind, val, lb_const_int(p->module, t_int, 0));
+				return res;
+			} else {
+				if (op_kind == Token_CmpEq) {
+					res.value = LLVMBuildIsNull(p->builder, x.value, "");
+				} else if (op_kind == Token_NotEq) {
+					res.value = LLVMBuildIsNotNull(p->builder, x.value, "");
+				}
+			}
+			return res;
+		}
 
 
 	case Type_Slice:
 	case Type_Slice:
 		{
 		{
@@ -4878,29 +4930,47 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
 	case Type_BitSet: {
 	case Type_BitSet: {
 		i64 sz = type_size_of(type);
 		i64 sz = type_size_of(type);
 		if (cl->elems.count > 0 && sz > 0) {
 		if (cl->elems.count > 0 && sz > 0) {
-			lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr)));
-
 			lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower));
 			lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower));
-			for (Ast *elem : cl->elems) {
-				GB_ASSERT(elem->kind != Ast_FieldValue);
 
 
-				if (lb_is_elem_const(elem, et)) {
-					continue;
+			Type *backing = bit_set_to_int(type);
+			if (is_type_array(backing)) {
+				GB_PANIC("TODO: bit_set [N]T");
+				Type *base_it = core_array_type(backing);
+				i64 bits_per_elem = 8*type_size_of(base_it);
+				gb_unused(bits_per_elem);
+				lbValue one = lb_const_value(p->module, t_i64, exact_value_i64(1));
+				for (Ast *elem : cl->elems) {
+					GB_ASSERT(elem->kind != Ast_FieldValue);
+					lbValue expr = lb_build_expr(p, elem);
+					GB_ASSERT(expr.type->kind != Type_Tuple);
+
+					lbValue e = lb_emit_conv(p, expr, t_i64);
+					e = lb_emit_arith(p, Token_Sub, e, lower, t_i64);
+					// lbValue idx = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64);
+					// lbValue val = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64);
 				}
 				}
-
-				lbValue expr = lb_build_expr(p, elem);
-				GB_ASSERT(expr.type->kind != Type_Tuple);
-
+			} else {
 				Type *it = bit_set_to_int(bt);
 				Type *it = bit_set_to_int(bt);
 				lbValue one = lb_const_value(p->module, it, exact_value_i64(1));
 				lbValue one = lb_const_value(p->module, it, exact_value_i64(1));
-				lbValue e = lb_emit_conv(p, expr, it);
-				e = lb_emit_arith(p, Token_Sub, e, lower, it);
-				e = lb_emit_arith(p, Token_Shl, one, e, it);
-
-				lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
-				lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
-				new_value = lb_emit_transmute(p, new_value, type);
-				lb_addr_store(p, v, new_value);
+				for (Ast *elem : cl->elems) {
+					GB_ASSERT(elem->kind != Ast_FieldValue);
+
+					if (lb_is_elem_const(elem, et)) {
+						continue;
+					}
+
+					lbValue expr = lb_build_expr(p, elem);
+					GB_ASSERT(expr.type->kind != Type_Tuple);
+
+					lbValue e = lb_emit_conv(p, expr, it);
+					e = lb_emit_arith(p, Token_Sub, e, lower, it);
+					e = lb_emit_arith(p, Token_Shl, one, e, it);
+
+					lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it);
+					lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it);
+					new_value = lb_emit_transmute(p, new_value, type);
+					lb_addr_store(p, v, new_value);
+				}
 			}
 			}
 		}
 		}
 		break;
 		break;

+ 2 - 0
src/llvm_backend_general.cpp

@@ -1023,6 +1023,8 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
 			LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr);
 			LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr);
 			LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0);
 			LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0);
 			LLVMBuildStore(p->builder, LLVMConstNull(rawptr_type), LLVMBuildBitCast(p->builder, ptr.value, rawptr_ptr_type, ""));
 			LLVMBuildStore(p->builder, LLVMConstNull(rawptr_type), LLVMBuildBitCast(p->builder, ptr.value, rawptr_ptr_type, ""));
+		} else if (is_type_bit_set(a)) {
+			lb_mem_zero_ptr(p, ptr.value, a, 1);
 		} else if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
 		} else if (lb_sizeof(src_t) <= lb_max_zero_init_size()) {
 			LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
 			LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value);
 		} else {
 		} else {

+ 5 - 0
src/llvm_backend_proc.cpp

@@ -159,6 +159,11 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i
 	case ProcInlining_no_inline:
 	case ProcInlining_no_inline:
 		lb_add_attribute_to_proc(m, p->value, "noinline");
 		lb_add_attribute_to_proc(m, p->value, "noinline");
 		break;
 		break;
+	default:
+		if (build_context.internal_no_inline) {
+			lb_add_attribute_to_proc(m, p->value, "noinline");
+			break;
+		}
 	}
 	}
 
 
 	switch (entity->Procedure.optimization_mode) {
 	switch (entity->Procedure.optimization_mode) {

+ 5 - 0
src/main.cpp

@@ -394,6 +394,7 @@ enum BuildFlagKind {
 	BuildFlag_InternalIgnorePanic,
 	BuildFlag_InternalIgnorePanic,
 	BuildFlag_InternalModulePerFile,
 	BuildFlag_InternalModulePerFile,
 	BuildFlag_InternalCached,
 	BuildFlag_InternalCached,
+	BuildFlag_InternalNoInline,
 
 
 	BuildFlag_Tilde,
 	BuildFlag_Tilde,
 
 
@@ -598,6 +599,7 @@ gb_internal bool parse_build_flags(Array<String> args) {
 	add_flag(&build_flags, BuildFlag_InternalIgnorePanic,     str_lit("internal-ignore-panic"),     BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalIgnorePanic,     str_lit("internal-ignore-panic"),     BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalModulePerFile,   str_lit("internal-module-per-file"),  BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalModulePerFile,   str_lit("internal-module-per-file"),  BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalCached,          str_lit("internal-cached"),           BuildFlagParam_None,    Command_all);
 	add_flag(&build_flags, BuildFlag_InternalCached,          str_lit("internal-cached"),           BuildFlagParam_None,    Command_all);
+	add_flag(&build_flags, BuildFlag_InternalNoInline,        str_lit("internal-no-inline"),        BuildFlagParam_None,    Command_all);
 
 
 #if ALLOW_TILDE
 #if ALLOW_TILDE
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
 	add_flag(&build_flags, BuildFlag_Tilde,                   str_lit("tilde"),                     BuildFlagParam_None,    Command__does_build);
@@ -1422,6 +1424,9 @@ gb_internal bool parse_build_flags(Array<String> args) {
 							build_context.cached = true;
 							build_context.cached = true;
 							build_context.use_separate_modules = true;
 							build_context.use_separate_modules = true;
 							break;
 							break;
+						case BuildFlag_InternalNoInline:
+							build_context.internal_no_inline = true;
+							break;
 
 
 						case BuildFlag_Tilde:
 						case BuildFlag_Tilde:
 							build_context.tilde_backend = true;
 							build_context.tilde_backend = true;

+ 21 - 0
src/types.cpp

@@ -2011,6 +2011,24 @@ gb_internal bool is_type_valid_bit_set_elem(Type *t) {
 	return false;
 	return false;
 }
 }
 
 
+
+gb_internal bool is_valid_bit_field_backing_type(Type *type) {
+	if (type == nullptr) {
+		return false;
+	}
+	type = base_type(type);
+	if (is_type_untyped(type)) {
+		return false;
+	}
+	if (is_type_integer(type)) {
+		return true;
+	}
+	if (type->kind == Type_Array) {
+		return is_type_integer(type->Array.elem);
+	}
+	return false;
+}
+
 gb_internal Type *bit_set_to_int(Type *t) {
 gb_internal Type *bit_set_to_int(Type *t) {
 	GB_ASSERT(is_type_bit_set(t));
 	GB_ASSERT(is_type_bit_set(t));
 	Type *bt = base_type(t);
 	Type *bt = base_type(t);
@@ -2018,6 +2036,9 @@ gb_internal Type *bit_set_to_int(Type *t) {
 	if (underlying != nullptr && is_type_integer(underlying)) {
 	if (underlying != nullptr && is_type_integer(underlying)) {
 		return underlying;
 		return underlying;
 	}
 	}
+	if (underlying != nullptr && is_valid_bit_field_backing_type(underlying)) {
+		return underlying;
+	}
 
 
 	i64 sz = type_size_of(t);
 	i64 sz = type_size_of(t);
 	switch (sz) {
 	switch (sz) {