Browse Source

`intrinsics.type_*` constant evaluation procedures

gingerBill 6 years ago
parent
commit
37633c1d2a
5 changed files with 740 additions and 221 deletions
  1. 411 1
      src/check_expr.cpp
  2. 2 212
      src/checker.hpp
  3. 312 0
      src/checker_builtin_procs.hpp
  4. 2 8
      src/exact_value.cpp
  5. 13 0
      src/types.cpp

+ 411 - 1
src/check_expr.cpp

@@ -3178,7 +3178,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 		/*fallthrough*/
 	}
 	default:
-		if (ce->args.count > 0) {
+		if (BuiltinProc__type_begin < id && id < BuiltinProc__type_end) {
+			check_expr_or_type(c, operand, ce->args[0]);
+		} else if (ce->args.count > 0) {
 			check_multi_expr(c, operand, ce->args[0]);
 		}
 		break;
@@ -4445,6 +4447,414 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			break;
 		}
 		break;
+
+	case BuiltinProc_type_base_type:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+		} else {
+			operand->type = base_type(operand->type);
+		}
+		operand->mode = Addressing_Type;
+		break;
+	case BuiltinProc_type_core_type:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+		} else {
+			operand->type = core_type(operand->type);
+		}
+		operand->mode = Addressing_Type;
+		break;
+
+	case BuiltinProc_type_is_boolean:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_boolean(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_integer:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_integer(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_rune:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_rune(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_float:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+		} else {
+
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_complex:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_complex(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_string:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_string(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_typeid:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_typeid(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_any:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_any(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+
+	case BuiltinProc_type_is_endian_little:
+		operand->value = exact_value_bool(false);
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected an integer type for '%.*s'", LIT(builtin_name));
+		} else if (!is_type_integer(operand->type)) {
+			error(operand->expr, "Expected an integer type for '%.*s'", LIT(builtin_name));
+		} else {
+			operand->value = exact_value_bool(is_type_integer_endian_little(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_endian_big:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else if (!is_type_integer(operand->type)) {
+			error(operand->expr, "Expected an integer type for '%.*s'", LIT(builtin_name));
+		} else {
+			operand->value = exact_value_bool(is_type_integer_endian_big(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_numeric:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_numeric(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_ordered:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_ordered(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_ordered_numeric:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_numeric(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_indexable:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_indexable(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_sliceable:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_sliceable(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_simple_compare:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_simple_compare(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_dereferenceable:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			if (is_type_rawptr(operand->type)) {
+				operand->value = exact_value_bool(false);
+			} else if (is_type_pointer(operand->type)) {
+				operand->value = exact_value_bool(true);
+			} else {
+				operand->value = exact_value_bool(false);
+			}
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+
+	case BuiltinProc_type_is_named:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_named(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_pointer:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_pointer(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_opaque:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_opaque(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_array:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_array(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_slice:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_slice(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_dynamic_array:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_dynamic_array(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_map:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_map(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_struct:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_struct(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_union:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_union(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_enum:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_enum(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_proc:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_proc(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_bit_field:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_bit_field(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_bit_field_value:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_bit_field_value(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_bit_set:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_bit_set(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+	case BuiltinProc_type_is_simd_vector:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+			operand->value = exact_value_bool(false);
+		} else {
+			operand->value = exact_value_bool(is_type_simd_vector(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+
+	case BuiltinProc_type_has_nil:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+		} else {
+			operand->value = exact_value_bool(type_has_nil(operand->type));
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_bool;
+		break;
+
+	case BuiltinProc_type_elem_type:
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
+		} else {
+			Type *bt = base_type(operand->type);
+			switch (bt->kind) {
+			case Type_Basic:
+				switch (bt->Basic.kind) {
+				case Basic_complex64:  operand->type = t_f32; break;
+				case Basic_complex128: operand->type = t_f64; break;
+				}
+				break;
+			case Type_Pointer:      operand->type = bt->Pointer.elem;      break;
+			case Type_Opaque:       operand->type = bt->Opaque.elem;       break;
+			case Type_Array:        operand->type = bt->Array.elem;        break;
+			case Type_Slice:        operand->type = bt->Slice.elem;        break;
+			case Type_DynamicArray: operand->type = bt->DynamicArray.elem; break;
+			}
+		}
+		operand->mode = Addressing_Type;
+		break;
+
+	case BuiltinProc_type_proc_parameter_count:
+		operand->value = exact_value_i64(0);
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name));
+		} else if (!is_type_proc(operand->type)) {
+			error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name));
+		} else {
+			Type *bt = base_type(operand->type);
+			operand->value = exact_value_i64(bt->Proc.param_count);
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_integer;
+		break;
+	case BuiltinProc_type_proc_return_count:
+		operand->value = exact_value_i64(0);
+		if (operand->mode != Addressing_Type) {
+			error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name));
+		} else if (!is_type_proc(operand->type)) {
+			error(operand->expr, "Expected a procedure type for '%.*s'", LIT(builtin_name));
+		} else {
+			Type *bt = base_type(operand->type);
+			operand->value = exact_value_i64(bt->Proc.result_count);
+		}
+		operand->mode = Addressing_Constant;
+		operand->type = t_untyped_integer;
+		break;
 	}
 
 	return true;

+ 2 - 212
src/checker.hpp

@@ -59,218 +59,8 @@ struct BuiltinProc {
 	BuiltinProcPkg pkg;
 };
 
-enum BuiltinProcId {
-	BuiltinProc_Invalid,
-
-	BuiltinProc_len,
-	BuiltinProc_cap,
-
-	BuiltinProc_size_of,
-	BuiltinProc_align_of,
-	BuiltinProc_offset_of,
-	BuiltinProc_type_of,
-	BuiltinProc_type_info_of,
-	BuiltinProc_typeid_of,
-
-	BuiltinProc_swizzle,
-
-	BuiltinProc_complex,
-	BuiltinProc_real,
-	BuiltinProc_imag,
-	BuiltinProc_conj,
-
-	BuiltinProc_expand_to_tuple,
-
-	BuiltinProc_min,
-	BuiltinProc_max,
-	BuiltinProc_abs,
-	BuiltinProc_clamp,
-
-	BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
-
-	// "Intrinsics"
-	BuiltinProc_vector,
-
-	BuiltinProc_atomic_fence,
-	BuiltinProc_atomic_fence_acq,
-	BuiltinProc_atomic_fence_rel,
-	BuiltinProc_atomic_fence_acqrel,
-
-	BuiltinProc_atomic_store,
-	BuiltinProc_atomic_store_rel,
-	BuiltinProc_atomic_store_relaxed,
-	BuiltinProc_atomic_store_unordered,
-
-	BuiltinProc_atomic_load,
-	BuiltinProc_atomic_load_acq,
-	BuiltinProc_atomic_load_relaxed,
-	BuiltinProc_atomic_load_unordered,
-
-	BuiltinProc_atomic_add,
-	BuiltinProc_atomic_add_acq,
-	BuiltinProc_atomic_add_rel,
-	BuiltinProc_atomic_add_acqrel,
-	BuiltinProc_atomic_add_relaxed,
-	BuiltinProc_atomic_sub,
-	BuiltinProc_atomic_sub_acq,
-	BuiltinProc_atomic_sub_rel,
-	BuiltinProc_atomic_sub_acqrel,
-	BuiltinProc_atomic_sub_relaxed,
-	BuiltinProc_atomic_and,
-	BuiltinProc_atomic_and_acq,
-	BuiltinProc_atomic_and_rel,
-	BuiltinProc_atomic_and_acqrel,
-	BuiltinProc_atomic_and_relaxed,
-	BuiltinProc_atomic_nand,
-	BuiltinProc_atomic_nand_acq,
-	BuiltinProc_atomic_nand_rel,
-	BuiltinProc_atomic_nand_acqrel,
-	BuiltinProc_atomic_nand_relaxed,
-	BuiltinProc_atomic_or,
-	BuiltinProc_atomic_or_acq,
-	BuiltinProc_atomic_or_rel,
-	BuiltinProc_atomic_or_acqrel,
-	BuiltinProc_atomic_or_relaxed,
-	BuiltinProc_atomic_xor,
-	BuiltinProc_atomic_xor_acq,
-	BuiltinProc_atomic_xor_rel,
-	BuiltinProc_atomic_xor_acqrel,
-	BuiltinProc_atomic_xor_relaxed,
-
-	BuiltinProc_atomic_xchg,
-	BuiltinProc_atomic_xchg_acq,
-	BuiltinProc_atomic_xchg_rel,
-	BuiltinProc_atomic_xchg_acqrel,
-	BuiltinProc_atomic_xchg_relaxed,
-
-	BuiltinProc_atomic_cxchg,
-	BuiltinProc_atomic_cxchg_acq,
-	BuiltinProc_atomic_cxchg_rel,
-	BuiltinProc_atomic_cxchg_acqrel,
-	BuiltinProc_atomic_cxchg_relaxed,
-	BuiltinProc_atomic_cxchg_failrelaxed,
-	BuiltinProc_atomic_cxchg_failacq,
-	BuiltinProc_atomic_cxchg_acq_failrelaxed,
-	BuiltinProc_atomic_cxchg_acqrel_failrelaxed,
-
-	BuiltinProc_atomic_cxchgweak,
-	BuiltinProc_atomic_cxchgweak_acq,
-	BuiltinProc_atomic_cxchgweak_rel,
-	BuiltinProc_atomic_cxchgweak_acqrel,
-	BuiltinProc_atomic_cxchgweak_relaxed,
-	BuiltinProc_atomic_cxchgweak_failrelaxed,
-	BuiltinProc_atomic_cxchgweak_failacq,
-	BuiltinProc_atomic_cxchgweak_acq_failrelaxed,
-	BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed,
-
-	BuiltinProc_COUNT,
-};
-gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
-	{STR_LIT(""),                 0, false, Expr_Stmt, BuiltinProcPkg_builtin},
-
-	{STR_LIT("len"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("cap"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT("size_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("align_of"),         1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("offset_of"),        2, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("type_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("type_info_of"),     1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("typeid_of"),        1, false, Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT("swizzle"),          1, true,  Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT("complex"),          2, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("real"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("imag"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("conj"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT("expand_to_tuple"),  1, false, Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT("min"),              1, true,  Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("max"),              1, true,  Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("abs"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
-	{STR_LIT("clamp"),            3, false, Expr_Expr, BuiltinProcPkg_builtin},
-
-	{STR_LIT(""),                 0, true,  Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
-
-
-	// "Intrinsics"
-	{STR_LIT("vector"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type
-
-
-	{STR_LIT("atomic_fence"),        0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_fence_acq"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_fence_rel"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_fence_acqrel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_store"),           2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_store_rel"),       2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_store_relaxed"),   2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_store_unordered"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_load"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_load_acq"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_load_relaxed"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_load_unordered"),  1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_add"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_add_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_add_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_add_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_add_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_sub"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_sub_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_sub_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_sub_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_sub_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_and"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_and_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_and_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_and_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_and_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_nand"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_nand_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_nand_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_nand_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_nand_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_or"),              2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_or_acq"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_or_rel"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_or_acqrel"),       2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_or_relaxed"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xor"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xor_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xor_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xor_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xor_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_xchg"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xchg_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xchg_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xchg_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_xchg_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_cxchg"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchg_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-
-	{STR_LIT("atomic_cxchgweak"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-	{STR_LIT("atomic_cxchgweak_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
-};
+
+#include "checker_builtin_procs.hpp"
 
 
 // Operand is used as an intermediate value whilst checking

+ 312 - 0
src/checker_builtin_procs.hpp

@@ -0,0 +1,312 @@
+// checker_builtin_procs.hpp
+
+enum BuiltinProcId {
+	BuiltinProc_Invalid,
+
+	BuiltinProc_len,
+	BuiltinProc_cap,
+
+	BuiltinProc_size_of,
+	BuiltinProc_align_of,
+	BuiltinProc_offset_of,
+	BuiltinProc_type_of,
+	BuiltinProc_type_info_of,
+	BuiltinProc_typeid_of,
+
+	BuiltinProc_swizzle,
+
+	BuiltinProc_complex,
+	BuiltinProc_real,
+	BuiltinProc_imag,
+	BuiltinProc_conj,
+
+	BuiltinProc_expand_to_tuple,
+
+	BuiltinProc_min,
+	BuiltinProc_max,
+	BuiltinProc_abs,
+	BuiltinProc_clamp,
+
+	BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
+
+	// "Intrinsics"
+	BuiltinProc_vector,
+
+	BuiltinProc_atomic_fence,
+	BuiltinProc_atomic_fence_acq,
+	BuiltinProc_atomic_fence_rel,
+	BuiltinProc_atomic_fence_acqrel,
+
+	BuiltinProc_atomic_store,
+	BuiltinProc_atomic_store_rel,
+	BuiltinProc_atomic_store_relaxed,
+	BuiltinProc_atomic_store_unordered,
+
+	BuiltinProc_atomic_load,
+	BuiltinProc_atomic_load_acq,
+	BuiltinProc_atomic_load_relaxed,
+	BuiltinProc_atomic_load_unordered,
+
+	BuiltinProc_atomic_add,
+	BuiltinProc_atomic_add_acq,
+	BuiltinProc_atomic_add_rel,
+	BuiltinProc_atomic_add_acqrel,
+	BuiltinProc_atomic_add_relaxed,
+	BuiltinProc_atomic_sub,
+	BuiltinProc_atomic_sub_acq,
+	BuiltinProc_atomic_sub_rel,
+	BuiltinProc_atomic_sub_acqrel,
+	BuiltinProc_atomic_sub_relaxed,
+	BuiltinProc_atomic_and,
+	BuiltinProc_atomic_and_acq,
+	BuiltinProc_atomic_and_rel,
+	BuiltinProc_atomic_and_acqrel,
+	BuiltinProc_atomic_and_relaxed,
+	BuiltinProc_atomic_nand,
+	BuiltinProc_atomic_nand_acq,
+	BuiltinProc_atomic_nand_rel,
+	BuiltinProc_atomic_nand_acqrel,
+	BuiltinProc_atomic_nand_relaxed,
+	BuiltinProc_atomic_or,
+	BuiltinProc_atomic_or_acq,
+	BuiltinProc_atomic_or_rel,
+	BuiltinProc_atomic_or_acqrel,
+	BuiltinProc_atomic_or_relaxed,
+	BuiltinProc_atomic_xor,
+	BuiltinProc_atomic_xor_acq,
+	BuiltinProc_atomic_xor_rel,
+	BuiltinProc_atomic_xor_acqrel,
+	BuiltinProc_atomic_xor_relaxed,
+
+	BuiltinProc_atomic_xchg,
+	BuiltinProc_atomic_xchg_acq,
+	BuiltinProc_atomic_xchg_rel,
+	BuiltinProc_atomic_xchg_acqrel,
+	BuiltinProc_atomic_xchg_relaxed,
+
+	BuiltinProc_atomic_cxchg,
+	BuiltinProc_atomic_cxchg_acq,
+	BuiltinProc_atomic_cxchg_rel,
+	BuiltinProc_atomic_cxchg_acqrel,
+	BuiltinProc_atomic_cxchg_relaxed,
+	BuiltinProc_atomic_cxchg_failrelaxed,
+	BuiltinProc_atomic_cxchg_failacq,
+	BuiltinProc_atomic_cxchg_acq_failrelaxed,
+	BuiltinProc_atomic_cxchg_acqrel_failrelaxed,
+
+	BuiltinProc_atomic_cxchgweak,
+	BuiltinProc_atomic_cxchgweak_acq,
+	BuiltinProc_atomic_cxchgweak_rel,
+	BuiltinProc_atomic_cxchgweak_acqrel,
+	BuiltinProc_atomic_cxchgweak_relaxed,
+	BuiltinProc_atomic_cxchgweak_failrelaxed,
+	BuiltinProc_atomic_cxchgweak_failacq,
+	BuiltinProc_atomic_cxchgweak_acq_failrelaxed,
+	BuiltinProc_atomic_cxchgweak_acqrel_failrelaxed,
+
+
+	// Constant type tests
+BuiltinProc__type_begin,
+
+	BuiltinProc_type_base_type,
+	BuiltinProc_type_core_type,
+
+	BuiltinProc_type_is_boolean,
+	BuiltinProc_type_is_integer,
+	BuiltinProc_type_is_rune,
+	BuiltinProc_type_is_float,
+	BuiltinProc_type_is_complex,
+	BuiltinProc_type_is_string,
+	BuiltinProc_type_is_typeid,
+	BuiltinProc_type_is_any,
+
+	BuiltinProc_type_is_endian_little,
+	BuiltinProc_type_is_endian_big,
+	BuiltinProc_type_is_numeric,
+	BuiltinProc_type_is_ordered,
+	BuiltinProc_type_is_ordered_numeric,
+	BuiltinProc_type_is_indexable,
+	BuiltinProc_type_is_sliceable,
+	BuiltinProc_type_is_simple_compare, // easily compared using memcmp
+	BuiltinProc_type_is_dereferenceable,
+
+	BuiltinProc_type_is_named,
+	BuiltinProc_type_is_pointer,
+	BuiltinProc_type_is_opaque,
+	BuiltinProc_type_is_array,
+	BuiltinProc_type_is_slice,
+	BuiltinProc_type_is_dynamic_array,
+	BuiltinProc_type_is_map,
+	BuiltinProc_type_is_struct,
+	BuiltinProc_type_is_union,
+	BuiltinProc_type_is_enum,
+	BuiltinProc_type_is_proc,
+	BuiltinProc_type_is_bit_field,
+	BuiltinProc_type_is_bit_field_value,
+	BuiltinProc_type_is_bit_set,
+	BuiltinProc_type_is_simd_vector,
+
+	BuiltinProc_type_has_nil,
+
+	BuiltinProc_type_elem_type,
+
+	BuiltinProc_type_proc_parameter_count,
+	BuiltinProc_type_proc_return_count,
+
+BuiltinProc__type_end,
+
+	BuiltinProc_COUNT,
+};
+gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
+	{STR_LIT(""),                 0, false, Expr_Stmt, BuiltinProcPkg_builtin},
+
+	{STR_LIT("len"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("cap"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT("size_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("align_of"),         1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("offset_of"),        2, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("type_of"),          1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("type_info_of"),     1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("typeid_of"),        1, false, Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT("swizzle"),          1, true,  Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT("complex"),          2, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("real"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("imag"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("conj"),             1, false, Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT("expand_to_tuple"),  1, false, Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT("min"),              1, true,  Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("max"),              1, true,  Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("abs"),              1, false, Expr_Expr, BuiltinProcPkg_builtin},
+	{STR_LIT("clamp"),            3, false, Expr_Expr, BuiltinProcPkg_builtin},
+
+	{STR_LIT(""),                 0, true,  Expr_Expr, BuiltinProcPkg_builtin}, // DIRECTIVE
+
+
+	// "Intrinsics"
+	{STR_LIT("vector"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type
+
+	{STR_LIT("atomic_fence"),        0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_acq"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_rel"),    0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_fence_acqrel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_store"),           2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_rel"),       2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_relaxed"),   2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_store_unordered"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_load"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_acq"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_relaxed"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_load_unordered"),  1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_add"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_add_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_sub_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_and_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_nand_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or"),              2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_acq"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_rel"),          2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_acqrel"),       2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_or_relaxed"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor"),             2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_acq"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_rel"),         2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_acqrel"),      2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xor_relaxed"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_xchg"),            2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_acq"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_rel"),        2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_acqrel"),     2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_xchg_relaxed"),    2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_cxchg"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchg_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("atomic_cxchgweak"),                    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acq"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_rel"),                3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acqrel"),             3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_relaxed"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_failrelaxed"),        3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_failacq"),            3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acq_failrelaxed"),    3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("atomic_cxchgweak_acqrel_failrelaxed"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+
+	{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_base_type"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_core_type"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("type_is_boolean"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_integer"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_rune"),              1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_float"),             1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_complex"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_string"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_typeid"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_any"),               1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("type_is_endian_little"),     1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_endian_big"),        1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_numeric"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_ordered"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_ordered_numeric"),   1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_indexable"),         1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_sliceable"),         1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_simple_compare"),    1, false, Expr_Expr, BuiltinProcPkg_intrinsics,},
+	{STR_LIT("type_is_dereferenceable"),   1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("type_is_named"),             1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_pointer"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_opaque"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_array"),             1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_slice"),             1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_dynamic_array"),     1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_map"),               1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_struct"),            1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_union"),             1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_enum"),              1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_proc"),              1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_bit_field"),         1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_bit_field_value"),   1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_bit_set"),           1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+	{STR_LIT("type_is_simd_vector"),       1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("type_has_nil"),              1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+
+	{STR_LIT("type_elem_type"),            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},
+	{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+};

+ 2 - 8
src/exact_value.cpp

@@ -53,14 +53,8 @@ HashKey hash_exact_value(ExactValue v) {
 		return hash_integer(u64(v.value_bool));
 	case ExactValue_String:
 		return hash_string(v.value_string);
-	case ExactValue_Integer: {
-		u64 *d = big_int_ptr(&v.value_integer);
-		u64 x = 0;
-		for (i32 i = 0; i < v.value_integer.len; i++) {
-			x |= d[i];
-		}
-		return hash_integer(x);
-	}
+	case ExactValue_Integer:
+		return hashing_proc(big_int_ptr(&v.value_integer), v.value_integer.len * gb_size_of(u64));
 	case ExactValue_Float:
 		return hash_f64(v.value_float);
 	case ExactValue_Pointer:

+ 13 - 0
src/types.cpp

@@ -1307,6 +1307,19 @@ bool is_type_indexable(Type *t) {
 	return false;
 }
 
+bool is_type_sliceable(Type *t) {
+	Type *bt = base_type(t);
+	switch (bt->kind) {
+	case Type_Basic:
+		return bt->Basic.kind == Basic_string;
+	case Type_Array:
+	case Type_Slice:
+	case Type_DynamicArray:
+		return true;
+	}
+	return false;
+}
+
 
 bool is_type_polymorphic_record(Type *t) {
 	t = base_type(t);