| ... | @@ -6381,8 +6381,7 @@ fn zirCall( | ... | @@ -6381,8 +6381,7 @@ fn zirCall( |
| 6381 | var input_is_error = false; | 6381 | var input_is_error = false; |
| 6382 | const block_index = @intCast(Air.Inst.Index, block.instructions.items.len); | 6382 | const block_index = @intCast(Air.Inst.Index, block.instructions.items.len); |
| 6383 | | 6383 | |
| 6384 | const func_ty_info = mod.typeToFunc(func_ty).?; | 6384 | const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len; |
| 6385 | const fn_params_len = func_ty_info.param_types.len; | | |
| 6386 | const parent_comptime = block.is_comptime; | 6385 | const parent_comptime = block.is_comptime; |
| 6387 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. | 6386 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. |
| 6388 | var extra_index: usize = 0; | 6387 | var extra_index: usize = 0; |
| ... | @@ -6391,6 +6390,7 @@ fn zirCall( | ... | @@ -6391,6 +6390,7 @@ fn zirCall( |
| 6391 | extra_index += 1; | 6390 | extra_index += 1; |
| 6392 | arg_index += 1; | 6391 | arg_index += 1; |
| 6393 | }) { | 6392 | }) { |
| | 6393 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| 6394 | const arg_end = sema.code.extra[extra.end + extra_index]; | 6394 | const arg_end = sema.code.extra[extra.end + extra_index]; |
| 6395 | defer arg_start = arg_end; | 6395 | defer arg_start = arg_end; |
| 6396 | | 6396 | |
| ... | @@ -6876,7 +6876,11 @@ fn analyzeCall( | ... | @@ -6876,7 +6876,11 @@ fn analyzeCall( |
| 6876 | .args_count = @intCast(u32, func_ty_info.param_types.len), | 6876 | .args_count = @intCast(u32, func_ty_info.param_types.len), |
| 6877 | }; | 6877 | }; |
| 6878 | var delete_memoized_call_key = false; | 6878 | var delete_memoized_call_key = false; |
| 6879 | defer if (delete_memoized_call_key) mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index); | 6879 | defer if (delete_memoized_call_key) { |
| | 6880 | assert(mod.memoized_call_args.items.len >= memoized_call_key.args_index and |
| | 6881 | mod.memoized_call_args.items.len < memoized_call_key.args_index + memoized_call_key.args_count); |
| | 6882 | mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index); |
| | 6883 | }; |
| 6880 | if (is_comptime_call) { | 6884 | if (is_comptime_call) { |
| 6881 | try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count); | 6885 | try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count); |
| 6882 | delete_memoized_call_key = true; | 6886 | delete_memoized_call_key = true; |
| ... | @@ -6990,14 +6994,22 @@ fn analyzeCall( | ... | @@ -6990,14 +6994,22 @@ fn analyzeCall( |
| 6990 | .{ .args = &mod.memoized_call_args }, | 6994 | .{ .args = &mod.memoized_call_args }, |
| 6991 | ); | 6995 | ); |
| 6992 | if (gop.found_existing) { | 6996 | if (gop.found_existing) { |
| | 6997 | assert(mod.memoized_call_args.items.len == memoized_call_key.args_index + memoized_call_key.args_count); |
| | 6998 | mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index); |
| | 6999 | delete_memoized_call_key = false; |
| | 7000 | |
| 6993 | // We need to use the original memoized error set instead of fn_ret_ty. | 7001 | // We need to use the original memoized error set instead of fn_ret_ty. |
| 6994 | const result = gop.value_ptr.*; | 7002 | const result = gop.value_ptr.*; |
| 6995 | assert(result != .none); // recursive memoization? | 7003 | assert(result != .none); // recursive memoization? |
| | 7004 | |
| 6996 | break :res2 try sema.addConstant(mod.intern_pool.typeOf(result).toType(), result.toValue()); | 7005 | break :res2 try sema.addConstant(mod.intern_pool.typeOf(result).toType(), result.toValue()); |
| 6997 | } | 7006 | } |
| 6998 | gop.value_ptr.* = .none; | 7007 | gop.value_ptr.* = .none; |
| 6999 | delete_memoized_call_key = false; | 7008 | } else if (delete_memoized_call_key) { |
| | 7009 | assert(mod.memoized_call_args.items.len == memoized_call_key.args_index + memoized_call_key.args_count); |
| | 7010 | mod.memoized_call_args.shrinkRetainingCapacity(memoized_call_key.args_index); |
| 7000 | } | 7011 | } |
| | 7012 | delete_memoized_call_key = false; |
| 7001 | | 7013 | |
| 7002 | const new_func_resolved_ty = try mod.funcType(new_fn_info); | 7014 | const new_func_resolved_ty = try mod.funcType(new_fn_info); |
| 7003 | if (!is_comptime_call and !block.is_typeof) { | 7015 | if (!is_comptime_call and !block.is_typeof) { |
| ... | @@ -14324,13 +14336,14 @@ fn zirOverflowArithmetic( | ... | @@ -14324,13 +14336,14 @@ fn zirOverflowArithmetic( |
| 14324 | const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); | 14336 | const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); |
| 14325 | | 14337 | |
| 14326 | const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty); | 14338 | const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty); |
| | 14339 | const overflow_ty = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type.types[1].toType(); |
| 14327 | | 14340 | |
| 14328 | var result: struct { | 14341 | var result: struct { |
| 14329 | inst: Air.Inst.Ref = .none, | 14342 | inst: Air.Inst.Ref = .none, |
| 14330 | wrapped: Value = Value.@"unreachable", | 14343 | wrapped: Value = Value.@"unreachable", |
| 14331 | overflow_bit: Value, | 14344 | overflow_bit: Value, |
| 14332 | } = result: { | 14345 | } = result: { |
| 14333 | const zero = try mod.intValue(dest_ty.scalarType(mod), 0); | 14346 | const zero_bit = try mod.intValue(Type.u1, 0); |
| 14334 | switch (zir_tag) { | 14347 | switch (zir_tag) { |
| 14335 | .add_with_overflow => { | 14348 | .add_with_overflow => { |
| 14336 | // If either of the arguments is zero, `false` is returned and the other is stored | 14349 | // If either of the arguments is zero, `false` is returned and the other is stored |
| ... | @@ -14338,12 +14351,12 @@ fn zirOverflowArithmetic( | ... | @@ -14338,12 +14351,12 @@ fn zirOverflowArithmetic( |
| 14338 | // Otherwise, if either of the argument is undefined, undefined is returned. | 14351 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 14339 | if (maybe_lhs_val) |lhs_val| { | 14352 | if (maybe_lhs_val) |lhs_val| { |
| 14340 | if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) { | 14353 | if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) { |
| 14341 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs }; | 14354 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; |
| 14342 | } | 14355 | } |
| 14343 | } | 14356 | } |
| 14344 | if (maybe_rhs_val) |rhs_val| { | 14357 | if (maybe_rhs_val) |rhs_val| { |
| 14345 | if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) { | 14358 | if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) { |
| 14346 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14359 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14347 | } | 14360 | } |
| 14348 | } | 14361 | } |
| 14349 | if (maybe_lhs_val) |lhs_val| { | 14362 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -14364,7 +14377,7 @@ fn zirOverflowArithmetic( | ... | @@ -14364,7 +14377,7 @@ fn zirOverflowArithmetic( |
| 14364 | if (rhs_val.isUndef(mod)) { | 14377 | if (rhs_val.isUndef(mod)) { |
| 14365 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; | 14378 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| 14366 | } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 14379 | } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 14367 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14380 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14368 | } else if (maybe_lhs_val) |lhs_val| { | 14381 | } else if (maybe_lhs_val) |lhs_val| { |
| 14369 | if (lhs_val.isUndef(mod)) { | 14382 | if (lhs_val.isUndef(mod)) { |
| 14370 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; | 14383 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| ... | @@ -14383,9 +14396,9 @@ fn zirOverflowArithmetic( | ... | @@ -14383,9 +14396,9 @@ fn zirOverflowArithmetic( |
| 14383 | if (maybe_lhs_val) |lhs_val| { | 14396 | if (maybe_lhs_val) |lhs_val| { |
| 14384 | if (!lhs_val.isUndef(mod)) { | 14397 | if (!lhs_val.isUndef(mod)) { |
| 14385 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 14398 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 14386 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14399 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14387 | } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { | 14400 | } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { |
| 14388 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs }; | 14401 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; |
| 14389 | } | 14402 | } |
| 14390 | } | 14403 | } |
| 14391 | } | 14404 | } |
| ... | @@ -14393,9 +14406,9 @@ fn zirOverflowArithmetic( | ... | @@ -14393,9 +14406,9 @@ fn zirOverflowArithmetic( |
| 14393 | if (maybe_rhs_val) |rhs_val| { | 14406 | if (maybe_rhs_val) |rhs_val| { |
| 14394 | if (!rhs_val.isUndef(mod)) { | 14407 | if (!rhs_val.isUndef(mod)) { |
| 14395 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 14408 | if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 14396 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs }; | 14409 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs }; |
| 14397 | } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { | 14410 | } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) { |
| 14398 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14411 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14399 | } | 14412 | } |
| 14400 | } | 14413 | } |
| 14401 | } | 14414 | } |
| ... | @@ -14417,12 +14430,12 @@ fn zirOverflowArithmetic( | ... | @@ -14417,12 +14430,12 @@ fn zirOverflowArithmetic( |
| 14417 | // Oterhwise if either of the arguments is undefined, both results are undefined. | 14430 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 14418 | if (maybe_lhs_val) |lhs_val| { | 14431 | if (maybe_lhs_val) |lhs_val| { |
| 14419 | if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) { | 14432 | if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) { |
| 14420 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14433 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14421 | } | 14434 | } |
| 14422 | } | 14435 | } |
| 14423 | if (maybe_rhs_val) |rhs_val| { | 14436 | if (maybe_rhs_val) |rhs_val| { |
| 14424 | if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) { | 14437 | if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) { |
| 14425 | break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs }; | 14438 | break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs }; |
| 14426 | } | 14439 | } |
| 14427 | } | 14440 | } |
| 14428 | if (maybe_lhs_val) |lhs_val| { | 14441 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -14922,13 +14935,18 @@ fn analyzeArithmetic( | ... | @@ -14922,13 +14935,18 @@ fn analyzeArithmetic( |
| 14922 | .ComptimeInt, .Int => try mod.intValue(scalar_type, 0), | 14935 | .ComptimeInt, .Int => try mod.intValue(scalar_type, 0), |
| 14923 | else => unreachable, | 14936 | else => unreachable, |
| 14924 | }; | 14937 | }; |
| | 14938 | const scalar_one = switch (scalar_tag) { |
| | 14939 | .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0), |
| | 14940 | .ComptimeInt, .Int => try mod.intValue(scalar_type, 1), |
| | 14941 | else => unreachable, |
| | 14942 | }; |
| 14925 | if (maybe_lhs_val) |lhs_val| { | 14943 | if (maybe_lhs_val) |lhs_val| { |
| 14926 | if (!lhs_val.isUndef(mod)) { | 14944 | if (!lhs_val.isUndef(mod)) { |
| 14927 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { | 14945 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 14928 | const zero_val = try sema.splat(resolved_type, scalar_zero); | 14946 | const zero_val = try sema.splat(resolved_type, scalar_zero); |
| 14929 | return sema.addConstant(resolved_type, zero_val); | 14947 | return sema.addConstant(resolved_type, zero_val); |
| 14930 | } | 14948 | } |
| 14931 | if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) { | 14949 | if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) { |
| 14932 | return casted_rhs; | 14950 | return casted_rhs; |
| 14933 | } | 14951 | } |
| 14934 | } | 14952 | } |
| ... | @@ -14941,7 +14959,7 @@ fn analyzeArithmetic( | ... | @@ -14941,7 +14959,7 @@ fn analyzeArithmetic( |
| 14941 | const zero_val = try sema.splat(resolved_type, scalar_zero); | 14959 | const zero_val = try sema.splat(resolved_type, scalar_zero); |
| 14942 | return sema.addConstant(resolved_type, zero_val); | 14960 | return sema.addConstant(resolved_type, zero_val); |
| 14943 | } | 14961 | } |
| 14944 | if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) { | 14962 | if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) { |
| 14945 | return casted_lhs; | 14963 | return casted_lhs; |
| 14946 | } | 14964 | } |
| 14947 | if (maybe_lhs_val) |lhs_val| { | 14965 | if (maybe_lhs_val) |lhs_val| { |
| ... | @@ -19219,10 +19237,9 @@ fn zirReify( | ... | @@ -19219,10 +19237,9 @@ fn zirReify( |
| 19219 | try names.ensureUnusedCapacity(sema.arena, len); | 19237 | try names.ensureUnusedCapacity(sema.arena, len); |
| 19220 | for (0..len) |i| { | 19238 | for (0..len) |i| { |
| 19221 | const elem_val = try payload_val.elemValue(mod, i); | 19239 | const elem_val = try payload_val.elemValue(mod, i); |
| 19222 | const struct_val = elem_val.castTag(.aggregate).?.data; | 19240 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19223 | // TODO use reflection instead of magic numbers here | 19241 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19224 | // error_set: type, | 19242 | |
| 19225 | const name_val = struct_val[0]; | | |
| 19226 | const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod); | 19243 | const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod); |
| 19227 | const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str); | 19244 | const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str); |
| 19228 | const gop = names.getOrPutAssumeCapacity(name_ip); | 19245 | const gop = names.getOrPutAssumeCapacity(name_ip); |
| ... | @@ -19303,12 +19320,9 @@ fn zirReify( | ... | @@ -19303,12 +19320,9 @@ fn zirReify( |
| 19303 | | 19320 | |
| 19304 | for (0..fields_len) |field_i| { | 19321 | for (0..fields_len) |field_i| { |
| 19305 | const elem_val = try fields_val.elemValue(mod, field_i); | 19322 | const elem_val = try fields_val.elemValue(mod, field_i); |
| 19306 | const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data; | 19323 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19307 | // TODO use reflection instead of magic numbers here | 19324 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19308 | // name: []const u8 | 19325 | const value_val = try elem_val.fieldValue(mod, elem_fields.getIndex("value").?); |
| 19309 | const name_val = field_struct_val[0]; | | |
| 19310 | // value: comptime_int | | |
| 19311 | const value_val = field_struct_val[1]; | | |
| 19312 | | 19326 | |
| 19313 | const field_name = try name_val.toAllocatedBytes( | 19327 | const field_name = try name_val.toAllocatedBytes( |
| 19314 | Type.slice_const_u8, | 19328 | Type.slice_const_u8, |
| ... | @@ -19485,14 +19499,10 @@ fn zirReify( | ... | @@ -19485,14 +19499,10 @@ fn zirReify( |
| 19485 | | 19499 | |
| 19486 | for (0..fields_len) |i| { | 19500 | for (0..fields_len) |i| { |
| 19487 | const elem_val = try fields_val.elemValue(mod, i); | 19501 | const elem_val = try fields_val.elemValue(mod, i); |
| 19488 | const field_struct_val = elem_val.castTag(.aggregate).?.data; | 19502 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19489 | // TODO use reflection instead of magic numbers here | 19503 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19490 | // name: []const u8 | 19504 | const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19491 | const name_val = field_struct_val[0]; | 19505 | const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex("alignment").?); |
| 19492 | // type: type, | | |
| 19493 | const type_val = field_struct_val[1]; | | |
| 19494 | // alignment: comptime_int, | | |
| 19495 | const alignment_val = field_struct_val[2]; | | |
| 19496 | | 19506 | |
| 19497 | const field_name = try name_val.toAllocatedBytes( | 19507 | const field_name = try name_val.toAllocatedBytes( |
| 19498 | Type.slice_const_u8, | 19508 | Type.slice_const_u8, |
| ... | @@ -19635,25 +19645,21 @@ fn zirReify( | ... | @@ -19635,25 +19645,21 @@ fn zirReify( |
| 19635 | | 19645 | |
| 19636 | var noalias_bits: u32 = 0; | 19646 | var noalias_bits: u32 = 0; |
| 19637 | for (param_types, 0..) |*param_type, i| { | 19647 | for (param_types, 0..) |*param_type, i| { |
| 19638 | const arg = try params_val.elemValue(mod, i); | 19648 | const elem_val = try params_val.elemValue(mod, i); |
| 19639 | const arg_val = arg.castTag(.aggregate).?.data; | 19649 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19640 | // TODO use reflection instead of magic numbers here | 19650 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_generic").?); |
| 19641 | // is_generic: bool, | 19651 | const param_is_noalias_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_noalias").?); |
| 19642 | const arg_is_generic = arg_val[0].toBool(); | 19652 | const opt_param_type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19643 | // is_noalias: bool, | | |
| 19644 | const arg_is_noalias = arg_val[1].toBool(); | | |
| 19645 | // type: ?type, | | |
| 19646 | const param_type_opt_val = arg_val[2]; | | |
| 19647 | | 19653 | |
| 19648 | if (arg_is_generic) { | 19654 | if (param_is_generic_val.toBool()) { |
| 19649 | return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); | 19655 | return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{}); |
| 19650 | } | 19656 | } |
| 19651 | | 19657 | |
| 19652 | const param_type_val = param_type_opt_val.optionalValue(mod) orelse | 19658 | const param_type_val = opt_param_type_val.optionalValue(mod) orelse |
| 19653 | return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); | 19659 | return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); |
| 19654 | param_type.* = param_type_val.toIntern(); | 19660 | param_type.* = param_type_val.toIntern(); |
| 19655 | | 19661 | |
| 19656 | if (arg_is_noalias) { | 19662 | if (param_is_noalias_val.toBool()) { |
| 19657 | if (!param_type.toType().isPtrAtRuntime(mod)) { | 19663 | if (!param_type.toType().isPtrAtRuntime(mod)) { |
| 19658 | return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); | 19664 | return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); |
| 19659 | } | 19665 | } |
| ... | @@ -19748,19 +19754,13 @@ fn reifyStruct( | ... | @@ -19748,19 +19754,13 @@ fn reifyStruct( |
| 19748 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | 19754 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 19749 | var i: usize = 0; | 19755 | var i: usize = 0; |
| 19750 | while (i < fields_len) : (i += 1) { | 19756 | while (i < fields_len) : (i += 1) { |
| 19751 | const elem_val = try fields_val.elemValue(sema.mod, i); | 19757 | const elem_val = try fields_val.elemValue(mod, i); |
| 19752 | const field_struct_val = elem_val.castTag(.aggregate).?.data; | 19758 | const elem_fields = mod.intern_pool.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19753 | // TODO use reflection instead of magic numbers here | 19759 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19754 | // name: []const u8 | 19760 | const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19755 | const name_val = field_struct_val[0]; | 19761 | const default_value_val = try elem_val.fieldValue(mod, elem_fields.getIndex("default_value").?); |
| 19756 | // type: type, | 19762 | const is_comptime_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_comptime").?); |
| 19757 | const type_val = field_struct_val[1]; | 19763 | const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex("alignment").?); |
| 19758 | // default_value: ?*const anyopaque, | | |
| 19759 | const default_value_val = field_struct_val[2]; | | |
| 19760 | // is_comptime: bool, | | |
| 19761 | const is_comptime_val = field_struct_val[3]; | | |
| 19762 | // alignment: comptime_int, | | |
| 19763 | const alignment_val = field_struct_val[4]; | | |
| 19764 | | 19764 | |
| 19765 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { | 19765 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { |
| 19766 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); | 19766 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| ... | @@ -19806,18 +19806,16 @@ fn reifyStruct( | ... | @@ -19806,18 +19806,16 @@ fn reifyStruct( |
| 19806 | return sema.fail(block, src, "duplicate struct field {s}", .{field_name}); | 19806 | return sema.fail(block, src, "duplicate struct field {s}", .{field_name}); |
| 19807 | } | 19807 | } |
| 19808 | | 19808 | |
| 19809 | const default_val = if (default_value_val.optionalValue(mod)) |opt_val| blk: { | 19809 | const field_ty = type_val.toType(); |
| 19810 | const payload_val = if (opt_val.pointerDecl(mod)) |opt_decl| | 19810 | const default_val = if (default_value_val.optionalValue(mod)) |opt_val| |
| 19811 | mod.declPtr(opt_decl).val | 19811 | try sema.pointerDeref(block, src, opt_val, try mod.singleConstPtrType(field_ty)) orelse |
| 19812 | else | 19812 | return sema.failWithNeededComptime(block, src, "struct field default value must be comptime-known") |
| 19813 | opt_val; | 19813 | else |
| 19814 | break :blk try payload_val.copy(new_decl_arena_allocator); | 19814 | Value.@"unreachable"; |
| 19815 | } else Value.@"unreachable"; | | |
| 19816 | if (is_comptime_val.toBool() and default_val.toIntern() == .unreachable_value) { | 19815 | if (is_comptime_val.toBool() and default_val.toIntern() == .unreachable_value) { |
| 19817 | return sema.fail(block, src, "comptime field without default initialization value", .{}); | 19816 | return sema.fail(block, src, "comptime field without default initialization value", .{}); |
| 19818 | } | 19817 | } |
| 19819 | | 19818 | |
| 19820 | const field_ty = type_val.toType(); | | |
| 19821 | gop.value_ptr.* = .{ | 19819 | gop.value_ptr.* = .{ |
| 19822 | .ty = field_ty, | 19820 | .ty = field_ty, |
| 19823 | .abi_align = abi_align, | 19821 | .abi_align = abi_align, |
| ... | @@ -20386,17 +20384,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air | ... | @@ -20386,17 +20384,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 20386 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) { | 20384 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) { |
| 20387 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}); | 20385 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}); |
| 20388 | } | 20386 | } |
| 20389 | return sema.addConstant(aligned_dest_ty, try mod.getCoerced(switch (mod.intern_pool.indexToKey(operand_val.toIntern())) { | 20387 | return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty)); |
| 20390 | .undef, .ptr => operand_val, | | |
| 20391 | .opt => |opt| switch (opt.val) { | | |
| 20392 | .none => if (dest_ty.ptrAllowsZero(mod)) | | |
| 20393 | Value.zero_usize | | |
| 20394 | else | | |
| 20395 | return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)}), | | |
| 20396 | else => opt.val.toValue(), | | |
| 20397 | }, | | |
| 20398 | else => unreachable, | | |
| 20399 | }, aligned_dest_ty)); | | |
| 20400 | } | 20388 | } |
| 20401 | | 20389 | |
| 20402 | try sema.requireRuntimeBlock(block, src, null); | 20390 | try sema.requireRuntimeBlock(block, src, null); |
| ... | @@ -20569,7 +20557,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -20569,7 +20557,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20569 | return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align }); | 20557 | return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align }); |
| 20570 | } | 20558 | } |
| 20571 | } | 20559 | } |
| 20572 | return sema.addConstant(dest_ty, val); | 20560 | return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty)); |
| 20573 | } | 20561 | } |
| 20574 | | 20562 | |
| 20575 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | 20563 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); |
| ... | @@ -20700,7 +20688,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -20700,7 +20688,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 20700 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); | 20688 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 20701 | for (elems, 0..) |*elem, i| { | 20689 | for (elems, 0..) |*elem, i| { |
| 20702 | const elem_val = try val.elemValue(mod, i); | 20690 | const elem_val = try val.elemValue(mod, i); |
| 20703 | elem.* = try (try elem_val.byteSwap(operand_ty, mod, sema.arena)).intern(scalar_ty, mod); | 20691 | elem.* = try (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod); |
| 20704 | } | 20692 | } |
| 20705 | return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{ | 20693 | return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{ |
| 20706 | .ty = operand_ty.toIntern(), | 20694 | .ty = operand_ty.toIntern(), |
| ... | @@ -25128,12 +25116,18 @@ fn tupleFieldValByIndex( | ... | @@ -25128,12 +25116,18 @@ fn tupleFieldValByIndex( |
| 25128 | } | 25116 | } |
| 25129 | | 25117 | |
| 25130 | if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| { | 25118 | if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| { |
| 25131 | if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty); | | |
| 25132 | if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { | 25119 | if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { |
| 25133 | return sema.addConstant(field_ty, opv); | 25120 | return sema.addConstant(field_ty, opv); |
| 25134 | } | 25121 | } |
| 25135 | const field_values = tuple_val.castTag(.aggregate).?.data; | 25122 | return switch (mod.intern_pool.indexToKey(tuple_val.toIntern())) { |
| 25136 | return sema.addConstant(field_ty, field_values[field_index]); | 25123 | .undef => sema.addConstUndef(field_ty), |
| | 25124 | .aggregate => |aggregate| sema.addConstant(field_ty, switch (aggregate.storage) { |
| | 25125 | .bytes => |bytes| try mod.intValue(Type.u8, bytes[0]), |
| | 25126 | .elems => |elems| elems[field_index].toValue(), |
| | 25127 | .repeated_elem => |elem| elem.toValue(), |
| | 25128 | }), |
| | 25129 | else => unreachable, |
| | 25130 | }; |
| 25137 | } | 25131 | } |
| 25138 | | 25132 | |
| 25139 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| { | 25133 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| ... | @@ -25883,7 +25877,7 @@ fn coerceExtra( | ... | @@ -25883,7 +25877,7 @@ fn coerceExtra( |
| 25883 | var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src); | 25877 | var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src); |
| 25884 | if (in_memory_result == .ok) { | 25878 | if (in_memory_result == .ok) { |
| 25885 | if (maybe_inst_val) |val| { | 25879 | if (maybe_inst_val) |val| { |
| 25886 | return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty)); | 25880 | return sema.coerceInMemory(block, val, inst_ty, dest_ty, dest_ty_src); |
| 25887 | } | 25881 | } |
| 25888 | try sema.requireRuntimeBlock(block, inst_src, null); | 25882 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 25889 | return block.addBitCast(dest_ty, inst); | 25883 | return block.addBitCast(dest_ty, inst); |
| ... | @@ -26072,7 +26066,7 @@ fn coerceExtra( | ... | @@ -26072,7 +26066,7 @@ fn coerceExtra( |
| 26072 | // coercion to C pointer | 26066 | // coercion to C pointer |
| 26073 | .C => switch (inst_ty.zigTypeTag(mod)) { | 26067 | .C => switch (inst_ty.zigTypeTag(mod)) { |
| 26074 | .Null => { | 26068 | .Null => { |
| 26075 | return sema.addConstant(dest_ty, Value.null); | 26069 | return sema.addConstant(dest_ty, try mod.getCoerced(Value.null, dest_ty)); |
| 26076 | }, | 26070 | }, |
| 26077 | .ComptimeInt => { | 26071 | .ComptimeInt => { |
| 26078 | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { | 26072 | const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) { |
| ... | @@ -26548,6 +26542,68 @@ fn coerceExtra( | ... | @@ -26548,6 +26542,68 @@ fn coerceExtra( |
| 26548 | return sema.failWithOwnedErrorMsg(msg); | 26542 | return sema.failWithOwnedErrorMsg(msg); |
| 26549 | } | 26543 | } |
| 26550 | | 26544 | |
| | 26545 | fn coerceInMemory( |
| | 26546 | sema: *Sema, |
| | 26547 | block: *Block, |
| | 26548 | val: Value, |
| | 26549 | src_ty: Type, |
| | 26550 | dst_ty: Type, |
| | 26551 | dst_ty_src: LazySrcLoc, |
| | 26552 | ) CompileError!Air.Inst.Ref { |
| | 26553 | const mod = sema.mod; |
| | 26554 | switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| | 26555 | .aggregate => |aggregate| { |
| | 26556 | const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern()); |
| | 26557 | const dest_len = try sema.usizeCast( |
| | 26558 | block, |
| | 26559 | dst_ty_src, |
| | 26560 | mod.intern_pool.aggregateTypeLen(dst_ty.toIntern()), |
| | 26561 | ); |
| | 26562 | direct: { |
| | 26563 | const src_ty_child = switch (mod.intern_pool.indexToKey(src_ty.toIntern())) { |
| | 26564 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| | 26565 | .anon_struct_type, .struct_type => break :direct, |
| | 26566 | else => unreachable, |
| | 26567 | }; |
| | 26568 | const dst_ty_child = switch (dst_ty_key) { |
| | 26569 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| | 26570 | .anon_struct_type, .struct_type => break :direct, |
| | 26571 | else => unreachable, |
| | 26572 | }; |
| | 26573 | if (src_ty_child != dst_ty_child) break :direct; |
| | 26574 | return try sema.addConstant(dst_ty, (try mod.intern(.{ .aggregate = .{ |
| | 26575 | .ty = dst_ty.toIntern(), |
| | 26576 | .storage = switch (aggregate.storage) { |
| | 26577 | .bytes => |bytes| .{ .bytes = bytes[0..dest_len] }, |
| | 26578 | .elems => |elems| .{ .elems = elems[0..dest_len] }, |
| | 26579 | .repeated_elem => |elem| .{ .repeated_elem = elem }, |
| | 26580 | }, |
| | 26581 | } })).toValue()); |
| | 26582 | } |
| | 26583 | const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len); |
| | 26584 | for (dest_elems, 0..) |*dest_elem, i| { |
| | 26585 | const elem_ty = switch (dst_ty_key) { |
| | 26586 | inline .array_type, .vector_type => |seq_type| seq_type.child, |
| | 26587 | .anon_struct_type => |anon_struct_type| anon_struct_type.types[i], |
| | 26588 | .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).? |
| | 26589 | .fields.values()[i].ty.toIntern(), |
| | 26590 | else => unreachable, |
| | 26591 | }; |
| | 26592 | dest_elem.* = try mod.intern_pool.getCoerced(mod.gpa, switch (aggregate.storage) { |
| | 26593 | .bytes => |bytes| (try mod.intValue(Type.u8, bytes[i])).toIntern(), |
| | 26594 | .elems => |elems| elems[i], |
| | 26595 | .repeated_elem => |elem| elem, |
| | 26596 | }, elem_ty); |
| | 26597 | } |
| | 26598 | return sema.addConstant(dst_ty, (try mod.intern(.{ .aggregate = .{ |
| | 26599 | .ty = dst_ty.toIntern(), |
| | 26600 | .storage = .{ .elems = dest_elems }, |
| | 26601 | } })).toValue()); |
| | 26602 | }, |
| | 26603 | else => return sema.addConstant(dst_ty, try mod.getCoerced(val, dst_ty)), |
| | 26604 | } |
| | 26605 | } |
| | 26606 | |
| 26551 | const InMemoryCoercionResult = union(enum) { | 26607 | const InMemoryCoercionResult = union(enum) { |
| 26552 | ok, | 26608 | ok, |
| 26553 | no_match: Pair, | 26609 | no_match: Pair, |
| ... | @@ -28619,7 +28675,11 @@ fn coerceArrayPtrToSlice( | ... | @@ -28619,7 +28675,11 @@ fn coerceArrayPtrToSlice( |
| 28619 | const array_ty = ptr_array_ty.childType(mod); | 28675 | const array_ty = ptr_array_ty.childType(mod); |
| 28620 | const slice_val = try mod.intern(.{ .ptr = .{ | 28676 | const slice_val = try mod.intern(.{ .ptr = .{ |
| 28621 | .ty = dest_ty.toIntern(), | 28677 | .ty = dest_ty.toIntern(), |
| 28622 | .addr = mod.intern_pool.indexToKey(val.toIntern()).ptr.addr, | 28678 | .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| | 28679 | .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) }, |
| | 28680 | .ptr => |ptr| ptr.addr, |
| | 28681 | else => unreachable, |
| | 28682 | }, |
| 28623 | .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(), | 28683 | .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(), |
| 28624 | } }); | 28684 | } }); |
| 28625 | return sema.addConstant(dest_ty, slice_val.toValue()); | 28685 | return sema.addConstant(dest_ty, slice_val.toValue()); |
| ... | @@ -28962,7 +29022,7 @@ fn coerceArrayLike( | ... | @@ -28962,7 +29022,7 @@ fn coerceArrayLike( |
| 28962 | if (in_memory_result == .ok) { | 29022 | if (in_memory_result == .ok) { |
| 28963 | if (try sema.resolveMaybeUndefVal(inst)) |inst_val| { | 29023 | if (try sema.resolveMaybeUndefVal(inst)) |inst_val| { |
| 28964 | // These types share the same comptime value representation. | 29024 | // These types share the same comptime value representation. |
| 28965 | return sema.addConstant(dest_ty, try mod.getCoerced(inst_val, dest_ty)); | 29025 | return sema.coerceInMemory(block, inst_val, inst_ty, dest_ty, dest_ty_src); |
| 28966 | } | 29026 | } |
| 28967 | try sema.requireRuntimeBlock(block, inst_src, null); | 29027 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 28968 | return block.addBitCast(dest_ty, inst); | 29028 | return block.addBitCast(dest_ty, inst); |
| ... | @@ -33599,9 +33659,8 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { | ... | @@ -33599,9 +33659,8 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { |
| 33599 | const mod = sema.mod; | 33659 | const mod = sema.mod; |
| 33600 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { | 33660 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 33601 | .ptr_type => |ptr_type| switch (ptr_type.size) { | 33661 | .ptr_type => |ptr_type| switch (ptr_type.size) { |
| | 33662 | .One, .Many, .C => ty, |
| 33602 | .Slice => null, | 33663 | .Slice => null, |
| 33603 | .C => ptr_type.elem_type.toType(), | | |
| 33604 | .One, .Many => ty, | | |
| 33605 | }, | 33664 | }, |
| 33606 | .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) { | 33665 | .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) { |
| 33607 | .ptr_type => |ptr_type| switch (ptr_type.size) { | 33666 | .ptr_type => |ptr_type| switch (ptr_type.size) { |