| ... | ... | @@ -1917,6 +1917,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime( |
| 1917 | 1917 | const ty_pl = sema.air_instructions.items(.data)[i].ty_pl; |
| 1918 | 1918 | const val = sema.air_values.items[ty_pl.payload]; |
| 1919 | 1919 | if (val.tag() == .runtime_value) make_runtime.* = true; |
| 1920 | if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true; |
| 1920 | 1921 | return val; |
| 1921 | 1922 | }, |
| 1922 | 1923 | .const_ty => { |
| ... | ... | @@ -4380,7 +4381,7 @@ fn zirValidateArrayInit( |
| 4380 | 4381 | var block_index = block.instructions.items.len - 1; |
| 4381 | 4382 | while (block.instructions.items[block_index] != elem_ptr_air_inst) { |
| 4382 | 4383 | if (block_index == 0) { |
| 4383 | | array_is_comptime = true; |
| 4384 | array_is_comptime = false; |
| 4384 | 4385 | continue :outer; |
| 4385 | 4386 | } |
| 4386 | 4387 | block_index -= 1; |
| ... | ... | @@ -10343,6 +10344,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 10343 | 10344 | } |
| 10344 | 10345 | if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, special.body, operand); |
| 10345 | 10346 | if (special.is_inline) child_block.inline_case_capture = operand; |
| 10347 | if (empty_enum) { |
| 10348 | return Air.Inst.Ref.void_value; |
| 10349 | } |
| 10346 | 10350 | return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges); |
| 10347 | 10351 | } |
| 10348 | 10352 | |
| ... | ... | @@ -11992,10 +11996,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 11992 | 11996 | const element_vals = try sema.arena.alloc(Value, final_len_including_sent); |
| 11993 | 11997 | var elem_i: usize = 0; |
| 11994 | 11998 | while (elem_i < lhs_len) : (elem_i += 1) { |
| 11995 | | element_vals[elem_i] = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 11999 | const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, elem_i); |
| 12000 | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12001 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12002 | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12003 | element_vals[elem_i] = coereced_elem_val; |
| 11996 | 12004 | } |
| 11997 | 12005 | while (elem_i < result_len) : (elem_i += 1) { |
| 11998 | | element_vals[elem_i] = try rhs_sub_val.elemValue(sema.mod, sema.arena, elem_i - lhs_len); |
| 12006 | const elem_val = try rhs_sub_val.elemValue(sema.mod, sema.arena, elem_i - lhs_len); |
| 12007 | const elem_val_inst = try sema.addConstant(lhs_info.elem_type, elem_val); |
| 12008 | const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded); |
| 12009 | const coereced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, ""); |
| 12010 | element_vals[elem_i] = coereced_elem_val; |
| 11999 | 12011 | } |
| 12000 | 12012 | if (res_sent_val) |sent_val| { |
| 12001 | 12013 | element_vals[result_len] = sent_val; |
| ... | ... | @@ -12469,10 +12481,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins |
| 12469 | 12481 | |
| 12470 | 12482 | if (maybe_rhs_val) |rhs_val| { |
| 12471 | 12483 | if (is_int) { |
| 12472 | | return sema.addConstant( |
| 12473 | | resolved_type, |
| 12474 | | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target), |
| 12475 | | ); |
| 12484 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target); |
| 12485 | var vector_index: usize = undefined; |
| 12486 | if (!(try sema.intFitsInType(block, src, res, resolved_type, &vector_index))) { |
| 12487 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 12488 | } |
| 12489 | return sema.addConstant(resolved_type, res); |
| 12476 | 12490 | } else { |
| 12477 | 12491 | return sema.addConstant( |
| 12478 | 12492 | resolved_type, |
| ... | ... | @@ -12584,10 +12598,12 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12584 | 12598 | if (modulus_val.compareWithZero(.neq)) { |
| 12585 | 12599 | return sema.fail(block, src, "exact division produced remainder", .{}); |
| 12586 | 12600 | } |
| 12587 | | return sema.addConstant( |
| 12588 | | resolved_type, |
| 12589 | | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target), |
| 12590 | | ); |
| 12601 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target); |
| 12602 | var vector_index: usize = undefined; |
| 12603 | if (!(try sema.intFitsInType(block, src, res, resolved_type, &vector_index))) { |
| 12604 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 12605 | } |
| 12606 | return sema.addConstant(resolved_type, res); |
| 12591 | 12607 | } else { |
| 12592 | 12608 | const modulus_val = try lhs_val.floatMod(rhs_val, resolved_type, sema.arena, target); |
| 12593 | 12609 | if (modulus_val.compareWithZero(.neq)) { |
| ... | ... | @@ -12862,10 +12878,12 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12862 | 12878 | |
| 12863 | 12879 | if (maybe_rhs_val) |rhs_val| { |
| 12864 | 12880 | if (is_int) { |
| 12865 | | return sema.addConstant( |
| 12866 | | resolved_type, |
| 12867 | | try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target), |
| 12868 | | ); |
| 12881 | const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, target); |
| 12882 | var vector_index: usize = undefined; |
| 12883 | if (!(try sema.intFitsInType(block, src, res, resolved_type, &vector_index))) { |
| 12884 | return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index); |
| 12885 | } |
| 12886 | return sema.addConstant(resolved_type, res); |
| 12869 | 12887 | } else { |
| 12870 | 12888 | return sema.addConstant( |
| 12871 | 12889 | resolved_type, |
| ... | ... | @@ -22457,7 +22475,10 @@ fn fieldVal( |
| 22457 | 22475 | } else (try sema.mod.getErrorValue(field_name)).key; |
| 22458 | 22476 | |
| 22459 | 22477 | return sema.addConstant( |
| 22460 | | try child_type.copy(arena), |
| 22478 | if (!child_type.isAnyError()) |
| 22479 | try child_type.copy(arena) |
| 22480 | else |
| 22481 | try Type.Tag.error_set_single.create(arena, name), |
| 22461 | 22482 | try Value.Tag.@"error".create(arena, .{ .name = name }), |
| 22462 | 22483 | ); |
| 22463 | 22484 | }, |
| ... | ... | @@ -22668,7 +22689,10 @@ fn fieldPtr( |
| 22668 | 22689 | var anon_decl = try block.startAnonDecl(src); |
| 22669 | 22690 | defer anon_decl.deinit(); |
| 22670 | 22691 | return sema.analyzeDeclRef(try anon_decl.finish( |
| 22671 | | try child_type.copy(anon_decl.arena()), |
| 22692 | if (!child_type.isAnyError()) |
| 22693 | try child_type.copy(anon_decl.arena()) |
| 22694 | else |
| 22695 | try Type.Tag.error_set_single.create(anon_decl.arena(), name), |
| 22672 | 22696 | try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }), |
| 22673 | 22697 | 0, // default alignment |
| 22674 | 22698 | )); |
| ... | ... | @@ -22827,6 +22851,7 @@ fn fieldCallBind( |
| 22827 | 22851 | { |
| 22828 | 22852 | const first_param_type = decl_type.fnParamType(0); |
| 22829 | 22853 | const first_param_tag = first_param_type.tag(); |
| 22854 | var opt_buf: Type.Payload.ElemType = undefined; |
| 22830 | 22855 | // zig fmt: off |
| 22831 | 22856 | if (first_param_tag == .var_args_param or |
| 22832 | 22857 | first_param_tag == .generic_poison or ( |
| ... | ... | @@ -22845,7 +22870,27 @@ fn fieldCallBind( |
| 22845 | 22870 | }); |
| 22846 | 22871 | return sema.addConstant(ty, value); |
| 22847 | 22872 | } else if (first_param_type.eql(concrete_ty, sema.mod)) { |
| 22848 | | var deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 22873 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 22874 | const ty = Type.Tag.bound_fn.init(); |
| 22875 | const value = try Value.Tag.bound_fn.create(arena, .{ |
| 22876 | .func_inst = decl_val, |
| 22877 | .arg0_inst = deref, |
| 22878 | }); |
| 22879 | return sema.addConstant(ty, value); |
| 22880 | } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .Optional and |
| 22881 | first_param_type.optionalChild(&opt_buf).eql(concrete_ty, sema.mod)) |
| 22882 | { |
| 22883 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 22884 | const ty = Type.Tag.bound_fn.init(); |
| 22885 | const value = try Value.Tag.bound_fn.create(arena, .{ |
| 22886 | .func_inst = decl_val, |
| 22887 | .arg0_inst = deref, |
| 22888 | }); |
| 22889 | return sema.addConstant(ty, value); |
| 22890 | } else if (first_param_tag != .generic_poison and first_param_type.zigTypeTag() == .ErrorUnion and |
| 22891 | first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod)) |
| 22892 | { |
| 22893 | const deref = try sema.analyzeLoad(block, src, object_ptr, src); |
| 22849 | 22894 | const ty = Type.Tag.bound_fn.init(); |
| 22850 | 22895 | const value = try Value.Tag.bound_fn.create(arena, .{ |
| 22851 | 22896 | .func_inst = decl_val, |
| ... | ... | @@ -28763,6 +28808,13 @@ fn resolvePeerTypes( |
| 28763 | 28808 | } |
| 28764 | 28809 | } |
| 28765 | 28810 | }, |
| 28811 | .Fn => { |
| 28812 | if (!cand_info.mutable and cand_info.pointee_type.zigTypeTag() == .Fn and .ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty, cand_info.pointee_type, target, src, src)) { |
| 28813 | chosen = candidate; |
| 28814 | chosen_i = candidate_i + 1; |
| 28815 | continue; |
| 28816 | } |
| 28817 | }, |
| 28766 | 28818 | else => {}, |
| 28767 | 28819 | } |
| 28768 | 28820 | }, |
| ... | ... | @@ -28793,6 +28845,11 @@ fn resolvePeerTypes( |
| 28793 | 28845 | .Vector => continue, |
| 28794 | 28846 | else => {}, |
| 28795 | 28847 | }, |
| 28848 | .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag() == .Fn) { |
| 28849 | if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) { |
| 28850 | continue; |
| 28851 | } |
| 28852 | }, |
| 28796 | 28853 | else => {}, |
| 28797 | 28854 | } |
| 28798 | 28855 | |
| ... | ... | @@ -30440,23 +30497,23 @@ pub fn typeHasOnePossibleValue( |
| 30440 | 30497 | if (enum_obj.tag_ty.hasRuntimeBits()) { |
| 30441 | 30498 | return null; |
| 30442 | 30499 | } |
| 30443 | | if (enum_obj.fields.count() == 1) { |
| 30444 | | if (enum_obj.values.count() == 0) { |
| 30500 | switch (enum_obj.fields.count()) { |
| 30501 | 0 => return Value.initTag(.unreachable_value), |
| 30502 | 1 => if (enum_obj.values.count() == 0) { |
| 30445 | 30503 | return Value.zero; // auto-numbered |
| 30446 | 30504 | } else { |
| 30447 | 30505 | return enum_obj.values.keys()[0]; |
| 30448 | | } |
| 30449 | | } else { |
| 30450 | | return null; |
| 30506 | }, |
| 30507 | else => return null, |
| 30451 | 30508 | } |
| 30452 | 30509 | }, |
| 30453 | 30510 | .enum_simple => { |
| 30454 | 30511 | const resolved_ty = try sema.resolveTypeFields(block, src, ty); |
| 30455 | 30512 | const enum_simple = resolved_ty.castTag(.enum_simple).?.data; |
| 30456 | | if (enum_simple.fields.count() == 1) { |
| 30457 | | return Value.zero; |
| 30458 | | } else { |
| 30459 | | return null; |
| 30513 | switch (enum_simple.fields.count()) { |
| 30514 | 0 => return Value.initTag(.unreachable_value), |
| 30515 | 1 => return Value.zero, |
| 30516 | else => return null, |
| 30460 | 30517 | } |
| 30461 | 30518 | }, |
| 30462 | 30519 | .enum_nonexhaustive => { |
| ... | ... | @@ -30473,7 +30530,7 @@ pub fn typeHasOnePossibleValue( |
| 30473 | 30530 | const tag_val = (try sema.typeHasOnePossibleValue(block, src, union_obj.tag_ty)) orelse |
| 30474 | 30531 | return null; |
| 30475 | 30532 | const fields = union_obj.fields.values(); |
| 30476 | | if (fields.len == 0) return Value.initTag(.empty_struct_value); |
| 30533 | if (fields.len == 0) return Value.initTag(.unreachable_value); |
| 30477 | 30534 | const only_field = fields[0]; |
| 30478 | 30535 | if (only_field.ty.eql(resolved_ty, sema.mod)) { |
| 30479 | 30536 | const msg = try Module.ErrorMsg.create( |
| ... | ... | @@ -32036,15 +32093,36 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { |
| 32036 | 32093 | const ptr_info = ptr_ty.ptrInfo().data; |
| 32037 | 32094 | const elem_ty = ptr_ty.elemType2(); |
| 32038 | 32095 | const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0; |
| 32096 | const target = sema.mod.getTarget(); |
| 32097 | const parent_ty = ptr_ty.childType(); |
| 32098 | |
| 32099 | const vector_info: struct { |
| 32100 | host_size: u16, |
| 32101 | bit_offset: u16, |
| 32102 | alignment: u32, |
| 32103 | } = if (parent_ty.tag() == .vector) blk: { |
| 32104 | const elem_bits = elem_ty.bitSize(target); |
| 32105 | const is_packed = elem_bits != 0 and (elem_bits & (elem_bits - 1)) != 0; |
| 32106 | // TODO: runtime-known index |
| 32107 | assert(!is_packed or offset != null); |
| 32108 | const is_packed_with_offset = is_packed and offset != null and offset.? != 0; |
| 32109 | const target_offset = if (is_packed_with_offset) (if (target.cpu.arch.endian() == .Big) (parent_ty.vectorLen() - 1 - offset.?) else offset.?) else 0; |
| 32110 | break :blk .{ |
| 32111 | .host_size = if (is_packed_with_offset) @intCast(u16, parent_ty.abiSize(target)) else 0, |
| 32112 | .bit_offset = if (is_packed_with_offset) @intCast(u16, elem_bits * target_offset) else 0, |
| 32113 | .alignment = if (is_packed_with_offset) @intCast(u16, parent_ty.abiAlignment(target)) else 0, |
| 32114 | }; |
| 32115 | } else .{ .host_size = 0, .bit_offset = 0, .alignment = 0 }; |
| 32116 | |
| 32039 | 32117 | const alignment: u32 = a: { |
| 32040 | 32118 | // Calculate the new pointer alignment. |
| 32041 | 32119 | if (ptr_info.@"align" == 0) { |
| 32120 | if (vector_info.alignment != 0) break :a vector_info.alignment; |
| 32042 | 32121 | // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness. |
| 32043 | 32122 | break :a 0; |
| 32044 | 32123 | } |
| 32045 | 32124 | // If the addend is not a comptime-known value we can still count on |
| 32046 | 32125 | // it being a multiple of the type size. |
| 32047 | | const target = sema.mod.getTarget(); |
| 32048 | 32126 | const elem_size = elem_ty.abiSize(target); |
| 32049 | 32127 | const addend = if (offset) |off| elem_size * off else elem_size; |
| 32050 | 32128 | |
| ... | ... | @@ -32061,5 +32139,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { |
| 32061 | 32139 | .@"allowzero" = allow_zero, |
| 32062 | 32140 | .@"volatile" = ptr_info.@"volatile", |
| 32063 | 32141 | .@"align" = alignment, |
| 32142 | .host_size = vector_info.host_size, |
| 32143 | .bit_offset = vector_info.bit_offset, |
| 32064 | 32144 | }); |
| 32065 | 32145 | } |