Browse Source

Add `intrinsics.type_struct_has_implicit_padding` #3844

gingerBill 1 year ago
parent
commit
544959326b
4 changed files with 31 additions and 2 deletions
  1. 2 1
      base/intrinsics/intrinsics.odin
  2. 25 0
      src/check_builtin.cpp
  3. 3 1
      src/checker_builtin_procs.hpp
  4. 1 0
      src/types.cpp

+ 2 - 1
base/intrinsics/intrinsics.odin

@@ -194,7 +194,8 @@ type_proc_return_count    :: proc($T: typeid) -> int where type_is_proc(T) ---
 type_proc_parameter_type  :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 type_proc_return_type     :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
 
-type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
+type_struct_field_count          :: proc($T: typeid) -> int  where type_is_struct(T) ---
+type_struct_has_implicit_padding :: proc($T: typeid) -> bool where type_is_struct(T) ---
 
 type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
 type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---

+ 25 - 0
src/check_builtin.cpp

@@ -5839,6 +5839,31 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
 		operand->mode = Addressing_Constant;
 		operand->type = t_untyped_integer;
 		break;
+	case BuiltinProc_type_struct_has_implicit_padding:
+		operand->value = exact_value_bool(false);
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name));
+		} else if (!is_type_struct(operand->type) && !is_type_soa_struct(operand->type)) {
+			error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name));
+		} else {
+			Type *bt = base_type(operand->type);
+			if (bt->Struct.is_packed) {
+				operand->value = exact_value_bool(false);
+			} else if (bt->Struct.fields.count != 0) {
+				i64 size = type_size_of(bt);
+				Type *field_type = nullptr;
+				i64 last_offset = type_offset_of(bt, bt->Struct.fields.count-1, &field_type);
+				if (last_offset+type_size_of(field_type) < size) {
+					operand->value = exact_value_bool(true);
+				} else {
+					i64 packed_size = type_size_of_struct_pretend_is_packed(bt);
+					operand->value = exact_value_bool(packed_size < size);
+				}
+			}
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
 
 	case BuiltinProc_type_proc_parameter_count:
 		operand->value = exact_value_i64(0);

+ 3 - 1
src/checker_builtin_procs.hpp

@@ -277,6 +277,7 @@ BuiltinProc__type_simple_boolean_end,
 	BuiltinProc_type_bit_set_underlying_type,
 
 	BuiltinProc_type_struct_field_count,
+	BuiltinProc_type_struct_has_implicit_padding,
 
 	BuiltinProc_type_proc_parameter_count,
 	BuiltinProc_type_proc_return_count,
@@ -593,7 +594,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("type_bit_set_elem_type"),       1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_bit_set_underlying_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 
-	{STR_LIT("type_struct_field_count"),   1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_struct_field_count"),          1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_struct_has_implicit_padding"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 
 	{STR_LIT("type_proc_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("type_proc_return_count"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics},

+ 1 - 0
src/types.cpp

@@ -2366,6 +2366,7 @@ gb_internal bool type_has_nil(Type *t) {
 	return false;
 }
 
+
 gb_internal bool elem_type_can_be_constant(Type *t) {
 	t = base_type(t);
 	if (t == t_invalid) {