diff --git a/src/big_int.cpp b/src/big_int.cpp index 141152913..e2ebb5c76 100644 --- a/src/big_int.cpp +++ b/src/big_int.cpp @@ -57,6 +57,8 @@ gb_internal void big_int_dealloc(BigInt *dst) { mp_clear(dst); } +gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x); + gb_internal BigInt big_int_make(BigInt const *b, bool abs=false); gb_internal BigInt big_int_make_abs(BigInt const *b); gb_internal BigInt big_int_make_u64(u64 x); @@ -293,6 +295,11 @@ gb_internal void big_int_from_string(BigInt *dst, String const &s, bool *success +gb_internal bool big_int_can_be_represented_in_64_bits(BigInt const *x) { + int bits_used = (x->used-1) * MP_DIGIT_BIT; + return bits_used <= 64; +} + gb_internal u64 big_int_to_u64(BigInt const *x) { GB_ASSERT(x->sign == 0); return mp_get_u64(x); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c72e89bf2..d634aa9c0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2167,9 +2167,13 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i BigInt i = v.value_integer; i64 byte_size = type_size_of(type); - BigInt umax = {}; - BigInt imin = {}; - BigInt imax = {}; + BigInt umax; + BigInt imin; + BigInt imax; + + u64 umax_64 = 0; + i64 imin_64 = 0; + i64 imax_64 = 0; if (c->bit_field_bit_size > 0) { i64 bit_size = gb_min(cast(i64)(8*byte_size), cast(i64)c->bit_field_bit_size); @@ -2192,10 +2196,10 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i big_int_shl_eq(&imax, &bi); mp_decr(&imax); } else { - if (byte_size < 16) { - big_int_from_u64(&umax, unsigned_integer_maxs[byte_size]); - big_int_from_i64(&imin, signed_integer_mins[byte_size]); - big_int_from_i64(&imax, signed_integer_maxs[byte_size]); + if (byte_size <= 8) { + umax_64 = unsigned_integer_maxs[byte_size]; + imin_64 = signed_integer_mins[byte_size]; + imax_64 = signed_integer_maxs[byte_size]; } else { big_int_from_u64(&umax, 1); big_int_from_i64(&imin, 1); @@ -2223,16 +2227,27 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i case Basic_i16: case Basic_i32: case Basic_i64: - case Basic_i128: case Basic_int: case Basic_i16le: case Basic_i32le: case Basic_i64le: - case Basic_i128le: case Basic_i16be: case Basic_i32be: case Basic_i64be: + { + // return imin <= i && i <= imax; + if (!big_int_can_be_represented_in_64_bits(&i)) { + return false; + } + + i64 val64 = big_int_to_i64(&i); + + return imin_64 <= val64 && val64 <= imax_64; + } + + case Basic_i128le: + case Basic_i128: case Basic_i128be: { // return imin <= i && i <= imax; @@ -2245,17 +2260,30 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i case Basic_u16: case Basic_u32: case Basic_u64: - case Basic_u128: case Basic_uint: case Basic_uintptr: case Basic_u16le: case Basic_u32le: case Basic_u64le: - case Basic_u128le: case Basic_u16be: case Basic_u32be: case Basic_u64be: + { + if (big_int_is_neg(&i)) { + return false; + } + if (!big_int_can_be_represented_in_64_bits(&i)) { + return false; + } + u64 val64 = big_int_to_u64(&i); + + return val64 <= umax_64; + + } + + case Basic_u128: + case Basic_u128le: case Basic_u128be: { // return 0ull <= i && i <= umax; diff --git a/src/check_type.cpp b/src/check_type.cpp index 1ba2ee051..b625fb3d0 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2442,6 +2442,9 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res } } + Entity *entities_to_use = permanent_alloc_array(variable_count); + isize entities_to_use_index = 0; + auto variables = array_make(permanent_allocator(), 0, variable_count); i32 field_group_index = -1; for_array(i, results) { @@ -2480,7 +2483,12 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res if (field->names.count == 0) { Token token = ast_token(field->type); token.string = str_lit(""); - Entity *param = alloc_entity_param(scope, token, type, false, false); + // Entity *param = alloc_entity_param(scope, token, type, false, false); + Entity *param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type); + param->state = EntityState_Resolved; + param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result; + param->Variable.param_value = param_value; param->Variable.field_group_index = -1; array_add(&variables, param); @@ -2503,8 +2511,17 @@ gb_internal Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_res error(name, "Result value cannot be a blank identifer `_`"); } - Entity *param = alloc_entity_param(scope, token, type, false, false); - param->flags |= EntityFlag_Result; + // Entity *param = alloc_entity_param(scope, token, type, false, false); + Entity *param = &entities_to_use[entities_to_use_index++]; + INTERNAL_ENTITY_INIT(param, Entity_Variable, scope, token, type); + param->state = EntityState_Resolved; + param->flags |= EntityFlag_Used|EntityFlag_Param|EntityFlag_Result; + + if (name->kind == Ast_Ident) { + param->interned_name.store(name->Ident.interned); + param->interned_name_hash.store(name->Ident.hash); + } + param->Variable.param_value = param_value; param->Variable.field_group_index = field_group_index; array_add(&variables, param);