| ... | ... | @@ -6381,8 +6381,7 @@ fn zirCall( |
| 6381 | 6381 | var input_is_error = false; |
| 6382 | 6382 | const block_index = @intCast(Air.Inst.Index, block.instructions.items.len); |
| 6383 | 6383 | |
| 6384 | | const func_ty_info = mod.typeToFunc(func_ty).?; |
| 6385 | | const fn_params_len = func_ty_info.param_types.len; |
| 6384 | const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len; |
| 6386 | 6385 | const parent_comptime = block.is_comptime; |
| 6387 | 6386 | // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument. |
| 6388 | 6387 | var extra_index: usize = 0; |
| ... | ... | @@ -6391,6 +6390,7 @@ fn zirCall( |
| 6391 | 6390 | extra_index += 1; |
| 6392 | 6391 | arg_index += 1; |
| 6393 | 6392 | }) { |
| 6393 | const func_ty_info = mod.typeToFunc(func_ty).?; |
| 6394 | 6394 | const arg_end = sema.code.extra[extra.end + extra_index]; |
| 6395 | 6395 | defer arg_start = arg_end; |
| 6396 | 6396 | |
| ... | ... | @@ -6876,7 +6876,11 @@ fn analyzeCall( |
| 6876 | 6876 | .args_count = @intCast(u32, func_ty_info.param_types.len), |
| 6877 | 6877 | }; |
| 6878 | 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 | 6884 | if (is_comptime_call) { |
| 6881 | 6885 | try mod.memoized_call_args.ensureUnusedCapacity(gpa, memoized_call_key.args_count); |
| 6882 | 6886 | delete_memoized_call_key = true; |
| ... | ... | @@ -6990,14 +6994,22 @@ fn analyzeCall( |
| 6990 | 6994 | .{ .args = &mod.memoized_call_args }, |
| 6991 | 6995 | ); |
| 6992 | 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 | 7001 | // We need to use the original memoized error set instead of fn_ret_ty. |
| 6994 | 7002 | const result = gop.value_ptr.*; |
| 6995 | 7003 | assert(result != .none); // recursive memoization? |
| 7004 | |
| 6996 | 7005 | break :res2 try sema.addConstant(mod.intern_pool.typeOf(result).toType(), result.toValue()); |
| 6997 | 7006 | } |
| 6998 | 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 | 7014 | const new_func_resolved_ty = try mod.funcType(new_fn_info); |
| 7003 | 7015 | if (!is_comptime_call and !block.is_typeof) { |
| ... | ... | @@ -14324,13 +14336,14 @@ fn zirOverflowArithmetic( |
| 14324 | 14336 | const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); |
| 14325 | 14337 | |
| 14326 | 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 | 14341 | var result: struct { |
| 14329 | 14342 | inst: Air.Inst.Ref = .none, |
| 14330 | 14343 | wrapped: Value = Value.@"unreachable", |
| 14331 | 14344 | overflow_bit: Value, |
| 14332 | 14345 | } = result: { |
| 14333 | | const zero = try mod.intValue(dest_ty.scalarType(mod), 0); |
| 14346 | const zero_bit = try mod.intValue(Type.u1, 0); |
| 14334 | 14347 | switch (zir_tag) { |
| 14335 | 14348 | .add_with_overflow => { |
| 14336 | 14349 | // If either of the arguments is zero, `false` is returned and the other is stored |
| ... | ... | @@ -14338,12 +14351,12 @@ fn zirOverflowArithmetic( |
| 14338 | 14351 | // Otherwise, if either of the argument is undefined, undefined is returned. |
| 14339 | 14352 | if (maybe_lhs_val) |lhs_val| { |
| 14340 | 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 | 14357 | if (maybe_rhs_val) |rhs_val| { |
| 14345 | 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 | 14362 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -14364,7 +14377,7 @@ fn zirOverflowArithmetic( |
| 14364 | 14377 | if (rhs_val.isUndef(mod)) { |
| 14365 | 14378 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| 14366 | 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 | 14381 | } else if (maybe_lhs_val) |lhs_val| { |
| 14369 | 14382 | if (lhs_val.isUndef(mod)) { |
| 14370 | 14383 | break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef }; |
| ... | ... | @@ -14383,9 +14396,9 @@ fn zirOverflowArithmetic( |
| 14383 | 14396 | if (maybe_lhs_val) |lhs_val| { |
| 14384 | 14397 | if (!lhs_val.isUndef(mod)) { |
| 14385 | 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 | 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 | 14406 | if (maybe_rhs_val) |rhs_val| { |
| 14394 | 14407 | if (!rhs_val.isUndef(mod)) { |
| 14395 | 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 | 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 | 14430 | // Oterhwise if either of the arguments is undefined, both results are undefined. |
| 14418 | 14431 | if (maybe_lhs_val) |lhs_val| { |
| 14419 | 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 | 14436 | if (maybe_rhs_val) |rhs_val| { |
| 14424 | 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 | 14441 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -14922,13 +14935,18 @@ fn analyzeArithmetic( |
| 14922 | 14935 | .ComptimeInt, .Int => try mod.intValue(scalar_type, 0), |
| 14923 | 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 | 14943 | if (maybe_lhs_val) |lhs_val| { |
| 14926 | 14944 | if (!lhs_val.isUndef(mod)) { |
| 14927 | 14945 | if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) { |
| 14928 | 14946 | const zero_val = try sema.splat(resolved_type, scalar_zero); |
| 14929 | 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 | 14950 | return casted_rhs; |
| 14933 | 14951 | } |
| 14934 | 14952 | } |
| ... | ... | @@ -14941,7 +14959,7 @@ fn analyzeArithmetic( |
| 14941 | 14959 | const zero_val = try sema.splat(resolved_type, scalar_zero); |
| 14942 | 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 | 14963 | return casted_lhs; |
| 14946 | 14964 | } |
| 14947 | 14965 | if (maybe_lhs_val) |lhs_val| { |
| ... | ... | @@ -19219,10 +19237,9 @@ fn zirReify( |
| 19219 | 19237 | try names.ensureUnusedCapacity(sema.arena, len); |
| 19220 | 19238 | for (0..len) |i| { |
| 19221 | 19239 | const elem_val = try payload_val.elemValue(mod, i); |
| 19222 | | const struct_val = elem_val.castTag(.aggregate).?.data; |
| 19223 | | // TODO use reflection instead of magic numbers here |
| 19224 | | // error_set: type, |
| 19225 | | const name_val = struct_val[0]; |
| 19240 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19241 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19242 | |
| 19226 | 19243 | const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod); |
| 19227 | 19244 | const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str); |
| 19228 | 19245 | const gop = names.getOrPutAssumeCapacity(name_ip); |
| ... | ... | @@ -19303,12 +19320,9 @@ fn zirReify( |
| 19303 | 19320 | |
| 19304 | 19321 | for (0..fields_len) |field_i| { |
| 19305 | 19322 | const elem_val = try fields_val.elemValue(mod, field_i); |
| 19306 | | const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data; |
| 19307 | | // TODO use reflection instead of magic numbers here |
| 19308 | | // name: []const u8 |
| 19309 | | const name_val = field_struct_val[0]; |
| 19310 | | // value: comptime_int |
| 19311 | | const value_val = field_struct_val[1]; |
| 19323 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19324 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19325 | const value_val = try elem_val.fieldValue(mod, elem_fields.getIndex("value").?); |
| 19312 | 19326 | |
| 19313 | 19327 | const field_name = try name_val.toAllocatedBytes( |
| 19314 | 19328 | Type.slice_const_u8, |
| ... | ... | @@ -19485,14 +19499,10 @@ fn zirReify( |
| 19485 | 19499 | |
| 19486 | 19500 | for (0..fields_len) |i| { |
| 19487 | 19501 | const elem_val = try fields_val.elemValue(mod, i); |
| 19488 | | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 19489 | | // TODO use reflection instead of magic numbers here |
| 19490 | | // name: []const u8 |
| 19491 | | const name_val = field_struct_val[0]; |
| 19492 | | // type: type, |
| 19493 | | const type_val = field_struct_val[1]; |
| 19494 | | // alignment: comptime_int, |
| 19495 | | const alignment_val = field_struct_val[2]; |
| 19502 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19503 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19504 | const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19505 | const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex("alignment").?); |
| 19496 | 19506 | |
| 19497 | 19507 | const field_name = try name_val.toAllocatedBytes( |
| 19498 | 19508 | Type.slice_const_u8, |
| ... | ... | @@ -19635,25 +19645,21 @@ fn zirReify( |
| 19635 | 19645 | |
| 19636 | 19646 | var noalias_bits: u32 = 0; |
| 19637 | 19647 | for (param_types, 0..) |*param_type, i| { |
| 19638 | | const arg = try params_val.elemValue(mod, i); |
| 19639 | | const arg_val = arg.castTag(.aggregate).?.data; |
| 19640 | | // TODO use reflection instead of magic numbers here |
| 19641 | | // is_generic: bool, |
| 19642 | | const arg_is_generic = arg_val[0].toBool(); |
| 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]; |
| 19648 | const elem_val = try params_val.elemValue(mod, i); |
| 19649 | const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19650 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_generic").?); |
| 19651 | const param_is_noalias_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_noalias").?); |
| 19652 | const opt_param_type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19647 | 19653 | |
| 19648 | | if (arg_is_generic) { |
| 19654 | if (param_is_generic_val.toBool()) { |
| 19649 | 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 | 19659 | return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{}); |
| 19654 | 19660 | param_type.* = param_type_val.toIntern(); |
| 19655 | 19661 | |
| 19656 | | if (arg_is_noalias) { |
| 19662 | if (param_is_noalias_val.toBool()) { |
| 19657 | 19663 | if (!param_type.toType().isPtrAtRuntime(mod)) { |
| 19658 | 19664 | return sema.fail(block, src, "non-pointer parameter declared noalias", .{}); |
| 19659 | 19665 | } |
| ... | ... | @@ -19748,19 +19754,13 @@ fn reifyStruct( |
| 19748 | 19754 | try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 19749 | 19755 | var i: usize = 0; |
| 19750 | 19756 | while (i < fields_len) : (i += 1) { |
| 19751 | | const elem_val = try fields_val.elemValue(sema.mod, i); |
| 19752 | | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 19753 | | // TODO use reflection instead of magic numbers here |
| 19754 | | // name: []const u8 |
| 19755 | | const name_val = field_struct_val[0]; |
| 19756 | | // type: type, |
| 19757 | | const type_val = field_struct_val[1]; |
| 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]; |
| 19757 | const elem_val = try fields_val.elemValue(mod, i); |
| 19758 | const elem_fields = mod.intern_pool.typeOf(elem_val.toIntern()).toType().structFields(mod); |
| 19759 | const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?); |
| 19760 | const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex("type").?); |
| 19761 | const default_value_val = try elem_val.fieldValue(mod, elem_fields.getIndex("default_value").?); |
| 19762 | const is_comptime_val = try elem_val.fieldValue(mod, elem_fields.getIndex("is_comptime").?); |
| 19763 | const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex("alignment").?); |
| 19764 | 19764 | |
| 19765 | 19765 | if (!try sema.intFitsInType(alignment_val, Type.u32, null)) { |
| 19766 | 19766 | return sema.fail(block, src, "alignment must fit in 'u32'", .{}); |
| ... | ... | @@ -19806,18 +19806,16 @@ fn reifyStruct( |
| 19806 | 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: { |
| 19810 | | const payload_val = if (opt_val.pointerDecl(mod)) |opt_decl| |
| 19811 | | mod.declPtr(opt_decl).val |
| 19812 | | else |
| 19813 | | opt_val; |
| 19814 | | break :blk try payload_val.copy(new_decl_arena_allocator); |
| 19815 | | } else Value.@"unreachable"; |
| 19809 | const field_ty = type_val.toType(); |
| 19810 | const default_val = if (default_value_val.optionalValue(mod)) |opt_val| |
| 19811 | try sema.pointerDeref(block, src, opt_val, try mod.singleConstPtrType(field_ty)) orelse |
| 19812 | return sema.failWithNeededComptime(block, src, "struct field default value must be comptime-known") |
| 19813 | else |
| 19814 | Value.@"unreachable"; |
| 19816 | 19815 | if (is_comptime_val.toBool() and default_val.toIntern() == .unreachable_value) { |
| 19817 | 19816 | return sema.fail(block, src, "comptime field without default initialization value", .{}); |
| 19818 | 19817 | } |
| 19819 | 19818 | |
| 19820 | | const field_ty = type_val.toType(); |
| 19821 | 19819 | gop.value_ptr.* = .{ |
| 19822 | 19820 | .ty = field_ty, |
| 19823 | 19821 | .abi_align = abi_align, |
| ... | ... | @@ -20386,17 +20384,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 20386 | 20384 | if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) { |
| 20387 | 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())) { |
| 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)); |
| 20387 | return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty)); |
| 20400 | 20388 | } |
| 20401 | 20389 | |
| 20402 | 20390 | try sema.requireRuntimeBlock(block, src, null); |
| ... | ... | @@ -20569,7 +20557,7 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 20569 | 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 | 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 | 20688 | const elems = try sema.arena.alloc(InternPool.Index, vec_len); |
| 20701 | 20689 | for (elems, 0..) |*elem, i| { |
| 20702 | 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 | 20693 | return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{ |
| 20706 | 20694 | .ty = operand_ty.toIntern(), |
| ... | ... | @@ -25128,12 +25116,18 @@ fn tupleFieldValByIndex( |
| 25128 | 25116 | } |
| 25129 | 25117 | |
| 25130 | 25118 | if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| { |
| 25131 | | if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty); |
| 25132 | 25119 | if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| { |
| 25133 | 25120 | return sema.addConstant(field_ty, opv); |
| 25134 | 25121 | } |
| 25135 | | const field_values = tuple_val.castTag(.aggregate).?.data; |
| 25136 | | return sema.addConstant(field_ty, field_values[field_index]); |
| 25122 | return switch (mod.intern_pool.indexToKey(tuple_val.toIntern())) { |
| 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 | 25133 | if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| { |
| ... | ... | @@ -25883,7 +25877,7 @@ fn coerceExtra( |
| 25883 | 25877 | var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src); |
| 25884 | 25878 | if (in_memory_result == .ok) { |
| 25885 | 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 | 25882 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 25889 | 25883 | return block.addBitCast(dest_ty, inst); |
| ... | ... | @@ -26072,7 +26066,7 @@ fn coerceExtra( |
| 26072 | 26066 | // coercion to C pointer |
| 26073 | 26067 | .C => switch (inst_ty.zigTypeTag(mod)) { |
| 26074 | 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 | 26071 | .ComptimeInt => { |
| 26078 | 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 | 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 | 26607 | const InMemoryCoercionResult = union(enum) { |
| 26552 | 26608 | ok, |
| 26553 | 26609 | no_match: Pair, |
| ... | ... | @@ -28619,7 +28675,11 @@ fn coerceArrayPtrToSlice( |
| 28619 | 28675 | const array_ty = ptr_array_ty.childType(mod); |
| 28620 | 28676 | const slice_val = try mod.intern(.{ .ptr = .{ |
| 28621 | 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 | 28683 | .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(), |
| 28624 | 28684 | } }); |
| 28625 | 28685 | return sema.addConstant(dest_ty, slice_val.toValue()); |
| ... | ... | @@ -28962,7 +29022,7 @@ fn coerceArrayLike( |
| 28962 | 29022 | if (in_memory_result == .ok) { |
| 28963 | 29023 | if (try sema.resolveMaybeUndefVal(inst)) |inst_val| { |
| 28964 | 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 | 29027 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 28968 | 29028 | return block.addBitCast(dest_ty, inst); |
| ... | ... | @@ -33599,9 +33659,8 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type { |
| 33599 | 33659 | const mod = sema.mod; |
| 33600 | 33660 | return switch (mod.intern_pool.indexToKey(ty.toIntern())) { |
| 33601 | 33661 | .ptr_type => |ptr_type| switch (ptr_type.size) { |
| 33662 | .One, .Many, .C => ty, |
| 33602 | 33663 | .Slice => null, |
| 33603 | | .C => ptr_type.elem_type.toType(), |
| 33604 | | .One, .Many => ty, |
| 33605 | 33664 | }, |
| 33606 | 33665 | .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) { |
| 33607 | 33666 | .ptr_type => |ptr_type| switch (ptr_type.size) { |