| ... | @@ -1991,23 +1991,21 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime( | ... | @@ -1991,23 +1991,21 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime( |
| 1991 | const i = int - InternPool.static_len; | 1991 | const i = int - InternPool.static_len; |
| 1992 | const air_tags = sema.air_instructions.items(.tag); | 1992 | const air_tags = sema.air_instructions.items(.tag); |
| 1993 | if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { | 1993 | if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| { |
| 1994 | if (air_tags[i] == .constant) { | 1994 | if (air_tags[i] == .interned) { |
| 1995 | const ty_pl = sema.air_instructions.items(.data)[i].ty_pl; | 1995 | const interned = sema.air_instructions.items(.data)[i].interned; |
| 1996 | const val = sema.air_values.items[ty_pl.payload]; | 1996 | const val = interned.toValue(); |
| 1997 | if (val.getVariable(sema.mod) != null) return val; | 1997 | if (val.getVariable(sema.mod) != null) return val; |
| 1998 | } | 1998 | } |
| 1999 | return opv; | 1999 | return opv; |
| 2000 | } | 2000 | } |
| 2001 | const air_datas = sema.air_instructions.items(.data); | 2001 | const air_datas = sema.air_instructions.items(.data); |
| 2002 | switch (air_tags[i]) { | 2002 | switch (air_tags[i]) { |
| 2003 | .constant => { | 2003 | .interned => { |
| 2004 | const ty_pl = air_datas[i].ty_pl; | 2004 | const val = air_datas[i].interned.toValue(); |
| 2005 | const val = sema.air_values.items[ty_pl.payload]; | | |
| 2006 | if (val.isRuntimeValue(sema.mod)) make_runtime.* = true; | 2005 | if (val.isRuntimeValue(sema.mod)) make_runtime.* = true; |
| 2007 | if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true; | 2006 | if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true; |
| 2008 | return val; | 2007 | return val; |
| 2009 | }, | 2008 | }, |
| 2010 | .interned => return air_datas[i].interned.toValue(), | | |
| 2011 | else => return null, | 2009 | else => return null, |
| 2012 | } | 2010 | } |
| 2013 | } | 2011 | } |
| ... | @@ -2440,64 +2438,64 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -2440,64 +2438,64 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 2440 | const addr_space = target_util.defaultAddressSpace(target, .local); | 2438 | const addr_space = target_util.defaultAddressSpace(target, .local); |
| 2441 | | 2439 | |
| 2442 | if (Air.refToIndex(ptr)) |ptr_inst| { | 2440 | if (Air.refToIndex(ptr)) |ptr_inst| { |
| 2443 | if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) { | 2441 | switch (sema.air_instructions.items(.tag)[ptr_inst]) { |
| 2444 | const air_datas = sema.air_instructions.items(.data); | 2442 | .inferred_alloc => { |
| 2445 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; | 2443 | const air_datas = sema.air_instructions.items(.data); |
| 2446 | switch (ptr_val.tag()) { | 2444 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 2447 | .inferred_alloc => { | 2445 | const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data; |
| 2448 | const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data; | 2446 | // Add the stored instruction to the set we will use to resolve peer types |
| 2449 | // Add the stored instruction to the set we will use to resolve peer types | 2447 | // for the inferred allocation. |
| 2450 | // for the inferred allocation. | 2448 | // This instruction will not make it to codegen; it is only to participate |
| 2451 | // This instruction will not make it to codegen; it is only to participate | 2449 | // in the `stored_inst_list` of the `inferred_alloc`. |
| 2452 | // in the `stored_inst_list` of the `inferred_alloc`. | 2450 | var trash_block = block.makeSubBlock(); |
| 2453 | var trash_block = block.makeSubBlock(); | 2451 | defer trash_block.instructions.deinit(sema.gpa); |
| 2454 | defer trash_block.instructions.deinit(sema.gpa); | 2452 | const operand = try trash_block.addBitCast(pointee_ty, .void_value); |
| 2455 | const operand = try trash_block.addBitCast(pointee_ty, .void_value); | 2453 | |
| 2456 | | 2454 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 2457 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | 2455 | .pointee_type = pointee_ty, |
| 2458 | .pointee_type = pointee_ty, | 2456 | .@"align" = inferred_alloc.alignment, |
| 2459 | .@"align" = inferred_alloc.alignment, | 2457 | .@"addrspace" = addr_space, |
| 2460 | .@"addrspace" = addr_space, | 2458 | }); |
| 2461 | }); | 2459 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); |
| 2462 | const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr); | | |
| 2463 | | 2460 | |
| 2464 | try inferred_alloc.prongs.append(sema.arena, .{ | 2461 | try inferred_alloc.prongs.append(sema.arena, .{ |
| 2465 | .stored_inst = operand, | 2462 | .stored_inst = operand, |
| 2466 | .placeholder = Air.refToIndex(bitcasted_ptr).?, | 2463 | .placeholder = Air.refToIndex(bitcasted_ptr).?, |
| 2467 | }); | 2464 | }); |
| 2468 | | 2465 | |
| 2469 | return bitcasted_ptr; | 2466 | return bitcasted_ptr; |
| 2470 | }, | 2467 | }, |
| 2471 | .inferred_alloc_comptime => { | 2468 | .inferred_alloc_comptime => { |
| 2472 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; | 2469 | const air_datas = sema.air_instructions.items(.data); |
| 2473 | // There will be only one coerce_result_ptr because we are running at comptime. | 2470 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 2474 | // The alloc will turn into a Decl. | 2471 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 2475 | var anon_decl = try block.startAnonDecl(); | 2472 | // There will be only one coerce_result_ptr because we are running at comptime. |
| 2476 | defer anon_decl.deinit(); | 2473 | // The alloc will turn into a Decl. |
| 2477 | iac.data.decl_index = try anon_decl.finish( | 2474 | var anon_decl = try block.startAnonDecl(); |
| 2478 | pointee_ty, | 2475 | defer anon_decl.deinit(); |
| 2479 | Value.undef, | 2476 | iac.data.decl_index = try anon_decl.finish( |
| 2480 | iac.data.alignment, | 2477 | pointee_ty, |
| 2481 | ); | 2478 | Value.undef, |
| 2482 | if (iac.data.alignment != 0) { | 2479 | iac.data.alignment, |
| 2483 | try sema.resolveTypeLayout(pointee_ty); | 2480 | ); |
| 2484 | } | 2481 | if (iac.data.alignment != 0) { |
| 2485 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ | 2482 | try sema.resolveTypeLayout(pointee_ty); |
| 2486 | .pointee_type = pointee_ty, | 2483 | } |
| 2487 | .@"align" = iac.data.alignment, | 2484 | const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ |
| 2488 | .@"addrspace" = addr_space, | 2485 | .pointee_type = pointee_ty, |
| 2489 | }); | 2486 | .@"align" = iac.data.alignment, |
| 2490 | try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index); | 2487 | .@"addrspace" = addr_space, |
| 2491 | return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{ | 2488 | }); |
| 2492 | .ty = ptr_ty.toIntern(), | 2489 | try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index); |
| 2493 | .addr = .{ .mut_decl = .{ | 2490 | return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{ |
| 2494 | .decl = iac.data.decl_index, | 2491 | .ty = ptr_ty.toIntern(), |
| 2495 | .runtime_index = block.runtime_index, | 2492 | .addr = .{ .mut_decl = .{ |
| 2496 | } }, | 2493 | .decl = iac.data.decl_index, |
| 2497 | } })).toValue()); | 2494 | .runtime_index = block.runtime_index, |
| 2498 | }, | 2495 | } }, |
| 2499 | else => {}, | 2496 | } })).toValue()); |
| 2500 | } | 2497 | }, |
| | 2498 | else => {}, |
| 2501 | } | 2499 | } |
| 2502 | } | 2500 | } |
| 2503 | | 2501 | |
| ... | @@ -3458,6 +3456,7 @@ fn zirAllocExtended( | ... | @@ -3458,6 +3456,7 @@ fn zirAllocExtended( |
| 3458 | block: *Block, | 3456 | block: *Block, |
| 3459 | extended: Zir.Inst.Extended.InstData, | 3457 | extended: Zir.Inst.Extended.InstData, |
| 3460 | ) CompileError!Air.Inst.Ref { | 3458 | ) CompileError!Air.Inst.Ref { |
| | 3459 | const gpa = sema.gpa; |
| 3461 | const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); | 3460 | const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); |
| 3462 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node }; | 3461 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node }; |
| 3463 | const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node }; | 3462 | const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node }; |
| ... | @@ -3487,13 +3486,19 @@ fn zirAllocExtended( | ... | @@ -3487,13 +3486,19 @@ fn zirAllocExtended( |
| 3487 | if (small.has_type) { | 3486 | if (small.has_type) { |
| 3488 | return sema.analyzeComptimeAlloc(block, var_ty, alignment); | 3487 | return sema.analyzeComptimeAlloc(block, var_ty, alignment); |
| 3489 | } else { | 3488 | } else { |
| 3490 | return sema.addConstant( | 3489 | const ty_inst = try sema.addType(inferred_alloc_ty); |
| 3491 | inferred_alloc_ty, | 3490 | try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 3492 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ | 3491 | .decl_index = undefined, |
| 3493 | .decl_index = undefined, | 3492 | .alignment = alignment, |
| 3494 | .alignment = alignment, | 3493 | })); |
| 3495 | }), | 3494 | try sema.air_instructions.append(gpa, .{ |
| 3496 | ); | 3495 | .tag = .inferred_alloc_comptime, |
| | 3496 | .data = .{ .ty_pl = .{ |
| | 3497 | .ty = ty_inst, |
| | 3498 | .payload = @intCast(u32, sema.air_values.items.len - 1), |
| | 3499 | } }, |
| | 3500 | }); |
| | 3501 | return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); |
| 3497 | } | 3502 | } |
| 3498 | } | 3503 | } |
| 3499 | | 3504 | |
| ... | @@ -3511,17 +3516,19 @@ fn zirAllocExtended( | ... | @@ -3511,17 +3516,19 @@ fn zirAllocExtended( |
| 3511 | return block.addTy(.alloc, ptr_type); | 3516 | return block.addTy(.alloc, ptr_type); |
| 3512 | } | 3517 | } |
| 3513 | | 3518 | |
| 3514 | // `Sema.addConstant` does not add the instruction to the block because it is | 3519 | const ty_inst = try sema.addType(inferred_alloc_ty); |
| 3515 | // not needed in the case of constant values. However here, we plan to "downgrade" | 3520 | try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{ |
| 3516 | // to a normal instruction when we hit `resolve_inferred_alloc`. So we append | 3521 | .alignment = alignment, |
| 3517 | // to the block even though it is currently a `.constant`. | 3522 | })); |
| 3518 | const result = try sema.addConstant( | 3523 | const result_index = try block.addInstAsIndex(.{ |
| 3519 | inferred_alloc_ty, | 3524 | .tag = .inferred_alloc, |
| 3520 | try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }), | 3525 | .data = .{ .ty_pl = .{ |
| 3521 | ); | 3526 | .ty = ty_inst, |
| 3522 | try block.instructions.append(sema.gpa, Air.refToIndex(result).?); | 3527 | .payload = @intCast(u32, sema.air_values.items.len - 1), |
| 3523 | try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {}); | 3528 | } }, |
| 3524 | return result; | 3529 | }); |
| | 3530 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {}); |
| | 3531 | return Air.indexToRef(result_index); |
| 3525 | } | 3532 | } |
| 3526 | | 3533 | |
| 3527 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 3534 | fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -3616,16 +3623,24 @@ fn zirAllocInferredComptime( | ... | @@ -3616,16 +3623,24 @@ fn zirAllocInferredComptime( |
| 3616 | inst: Zir.Inst.Index, | 3623 | inst: Zir.Inst.Index, |
| 3617 | inferred_alloc_ty: Type, | 3624 | inferred_alloc_ty: Type, |
| 3618 | ) CompileError!Air.Inst.Ref { | 3625 | ) CompileError!Air.Inst.Ref { |
| | 3626 | const gpa = sema.gpa; |
| 3619 | const src_node = sema.code.instructions.items(.data)[inst].node; | 3627 | const src_node = sema.code.instructions.items(.data)[inst].node; |
| 3620 | const src = LazySrcLoc.nodeOffset(src_node); | 3628 | const src = LazySrcLoc.nodeOffset(src_node); |
| 3621 | sema.src = src; | 3629 | sema.src = src; |
| 3622 | return sema.addConstant( | 3630 | |
| 3623 | inferred_alloc_ty, | 3631 | const ty_inst = try sema.addType(inferred_alloc_ty); |
| 3624 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ | 3632 | try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 3625 | .decl_index = undefined, | 3633 | .decl_index = undefined, |
| 3626 | .alignment = 0, | 3634 | .alignment = 0, |
| 3627 | }), | 3635 | })); |
| 3628 | ); | 3636 | try sema.air_instructions.append(gpa, .{ |
| | 3637 | .tag = .inferred_alloc_comptime, |
| | 3638 | .data = .{ .ty_pl = .{ |
| | 3639 | .ty = ty_inst, |
| | 3640 | .payload = @intCast(u32, sema.air_values.items.len - 1), |
| | 3641 | } }, |
| | 3642 | }); |
| | 3643 | return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); |
| 3629 | } | 3644 | } |
| 3630 | | 3645 | |
| 3631 | fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 3646 | fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| ... | @@ -3676,31 +3691,39 @@ fn zirAllocInferred( | ... | @@ -3676,31 +3691,39 @@ fn zirAllocInferred( |
| 3676 | const tracy = trace(@src()); | 3691 | const tracy = trace(@src()); |
| 3677 | defer tracy.end(); | 3692 | defer tracy.end(); |
| 3678 | | 3693 | |
| | 3694 | const gpa = sema.gpa; |
| 3679 | const src_node = sema.code.instructions.items(.data)[inst].node; | 3695 | const src_node = sema.code.instructions.items(.data)[inst].node; |
| 3680 | const src = LazySrcLoc.nodeOffset(src_node); | 3696 | const src = LazySrcLoc.nodeOffset(src_node); |
| 3681 | sema.src = src; | 3697 | sema.src = src; |
| 3682 | | 3698 | |
| | 3699 | const ty_inst = try sema.addType(inferred_alloc_ty); |
| 3683 | if (block.is_comptime) { | 3700 | if (block.is_comptime) { |
| 3684 | return sema.addConstant( | 3701 | try sema.air_values.append(gpa, try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ |
| 3685 | inferred_alloc_ty, | 3702 | .decl_index = undefined, |
| 3686 | try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{ | 3703 | .alignment = 0, |
| 3687 | .decl_index = undefined, | 3704 | })); |
| 3688 | .alignment = 0, | 3705 | try sema.air_instructions.append(gpa, .{ |
| 3689 | }), | 3706 | .tag = .inferred_alloc_comptime, |
| 3690 | ); | 3707 | .data = .{ .ty_pl = .{ |
| | 3708 | .ty = ty_inst, |
| | 3709 | .payload = @intCast(u32, sema.air_values.items.len - 1), |
| | 3710 | } }, |
| | 3711 | }); |
| | 3712 | return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); |
| 3691 | } | 3713 | } |
| 3692 | | 3714 | |
| 3693 | // `Sema.addConstant` does not add the instruction to the block because it is | 3715 | try sema.air_values.append(gpa, try Value.Tag.inferred_alloc.create(sema.arena, .{ |
| 3694 | // not needed in the case of constant values. However here, we plan to "downgrade" | 3716 | .alignment = 0, |
| 3695 | // to a normal instruction when we hit `resolve_inferred_alloc`. So we append | 3717 | })); |
| 3696 | // to the block even though it is currently a `.constant`. | 3718 | const result_index = try block.addInstAsIndex(.{ |
| 3697 | const result = try sema.addConstant( | 3719 | .tag = .inferred_alloc, |
| 3698 | inferred_alloc_ty, | 3720 | .data = .{ .ty_pl = .{ |
| 3699 | try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }), | 3721 | .ty = ty_inst, |
| 3700 | ); | 3722 | .payload = @intCast(u32, sema.air_values.items.len - 1), |
| 3701 | try block.instructions.append(sema.gpa, Air.refToIndex(result).?); | 3723 | } }, |
| 3702 | try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {}); | 3724 | }); |
| 3703 | return result; | 3725 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, {}); |
| | 3726 | return Air.indexToRef(result_index); |
| 3704 | } | 3727 | } |
| 3705 | | 3728 | |
| 3706 | fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 3729 | fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -3712,7 +3735,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -3712,7 +3735,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3712 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; | 3735 | const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node }; |
| 3713 | const ptr = try sema.resolveInst(inst_data.operand); | 3736 | const ptr = try sema.resolveInst(inst_data.operand); |
| 3714 | const ptr_inst = Air.refToIndex(ptr).?; | 3737 | const ptr_inst = Air.refToIndex(ptr).?; |
| 3715 | assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant); | | |
| 3716 | const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload; | 3738 | const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload; |
| 3717 | const ptr_val = sema.air_values.items[value_index]; | 3739 | const ptr_val = sema.air_values.items[value_index]; |
| 3718 | const var_is_mut = switch (sema.typeOf(ptr).toIntern()) { | 3740 | const var_is_mut = switch (sema.typeOf(ptr).toIntern()) { |
| ... | @@ -3722,7 +3744,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -3722,7 +3744,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3722 | }; | 3744 | }; |
| 3723 | const target = sema.mod.getTarget(); | 3745 | const target = sema.mod.getTarget(); |
| 3724 | | 3746 | |
| 3725 | switch (ptr_val.tag()) { | 3747 | switch (sema.air_instructions.items(.tag)[ptr_inst]) { |
| 3726 | .inferred_alloc_comptime => { | 3748 | .inferred_alloc_comptime => { |
| 3727 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; | 3749 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 3728 | const decl_index = iac.data.decl_index; | 3750 | const decl_index = iac.data.decl_index; |
| ... | @@ -3767,7 +3789,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -3767,7 +3789,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3767 | // Detect if the value is comptime-known. In such case, the | 3789 | // Detect if the value is comptime-known. In such case, the |
| 3768 | // last 3 AIR instructions of the block will look like this: | 3790 | // last 3 AIR instructions of the block will look like this: |
| 3769 | // | 3791 | // |
| 3770 | // %a = constant | 3792 | // %a = interned |
| 3771 | // %b = bitcast(%a) | 3793 | // %b = bitcast(%a) |
| 3772 | // %c = store(%b, %d) | 3794 | // %c = store(%b, %d) |
| 3773 | // | 3795 | // |
| ... | @@ -3814,7 +3836,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -3814,7 +3836,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 3814 | const candidate = block.instructions.items[search_index]; | 3836 | const candidate = block.instructions.items[search_index]; |
| 3815 | switch (air_tags[candidate]) { | 3837 | switch (air_tags[candidate]) { |
| 3816 | .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue, | 3838 | .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue, |
| 3817 | .constant => break candidate, | 3839 | .interned => break candidate, |
| 3818 | else => break :ct, | 3840 | else => break :ct, |
| 3819 | } | 3841 | } |
| 3820 | }; | 3842 | }; |
| ... | @@ -4981,15 +5003,15 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -4981,15 +5003,15 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 4981 | const src: LazySrcLoc = sema.src; | 5003 | const src: LazySrcLoc = sema.src; |
| 4982 | blk: { | 5004 | blk: { |
| 4983 | const ptr_inst = Air.refToIndex(ptr) orelse break :blk; | 5005 | const ptr_inst = Air.refToIndex(ptr) orelse break :blk; |
| 4984 | if (sema.air_instructions.items(.tag)[ptr_inst] != .constant) break :blk; | 5006 | const air_data = sema.air_instructions.items(.data)[ptr_inst]; |
| 4985 | const air_datas = sema.air_instructions.items(.data); | 5007 | switch (sema.air_instructions.items(.tag)[ptr_inst]) { |
| 4986 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; | | |
| 4987 | switch (ptr_val.tag()) { | | |
| 4988 | .inferred_alloc_comptime => { | 5008 | .inferred_alloc_comptime => { |
| | 5009 | const ptr_val = sema.air_values.items[air_data.ty_pl.payload]; |
| 4989 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; | 5010 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 4990 | return sema.storeToInferredAllocComptime(block, src, operand, iac); | 5011 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| 4991 | }, | 5012 | }, |
| 4992 | .inferred_alloc => { | 5013 | .inferred_alloc => { |
| | 5014 | const ptr_val = sema.air_values.items[air_data.ty_pl.payload]; |
| 4993 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; | 5015 | const inferred_alloc = ptr_val.castTag(.inferred_alloc).?; |
| 4994 | return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc); | 5016 | return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc); |
| 4995 | }, | 5017 | }, |
| ... | @@ -5009,11 +5031,10 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -5009,11 +5031,10 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 5009 | const ptr = try sema.resolveInst(bin_inst.lhs); | 5031 | const ptr = try sema.resolveInst(bin_inst.lhs); |
| 5010 | const operand = try sema.resolveInst(bin_inst.rhs); | 5032 | const operand = try sema.resolveInst(bin_inst.rhs); |
| 5011 | const ptr_inst = Air.refToIndex(ptr).?; | 5033 | const ptr_inst = Air.refToIndex(ptr).?; |
| 5012 | assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant); | | |
| 5013 | const air_datas = sema.air_instructions.items(.data); | 5034 | const air_datas = sema.air_instructions.items(.data); |
| 5014 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; | 5035 | const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload]; |
| 5015 | | 5036 | |
| 5016 | switch (ptr_val.tag()) { | 5037 | switch (sema.air_instructions.items(.tag)[ptr_inst]) { |
| 5017 | .inferred_alloc_comptime => { | 5038 | .inferred_alloc_comptime => { |
| 5018 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; | 5039 | const iac = ptr_val.castTag(.inferred_alloc_comptime).?; |
| 5019 | return sema.storeToInferredAllocComptime(block, src, operand, iac); | 5040 | return sema.storeToInferredAllocComptime(block, src, operand, iac); |
| ... | @@ -6988,16 +7009,7 @@ fn analyzeCall( | ... | @@ -6988,16 +7009,7 @@ fn analyzeCall( |
| 6988 | const res2: Air.Inst.Ref = res2: { | 7009 | const res2: Air.Inst.Ref = res2: { |
| 6989 | if (should_memoize and is_comptime_call) { | 7010 | if (should_memoize and is_comptime_call) { |
| 6990 | if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| { | 7011 | if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| { |
| 6991 | const ty_inst = try sema.addType(fn_ret_ty); | 7012 | break :res2 try sema.addConstant(fn_ret_ty, result.val); |
| 6992 | try sema.air_values.append(gpa, result.val); | | |
| 6993 | sema.air_instructions.set(block_inst, .{ | | |
| 6994 | .tag = .constant, | | |
| 6995 | .data = .{ .ty_pl = .{ | | |
| 6996 | .ty = ty_inst, | | |
| 6997 | .payload = @intCast(u32, sema.air_values.items.len - 1), | | |
| 6998 | } }, | | |
| 6999 | }); | | |
| 7000 | break :res2 Air.indexToRef(block_inst); | | |
| 7001 | } | 7013 | } |
| 7002 | } | 7014 | } |
| 7003 | | 7015 | |
| ... | @@ -9407,7 +9419,7 @@ fn zirParam( | ... | @@ -9407,7 +9419,7 @@ fn zirParam( |
| 9407 | if (is_comptime) { | 9419 | if (is_comptime) { |
| 9408 | // If this is a comptime parameter we can add a constant generic_poison | 9420 | // If this is a comptime parameter we can add a constant generic_poison |
| 9409 | // since this is also a generic parameter. | 9421 | // since this is also a generic parameter. |
| 9410 | const result = try sema.addConstant(param_ty, Value.generic_poison); | 9422 | const result = try sema.addConstant(Type.generic_poison, Value.generic_poison); |
| 9411 | sema.inst_map.putAssumeCapacityNoClobber(inst, result); | 9423 | sema.inst_map.putAssumeCapacityNoClobber(inst, result); |
| 9412 | } else { | 9424 | } else { |
| 9413 | // Otherwise we need a dummy runtime instruction. | 9425 | // Otherwise we need a dummy runtime instruction. |
| ... | @@ -15104,7 +15116,7 @@ fn analyzePtrArithmetic( | ... | @@ -15104,7 +15116,7 @@ fn analyzePtrArithmetic( |
| 15104 | if (air_tag == .ptr_sub) { | 15116 | if (air_tag == .ptr_sub) { |
| 15105 | return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{}); | 15117 | return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{}); |
| 15106 | } | 15118 | } |
| 15107 | const new_ptr_val = try ptr_val.elemPtr(ptr_ty, offset_int, sema.mod); | 15119 | const new_ptr_val = try ptr_val.elemPtr(new_ptr_ty, offset_int, sema.mod); |
| 15108 | return sema.addConstant(new_ptr_ty, new_ptr_val); | 15120 | return sema.addConstant(new_ptr_ty, new_ptr_val); |
| 15109 | } else break :rs offset_src; | 15121 | } else break :rs offset_src; |
| 15110 | } else break :rs ptr_src; | 15122 | } else break :rs ptr_src; |
| ... | @@ -25378,8 +25390,8 @@ fn elemPtrOneLayerOnly( | ... | @@ -25378,8 +25390,8 @@ fn elemPtrOneLayerOnly( |
| 25378 | const ptr_val = maybe_ptr_val orelse break :rs indexable_src; | 25390 | const ptr_val = maybe_ptr_val orelse break :rs indexable_src; |
| 25379 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 25391 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 25380 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); | 25392 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25381 | const elem_ptr = try ptr_val.elemPtr(indexable_ty, index, mod); | | |
| 25382 | const result_ty = try sema.elemPtrType(indexable_ty, index); | 25393 | const result_ty = try sema.elemPtrType(indexable_ty, index); |
| | 25394 | const elem_ptr = try ptr_val.elemPtr(result_ty, index, mod); |
| 25383 | return sema.addConstant(result_ty, elem_ptr); | 25395 | return sema.addConstant(result_ty, elem_ptr); |
| 25384 | }; | 25396 | }; |
| 25385 | const result_ty = try sema.elemPtrType(indexable_ty, null); | 25397 | const result_ty = try sema.elemPtrType(indexable_ty, null); |
| ... | @@ -25424,8 +25436,9 @@ fn elemVal( | ... | @@ -25424,8 +25436,9 @@ fn elemVal( |
| 25424 | const indexable_val = maybe_indexable_val orelse break :rs indexable_src; | 25436 | const indexable_val = maybe_indexable_val orelse break :rs indexable_src; |
| 25425 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 25437 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 25426 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); | 25438 | const index = @intCast(usize, index_val.toUnsignedInt(mod)); |
| 25427 | const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, index, mod); | 25439 | const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index); |
| 25428 | if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| { | 25440 | const elem_ptr_val = try indexable_val.elemPtr(elem_ptr_ty, index, mod); |
| | 25441 | if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| { |
| 25429 | return sema.addConstant(indexable_ty.elemType2(mod), elem_val); | 25442 | return sema.addConstant(indexable_ty.elemType2(mod), elem_val); |
| 25430 | } | 25443 | } |
| 25431 | break :rs indexable_src; | 25444 | break :rs indexable_src; |
| ... | @@ -25684,7 +25697,7 @@ fn elemPtrArray( | ... | @@ -25684,7 +25697,7 @@ fn elemPtrArray( |
| 25684 | return sema.addConstUndef(elem_ptr_ty); | 25697 | return sema.addConstUndef(elem_ptr_ty); |
| 25685 | } | 25698 | } |
| 25686 | if (offset) |index| { | 25699 | if (offset) |index| { |
| 25687 | const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, index, mod); | 25700 | const elem_ptr = try array_ptr_val.elemPtr(elem_ptr_ty, index, mod); |
| 25688 | return sema.addConstant(elem_ptr_ty, elem_ptr); | 25701 | return sema.addConstant(elem_ptr_ty, elem_ptr); |
| 25689 | } | 25702 | } |
| 25690 | } | 25703 | } |
| ... | @@ -25740,8 +25753,9 @@ fn elemValSlice( | ... | @@ -25740,8 +25753,9 @@ fn elemValSlice( |
| 25740 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; | 25753 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 25741 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); | 25754 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 25742 | } | 25755 | } |
| 25743 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod); | 25756 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, index); |
| 25744 | if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| { | 25757 | const elem_ptr_val = try slice_val.elemPtr(elem_ptr_ty, index, mod); |
| | 25758 | if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| { |
| 25745 | return sema.addConstant(elem_ty, elem_val); | 25759 | return sema.addConstant(elem_ty, elem_val); |
| 25746 | } | 25760 | } |
| 25747 | runtime_src = slice_src; | 25761 | runtime_src = slice_src; |
| ... | @@ -25800,7 +25814,7 @@ fn elemPtrSlice( | ... | @@ -25800,7 +25814,7 @@ fn elemPtrSlice( |
| 25800 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; | 25814 | const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else ""; |
| 25801 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); | 25815 | return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label }); |
| 25802 | } | 25816 | } |
| 25803 | const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod); | 25817 | const elem_ptr_val = try slice_val.elemPtr(elem_ptr_ty, index, mod); |
| 25804 | return sema.addConstant(elem_ptr_ty, elem_ptr_val); | 25818 | return sema.addConstant(elem_ptr_ty, elem_ptr_val); |
| 25805 | } | 25819 | } |
| 25806 | } | 25820 | } |
| ... | @@ -25916,7 +25930,10 @@ fn coerceExtra( | ... | @@ -25916,7 +25930,10 @@ fn coerceExtra( |
| 25916 | | 25930 | |
| 25917 | // null to ?T | 25931 | // null to ?T |
| 25918 | if (inst_ty.zigTypeTag(mod) == .Null) { | 25932 | if (inst_ty.zigTypeTag(mod) == .Null) { |
| 25919 | return sema.addConstant(dest_ty, Value.null); | 25933 | return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{ |
| | 25934 | .ty = dest_ty.toIntern(), |
| | 25935 | .val = .none, |
| | 25936 | } })).toValue()); |
| 25920 | } | 25937 | } |
| 25921 | | 25938 | |
| 25922 | // cast from ?*T and ?[*]T to ?*anyopaque | 25939 | // cast from ?*T and ?[*]T to ?*anyopaque |
| ... | @@ -27665,43 +27682,40 @@ fn storePtrVal( | ... | @@ -27665,43 +27682,40 @@ fn storePtrVal( |
| 27665 | switch (mut_kit.pointee) { | 27682 | switch (mut_kit.pointee) { |
| 27666 | .direct => |val_ptr| { | 27683 | .direct => |val_ptr| { |
| 27667 | if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) { | 27684 | if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) { |
| 27668 | if (!operand_val.eql(val_ptr.*, operand_ty, sema.mod)) { | 27685 | if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { |
| 27669 | // TODO use failWithInvalidComptimeFieldStore | 27686 | // TODO use failWithInvalidComptimeFieldStore |
| 27670 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); | 27687 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); |
| 27671 | } | 27688 | } |
| 27672 | return; | 27689 | return; |
| 27673 | } | 27690 | } |
| 27674 | const arena = mut_kit.beginArena(sema.mod); | 27691 | val_ptr.* = (try operand_val.intern(operand_ty, mod)).toValue(); |
| 27675 | defer mut_kit.finishArena(sema.mod); | | |
| 27676 | | | |
| 27677 | val_ptr.* = try operand_val.copy(arena); | | |
| 27678 | }, | 27692 | }, |
| 27679 | .reinterpret => |reinterpret| { | 27693 | .reinterpret => |reinterpret| { |
| 27680 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); | 27694 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); |
| 27681 | const buffer = try sema.gpa.alloc(u8, abi_size); | 27695 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 27682 | defer sema.gpa.free(buffer); | 27696 | defer sema.gpa.free(buffer); |
| 27683 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) { | 27697 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) { |
| 27684 | error.OutOfMemory => return error.OutOfMemory, | 27698 | error.OutOfMemory => return error.OutOfMemory, |
| 27685 | error.ReinterpretDeclRef => unreachable, | 27699 | error.ReinterpretDeclRef => unreachable, |
| 27686 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already | 27700 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already |
| 27687 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}), | 27701 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(mod)}), |
| 27688 | }; | 27702 | }; |
| 27689 | operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) { | 27703 | operand_val.writeToMemory(operand_ty, mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) { |
| 27690 | error.OutOfMemory => return error.OutOfMemory, | 27704 | error.OutOfMemory => return error.OutOfMemory, |
| 27691 | error.ReinterpretDeclRef => unreachable, | 27705 | error.ReinterpretDeclRef => unreachable, |
| 27692 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already | 27706 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already |
| 27693 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}), | 27707 | error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(mod)}), |
| 27694 | }; | 27708 | }; |
| 27695 | | 27709 | |
| 27696 | const arena = mut_kit.beginArena(sema.mod); | 27710 | const arena = mut_kit.beginArena(mod); |
| 27697 | defer mut_kit.finishArena(sema.mod); | 27711 | defer mut_kit.finishArena(mod); |
| 27698 | | 27712 | |
| 27699 | reinterpret.val_ptr.* = try Value.readFromMemory(mut_kit.ty, sema.mod, buffer, arena); | 27713 | reinterpret.val_ptr.* = (try (try Value.readFromMemory(mut_kit.ty, mod, buffer, arena)).intern(mut_kit.ty, mod)).toValue(); |
| 27700 | }, | 27714 | }, |
| 27701 | .bad_decl_ty, .bad_ptr_ty => { | 27715 | .bad_decl_ty, .bad_ptr_ty => { |
| 27702 | // TODO show the decl declaration site in a note and explain whether the decl | 27716 | // TODO show the decl declaration site in a note and explain whether the decl |
| 27703 | // or the pointer is the problematic type | 27717 | // or the pointer is the problematic type |
| 27704 | return sema.fail(block, src, "comptime mutation of a reinterpreted pointer requires type '{}' to have a well-defined memory layout", .{mut_kit.ty.fmt(sema.mod)}); | 27718 | return sema.fail(block, src, "comptime mutation of a reinterpreted pointer requires type '{}' to have a well-defined memory layout", .{mut_kit.ty.fmt(mod)}); |
| 27705 | }, | 27719 | }, |
| 27706 | } | 27720 | } |
| 27707 | } | 27721 | } |
| ... | @@ -27754,7 +27768,7 @@ fn beginComptimePtrMutation( | ... | @@ -27754,7 +27768,7 @@ fn beginComptimePtrMutation( |
| 27754 | const mod = sema.mod; | 27768 | const mod = sema.mod; |
| 27755 | const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr; | 27769 | const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr; |
| 27756 | switch (ptr.addr) { | 27770 | switch (ptr.addr) { |
| 27757 | .decl => unreachable, // isComptimeMutablePtr has been checked already | 27771 | .decl, .int => unreachable, // isComptimeMutablePtr has been checked already |
| 27758 | .mut_decl => |mut_decl| { | 27772 | .mut_decl => |mut_decl| { |
| 27759 | const decl = mod.declPtr(mut_decl.decl); | 27773 | const decl = mod.declPtr(mut_decl.decl); |
| 27760 | return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl); | 27774 | return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl); |
| ... | @@ -27767,546 +27781,472 @@ fn beginComptimePtrMutation( | ... | @@ -27767,546 +27781,472 @@ fn beginComptimePtrMutation( |
| 27767 | .runtime_index = .comptime_field_ptr, | 27781 | .runtime_index = .comptime_field_ptr, |
| 27768 | }); | 27782 | }); |
| 27769 | }, | 27783 | }, |
| 27770 | else => unreachable, | 27784 | .eu_payload => |eu_ptr| { |
| 27771 | } | 27785 | const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod); |
| 27772 | if (true) unreachable; | 27786 | var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.toValue(), eu_ty); |
| 27773 | switch (ptr_val.toIntern()) { | 27787 | switch (parent.pointee) { |
| 27774 | .none => switch (ptr_val.tag()) { | 27788 | .direct => |val_ptr| { |
| 27775 | .decl_ref_mut => { | 27789 | const payload_ty = parent.ty.errorUnionPayload(mod); |
| 27776 | const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data; | 27790 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { |
| 27777 | const decl = sema.mod.declPtr(decl_ref_mut.decl_index); | 27791 | return ComptimePtrMutationKit{ |
| 27778 | return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, decl_ref_mut); | 27792 | .mut_decl = parent.mut_decl, |
| 27779 | }, | 27793 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, |
| 27780 | .comptime_field_ptr => { | 27794 | .ty = payload_ty, |
| 27781 | const payload = ptr_val.castTag(.comptime_field_ptr).?.data; | 27795 | }; |
| 27782 | const duped = try sema.arena.create(Value); | 27796 | } else { |
| 27783 | duped.* = payload.field_val; | 27797 | // An error union has been initialized to undefined at comptime and now we |
| 27784 | return sema.beginComptimePtrMutationInner(block, src, payload.field_ty, duped, ptr_elem_ty, .{ | 27798 | // are for the first time setting the payload. We must change the |
| 27785 | .decl_index = @intToEnum(Module.Decl.Index, 0), | 27799 | // representation of the error union from `undef` to `opt_payload`. |
| 27786 | .runtime_index = .comptime_field_ptr, | 27800 | const arena = parent.beginArena(sema.mod); |
| 27787 | }); | 27801 | defer parent.finishArena(sema.mod); |
| 27788 | }, | 27802 | |
| 27789 | .elem_ptr => { | 27803 | const payload = try arena.create(Value.Payload.SubValue); |
| 27790 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; | 27804 | payload.* = .{ |
| 27791 | var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.array_ptr, elem_ptr.elem_ty); | 27805 | .base = .{ .tag = .eu_payload }, |
| 27792 | | 27806 | .data = Value.undef, |
| 27793 | switch (parent.pointee) { | 27807 | }; |
| 27794 | .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) { | | |
| 27795 | .Array, .Vector => { | | |
| 27796 | const check_len = parent.ty.arrayLenIncludingSentinel(mod); | | |
| 27797 | if (elem_ptr.index >= check_len) { | | |
| 27798 | // TODO have the parent include the decl so we can say "declared here" | | |
| 27799 | return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{ | | |
| 27800 | elem_ptr.index, check_len, | | |
| 27801 | }); | | |
| 27802 | } | | |
| 27803 | const elem_ty = parent.ty.childType(mod); | | |
| 27804 | | | |
| 27805 | // We might have a pointer to multiple elements of the array (e.g. a pointer | | |
| 27806 | // to a sub-array). In this case, we just have to reinterpret the relevant | | |
| 27807 | // bytes of the whole array rather than any single element. | | |
| 27808 | const elem_abi_size_u64 = try sema.typeAbiSize(elem_ptr.elem_ty); | | |
| 27809 | if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) { | | |
| 27810 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); | | |
| 27811 | return .{ | | |
| 27812 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 27813 | .pointee = .{ .reinterpret = .{ | | |
| 27814 | .val_ptr = val_ptr, | | |
| 27815 | .byte_offset = elem_abi_size * elem_ptr.index, | | |
| 27816 | } }, | | |
| 27817 | .ty = parent.ty, | | |
| 27818 | }; | | |
| 27819 | } | | |
| 27820 | | 27808 | |
| 27821 | switch (val_ptr.toIntern()) { | 27809 | val_ptr.* = Value.initPayload(&payload.base); |
| 27822 | .undef => { | | |
| 27823 | // An array has been initialized to undefined at comptime and now we | | |
| 27824 | // are for the first time setting an element. We must change the representation | | |
| 27825 | // of the array from `undef` to `array`. | | |
| 27826 | const arena = parent.beginArena(sema.mod); | | |
| 27827 | defer parent.finishArena(sema.mod); | | |
| 27828 | | 27810 | |
| 27829 | const array_len_including_sentinel = | 27811 | return ComptimePtrMutationKit{ |
| 27830 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | 27812 | .mut_decl = parent.mut_decl, |
| 27831 | const elems = try arena.alloc(Value, array_len_including_sentinel); | 27813 | .pointee = .{ .direct = &payload.data }, |
| 27832 | @memset(elems, Value.undef); | 27814 | .ty = payload_ty, |
| | 27815 | }; |
| | 27816 | } |
| | 27817 | }, |
| | 27818 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| | 27819 | // Even though the parent value type has well-defined memory layout, our |
| | 27820 | // pointer type does not. |
| | 27821 | .reinterpret => return ComptimePtrMutationKit{ |
| | 27822 | .mut_decl = parent.mut_decl, |
| | 27823 | .pointee = .bad_ptr_ty, |
| | 27824 | .ty = eu_ty, |
| | 27825 | }, |
| | 27826 | } |
| | 27827 | }, |
| | 27828 | .opt_payload => |opt_ptr| { |
| | 27829 | const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod); |
| | 27830 | var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.toValue(), opt_ty); |
| | 27831 | switch (parent.pointee) { |
| | 27832 | .direct => |val_ptr| { |
| | 27833 | const payload_ty = parent.ty.optionalChild(mod); |
| | 27834 | switch (val_ptr.ip_index) { |
| | 27835 | .undef, .null_value => { |
| | 27836 | // An optional has been initialized to undefined at comptime and now we |
| | 27837 | // are for the first time setting the payload. We must change the |
| | 27838 | // representation of the optional from `undef` to `opt_payload`. |
| | 27839 | const arena = parent.beginArena(sema.mod); |
| | 27840 | defer parent.finishArena(sema.mod); |
| 27833 | | 27841 | |
| 27834 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | 27842 | const payload = try arena.create(Value.Payload.SubValue); |
| | 27843 | payload.* = .{ |
| | 27844 | .base = .{ .tag = .opt_payload }, |
| | 27845 | .data = Value.undef, |
| | 27846 | }; |
| 27835 | | 27847 | |
| 27836 | return beginComptimePtrMutationInner( | 27848 | val_ptr.* = Value.initPayload(&payload.base); |
| 27837 | sema, | | |
| 27838 | block, | | |
| 27839 | src, | | |
| 27840 | elem_ty, | | |
| 27841 | &elems[elem_ptr.index], | | |
| 27842 | ptr_elem_ty, | | |
| 27843 | parent.decl_ref_mut, | | |
| 27844 | ); | | |
| 27845 | }, | | |
| 27846 | .none => switch (val_ptr.tag()) { | | |
| 27847 | .bytes => { | | |
| 27848 | // An array is memory-optimized to store a slice of bytes, but we are about | | |
| 27849 | // to modify an individual field and the representation has to change. | | |
| 27850 | // If we wanted to avoid this, there would need to be special detection | | |
| 27851 | // elsewhere to identify when writing a value to an array element that is stored | | |
| 27852 | // using the `bytes` tag, and handle it without making a call to this function. | | |
| 27853 | const arena = parent.beginArena(sema.mod); | | |
| 27854 | defer parent.finishArena(sema.mod); | | |
| 27855 | | | |
| 27856 | const bytes = val_ptr.castTag(.bytes).?.data; | | |
| 27857 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | | |
| 27858 | // bytes.len may be one greater than dest_len because of the case when | | |
| 27859 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. | | |
| 27860 | assert(bytes.len >= dest_len); | | |
| 27861 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); | | |
| 27862 | for (elems, 0..) |*elem, i| { | | |
| 27863 | elem.* = try mod.intValue(elem_ty, bytes[i]); | | |
| 27864 | } | | |
| 27865 | | | |
| 27866 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 27867 | | | |
| 27868 | return beginComptimePtrMutationInner( | | |
| 27869 | sema, | | |
| 27870 | block, | | |
| 27871 | src, | | |
| 27872 | elem_ty, | | |
| 27873 | &elems[elem_ptr.index], | | |
| 27874 | ptr_elem_ty, | | |
| 27875 | parent.decl_ref_mut, | | |
| 27876 | ); | | |
| 27877 | }, | | |
| 27878 | .str_lit => { | | |
| 27879 | // An array is memory-optimized to store a slice of bytes, but we are about | | |
| 27880 | // to modify an individual field and the representation has to change. | | |
| 27881 | // If we wanted to avoid this, there would need to be special detection | | |
| 27882 | // elsewhere to identify when writing a value to an array element that is stored | | |
| 27883 | // using the `str_lit` tag, and handle it without making a call to this function. | | |
| 27884 | const arena = parent.beginArena(sema.mod); | | |
| 27885 | defer parent.finishArena(sema.mod); | | |
| 27886 | | | |
| 27887 | const str_lit = val_ptr.castTag(.str_lit).?.data; | | |
| 27888 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | | |
| 27889 | const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len]; | | |
| 27890 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); | | |
| 27891 | for (bytes, 0..) |byte, i| { | | |
| 27892 | elems[i] = try mod.intValue(elem_ty, byte); | | |
| 27893 | } | | |
| 27894 | if (parent.ty.sentinel(mod)) |sent_val| { | | |
| 27895 | assert(elems.len == bytes.len + 1); | | |
| 27896 | elems[bytes.len] = sent_val; | | |
| 27897 | } | | |
| 27898 | | | |
| 27899 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 27900 | | | |
| 27901 | return beginComptimePtrMutationInner( | | |
| 27902 | sema, | | |
| 27903 | block, | | |
| 27904 | src, | | |
| 27905 | elem_ty, | | |
| 27906 | &elems[elem_ptr.index], | | |
| 27907 | ptr_elem_ty, | | |
| 27908 | parent.decl_ref_mut, | | |
| 27909 | ); | | |
| 27910 | }, | | |
| 27911 | .repeated => { | | |
| 27912 | // An array is memory-optimized to store only a single element value, and | | |
| 27913 | // that value is understood to be the same for the entire length of the array. | | |
| 27914 | // However, now we want to modify an individual field and so the | | |
| 27915 | // representation has to change. If we wanted to avoid this, there would | | |
| 27916 | // need to be special detection elsewhere to identify when writing a value to an | | |
| 27917 | // array element that is stored using the `repeated` tag, and handle it | | |
| 27918 | // without making a call to this function. | | |
| 27919 | const arena = parent.beginArena(sema.mod); | | |
| 27920 | defer parent.finishArena(sema.mod); | | |
| 27921 | | | |
| 27922 | const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena); | | |
| 27923 | const array_len_including_sentinel = | | |
| 27924 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | | |
| 27925 | const elems = try arena.alloc(Value, array_len_including_sentinel); | | |
| 27926 | if (elems.len > 0) elems[0] = repeated_val; | | |
| 27927 | for (elems[1..]) |*elem| { | | |
| 27928 | elem.* = try repeated_val.copy(arena); | | |
| 27929 | } | | |
| 27930 | | | |
| 27931 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 27932 | | | |
| 27933 | return beginComptimePtrMutationInner( | | |
| 27934 | sema, | | |
| 27935 | block, | | |
| 27936 | src, | | |
| 27937 | elem_ty, | | |
| 27938 | &elems[elem_ptr.index], | | |
| 27939 | ptr_elem_ty, | | |
| 27940 | parent.decl_ref_mut, | | |
| 27941 | ); | | |
| 27942 | }, | | |
| 27943 | | | |
| 27944 | .aggregate => return beginComptimePtrMutationInner( | | |
| 27945 | sema, | | |
| 27946 | block, | | |
| 27947 | src, | | |
| 27948 | elem_ty, | | |
| 27949 | &val_ptr.castTag(.aggregate).?.data[elem_ptr.index], | | |
| 27950 | ptr_elem_ty, | | |
| 27951 | parent.decl_ref_mut, | | |
| 27952 | ), | | |
| 27953 | | 27849 | |
| 27954 | .the_only_possible_value => { | 27850 | return ComptimePtrMutationKit{ |
| 27955 | const duped = try sema.arena.create(Value); | 27851 | .mut_decl = parent.mut_decl, |
| 27956 | duped.* = Value.initTag(.the_only_possible_value); | 27852 | .pointee = .{ .direct = &payload.data }, |
| 27957 | return beginComptimePtrMutationInner( | 27853 | .ty = payload_ty, |
| 27958 | sema, | 27854 | }; |
| 27959 | block, | 27855 | }, |
| 27960 | src, | 27856 | .none => switch (val_ptr.tag()) { |
| 27961 | elem_ty, | 27857 | .opt_payload => return ComptimePtrMutationKit{ |
| 27962 | duped, | 27858 | .mut_decl = parent.mut_decl, |
| 27963 | ptr_elem_ty, | 27859 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, |
| 27964 | parent.decl_ref_mut, | 27860 | .ty = payload_ty, |
| 27965 | ); | 27861 | }, |
| 27966 | }, | | |
| 27967 | | 27862 | |
| 27968 | else => unreachable, | 27863 | else => return ComptimePtrMutationKit{ |
| 27969 | }, | 27864 | .mut_decl = parent.mut_decl, |
| 27970 | else => unreachable, | 27865 | .pointee = .{ .direct = val_ptr }, |
| 27971 | } | 27866 | .ty = payload_ty, |
| | 27867 | }, |
| 27972 | }, | 27868 | }, |
| 27973 | else => { | 27869 | else => return ComptimePtrMutationKit{ |
| 27974 | if (elem_ptr.index != 0) { | 27870 | .mut_decl = parent.mut_decl, |
| 27975 | // TODO include a "declared here" note for the decl | 27871 | .pointee = .{ .direct = val_ptr }, |
| 27976 | return sema.fail(block, src, "out of bounds comptime store of index {d}", .{ | 27872 | .ty = payload_ty, |
| 27977 | elem_ptr.index, | | |
| 27978 | }); | | |
| 27979 | } | | |
| 27980 | return beginComptimePtrMutationInner( | | |
| 27981 | sema, | | |
| 27982 | block, | | |
| 27983 | src, | | |
| 27984 | parent.ty, | | |
| 27985 | val_ptr, | | |
| 27986 | ptr_elem_ty, | | |
| 27987 | parent.decl_ref_mut, | | |
| 27988 | ); | | |
| 27989 | }, | 27873 | }, |
| 27990 | }, | 27874 | } |
| 27991 | .reinterpret => |reinterpret| { | 27875 | }, |
| 27992 | if (!elem_ptr.elem_ty.hasWellDefinedLayout(mod)) { | 27876 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 27993 | // Even though the parent value type has well-defined memory layout, our | 27877 | // Even though the parent value type has well-defined memory layout, our |
| 27994 | // pointer type does not. | 27878 | // pointer type does not. |
| 27995 | return ComptimePtrMutationKit{ | 27879 | .reinterpret => return ComptimePtrMutationKit{ |
| 27996 | .decl_ref_mut = parent.decl_ref_mut, | 27880 | .mut_decl = parent.mut_decl, |
| 27997 | .pointee = .bad_ptr_ty, | 27881 | .pointee = .bad_ptr_ty, |
| 27998 | .ty = elem_ptr.elem_ty, | 27882 | .ty = opt_ty, |
| | 27883 | }, |
| | 27884 | } |
| | 27885 | }, |
| | 27886 | .elem => |elem_ptr| { |
| | 27887 | const base_elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod); |
| | 27888 | var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.base.toValue(), base_elem_ty); |
| | 27889 | |
| | 27890 | switch (parent.pointee) { |
| | 27891 | .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) { |
| | 27892 | .Array, .Vector => { |
| | 27893 | const check_len = parent.ty.arrayLenIncludingSentinel(mod); |
| | 27894 | if (elem_ptr.index >= check_len) { |
| | 27895 | // TODO have the parent include the decl so we can say "declared here" |
| | 27896 | return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{ |
| | 27897 | elem_ptr.index, check_len, |
| | 27898 | }); |
| | 27899 | } |
| | 27900 | const elem_ty = parent.ty.childType(mod); |
| | 27901 | |
| | 27902 | // We might have a pointer to multiple elements of the array (e.g. a pointer |
| | 27903 | // to a sub-array). In this case, we just have to reinterpret the relevant |
| | 27904 | // bytes of the whole array rather than any single element. |
| | 27905 | const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); |
| | 27906 | if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) { |
| | 27907 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| | 27908 | return .{ |
| | 27909 | .mut_decl = parent.mut_decl, |
| | 27910 | .pointee = .{ .reinterpret = .{ |
| | 27911 | .val_ptr = val_ptr, |
| | 27912 | .byte_offset = elem_abi_size * elem_ptr.index, |
| | 27913 | } }, |
| | 27914 | .ty = parent.ty, |
| 27999 | }; | 27915 | }; |
| 28000 | } | 27916 | } |
| 28001 | | 27917 | |
| 28002 | const elem_abi_size_u64 = try sema.typeAbiSize(elem_ptr.elem_ty); | 27918 | switch (val_ptr.ip_index) { |
| 28003 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); | 27919 | .undef => { |
| 28004 | return ComptimePtrMutationKit{ | 27920 | // An array has been initialized to undefined at comptime and now we |
| 28005 | .decl_ref_mut = parent.decl_ref_mut, | 27921 | // are for the first time setting an element. We must change the representation |
| 28006 | .pointee = .{ .reinterpret = .{ | 27922 | // of the array from `undef` to `array`. |
| 28007 | .val_ptr = reinterpret.val_ptr, | 27923 | const arena = parent.beginArena(sema.mod); |
| 28008 | .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_ptr.index, | 27924 | defer parent.finishArena(sema.mod); |
| 28009 | } }, | | |
| 28010 | .ty = parent.ty, | | |
| 28011 | }; | | |
| 28012 | }, | | |
| 28013 | .bad_decl_ty, .bad_ptr_ty => return parent, | | |
| 28014 | } | | |
| 28015 | }, | | |
| 28016 | .field_ptr => { | | |
| 28017 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | | |
| 28018 | const field_index = @intCast(u32, field_ptr.field_index); | | |
| 28019 | | 27925 | |
| 28020 | var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.container_ptr, field_ptr.container_ty); | 27926 | const array_len_including_sentinel = |
| 28021 | switch (parent.pointee) { | 27927 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); |
| 28022 | .direct => |val_ptr| switch (val_ptr.toIntern()) { | 27928 | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| 28023 | .undef => { | 27929 | @memset(elems, Value.undef); |
| 28024 | // A struct or union has been initialized to undefined at comptime and now we | | |
| 28025 | // are for the first time setting a field. We must change the representation | | |
| 28026 | // of the struct/union from `undef` to `struct`/`union`. | | |
| 28027 | const arena = parent.beginArena(sema.mod); | | |
| 28028 | defer parent.finishArena(sema.mod); | | |
| 28029 | | 27930 | |
| 28030 | switch (parent.ty.zigTypeTag(mod)) { | 27931 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 28031 | .Struct => { | | |
| 28032 | const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | | |
| 28033 | @memset(fields, Value.undef); | | |
| 28034 | | 27932 | |
| 28035 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); | 27933 | return beginComptimePtrMutationInner( |
| | 27934 | sema, |
| | 27935 | block, |
| | 27936 | src, |
| | 27937 | elem_ty, |
| | 27938 | &elems[elem_ptr.index], |
| | 27939 | ptr_elem_ty, |
| | 27940 | parent.mut_decl, |
| | 27941 | ); |
| | 27942 | }, |
| | 27943 | .none => switch (val_ptr.tag()) { |
| | 27944 | .bytes => { |
| | 27945 | // An array is memory-optimized to store a slice of bytes, but we are about |
| | 27946 | // to modify an individual field and the representation has to change. |
| | 27947 | // If we wanted to avoid this, there would need to be special detection |
| | 27948 | // elsewhere to identify when writing a value to an array element that is stored |
| | 27949 | // using the `bytes` tag, and handle it without making a call to this function. |
| | 27950 | const arena = parent.beginArena(sema.mod); |
| | 27951 | defer parent.finishArena(sema.mod); |
| | 27952 | |
| | 27953 | const bytes = val_ptr.castTag(.bytes).?.data; |
| | 27954 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); |
| | 27955 | // bytes.len may be one greater than dest_len because of the case when |
| | 27956 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. |
| | 27957 | assert(bytes.len >= dest_len); |
| | 27958 | const elems = try arena.alloc(Value, @intCast(usize, dest_len)); |
| | 27959 | for (elems, 0..) |*elem, i| { |
| | 27960 | elem.* = try mod.intValue(elem_ty, bytes[i]); |
| | 27961 | } |
| | 27962 | |
| | 27963 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 28036 | | 27964 | |
| 28037 | return beginComptimePtrMutationInner( | 27965 | return beginComptimePtrMutationInner( |
| 28038 | sema, | 27966 | sema, |
| 28039 | block, | 27967 | block, |
| 28040 | src, | 27968 | src, |
| 28041 | parent.ty.structFieldType(field_index, mod), | 27969 | elem_ty, |
| 28042 | &fields[field_index], | 27970 | &elems[elem_ptr.index], |
| 28043 | ptr_elem_ty, | 27971 | ptr_elem_ty, |
| 28044 | parent.decl_ref_mut, | 27972 | parent.mut_decl, |
| 28045 | ); | 27973 | ); |
| 28046 | }, | 27974 | }, |
| 28047 | .Union => { | 27975 | .repeated => { |
| 28048 | const payload = try arena.create(Value.Payload.Union); | 27976 | // An array is memory-optimized to store only a single element value, and |
| 28049 | const tag_ty = parent.ty.unionTagTypeHypothetical(mod); | 27977 | // that value is understood to be the same for the entire length of the array. |
| 28050 | payload.* = .{ .data = .{ | 27978 | // However, now we want to modify an individual field and so the |
| 28051 | .tag = try mod.enumValueFieldIndex(tag_ty, field_index), | 27979 | // representation has to change. If we wanted to avoid this, there would |
| 28052 | .val = Value.undef, | 27980 | // need to be special detection elsewhere to identify when writing a value to an |
| 28053 | } }; | 27981 | // array element that is stored using the `repeated` tag, and handle it |
| | 27982 | // without making a call to this function. |
| | 27983 | const arena = parent.beginArena(sema.mod); |
| | 27984 | defer parent.finishArena(sema.mod); |
| | 27985 | |
| | 27986 | const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena); |
| | 27987 | const array_len_including_sentinel = |
| | 27988 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); |
| | 27989 | const elems = try arena.alloc(Value, array_len_including_sentinel); |
| | 27990 | if (elems.len > 0) elems[0] = repeated_val; |
| | 27991 | for (elems[1..]) |*elem| { |
| | 27992 | elem.* = try repeated_val.copy(arena); |
| | 27993 | } |
| 28054 | | 27994 | |
| 28055 | val_ptr.* = Value.initPayload(&payload.base); | 27995 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 28056 | | 27996 | |
| 28057 | return beginComptimePtrMutationInner( | 27997 | return beginComptimePtrMutationInner( |
| 28058 | sema, | 27998 | sema, |
| 28059 | block, | 27999 | block, |
| 28060 | src, | 28000 | src, |
| 28061 | parent.ty.structFieldType(field_index, mod), | 28001 | elem_ty, |
| 28062 | &payload.data.val, | 28002 | &elems[elem_ptr.index], |
| 28063 | ptr_elem_ty, | 28003 | ptr_elem_ty, |
| 28064 | parent.decl_ref_mut, | 28004 | parent.mut_decl, |
| 28065 | ); | 28005 | ); |
| 28066 | }, | 28006 | }, |
| 28067 | .Pointer => { | 28007 | |
| 28068 | assert(parent.ty.isSlice(mod)); | 28008 | .aggregate => return beginComptimePtrMutationInner( |
| 28069 | val_ptr.* = try Value.Tag.slice.create(arena, .{ | 28009 | sema, |
| 28070 | .ptr = Value.undef, | 28010 | block, |
| 28071 | .len = Value.undef, | 28011 | src, |
| 28072 | }); | 28012 | elem_ty, |
| 28073 | | 28013 | &val_ptr.castTag(.aggregate).?.data[elem_ptr.index], |
| 28074 | switch (field_index) { | 28014 | ptr_elem_ty, |
| 28075 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( | 28015 | parent.mut_decl, |
| 28076 | sema, | 28016 | ), |
| 28077 | block, | 28017 | |
| 28078 | src, | | |
| 28079 | parent.ty.slicePtrFieldType(mod), | | |
| 28080 | &val_ptr.castTag(.slice).?.data.ptr, | | |
| 28081 | ptr_elem_ty, | | |
| 28082 | parent.decl_ref_mut, | | |
| 28083 | ), | | |
| 28084 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( | | |
| 28085 | sema, | | |
| 28086 | block, | | |
| 28087 | src, | | |
| 28088 | Type.usize, | | |
| 28089 | &val_ptr.castTag(.slice).?.data.len, | | |
| 28090 | ptr_elem_ty, | | |
| 28091 | parent.decl_ref_mut, | | |
| 28092 | ), | | |
| 28093 | | | |
| 28094 | else => unreachable, | | |
| 28095 | } | | |
| 28096 | }, | | |
| 28097 | else => unreachable, | 28018 | else => unreachable, |
| 28098 | } | 28019 | }, |
| 28099 | }, | 28020 | else => unreachable, |
| 28100 | .empty_struct => { | 28021 | } |
| 28101 | const duped = try sema.arena.create(Value); | 28022 | }, |
| 28102 | duped.* = Value.initTag(.the_only_possible_value); | 28023 | else => { |
| 28103 | return beginComptimePtrMutationInner( | 28024 | if (elem_ptr.index != 0) { |
| 28104 | sema, | 28025 | // TODO include a "declared here" note for the decl |
| 28105 | block, | 28026 | return sema.fail(block, src, "out of bounds comptime store of index {d}", .{ |
| 28106 | src, | 28027 | elem_ptr.index, |
| 28107 | parent.ty.structFieldType(field_index, mod), | 28028 | }); |
| 28108 | duped, | 28029 | } |
| 28109 | ptr_elem_ty, | 28030 | return beginComptimePtrMutationInner( |
| 28110 | parent.decl_ref_mut, | 28031 | sema, |
| 28111 | ); | 28032 | block, |
| 28112 | }, | 28033 | src, |
| 28113 | .none => switch (val_ptr.tag()) { | 28034 | parent.ty, |
| 28114 | .aggregate => return beginComptimePtrMutationInner( | 28035 | val_ptr, |
| 28115 | sema, | 28036 | ptr_elem_ty, |
| 28116 | block, | 28037 | parent.mut_decl, |
| 28117 | src, | 28038 | ); |
| 28118 | parent.ty.structFieldType(field_index, mod), | 28039 | }, |
| 28119 | &val_ptr.castTag(.aggregate).?.data[field_index], | 28040 | }, |
| 28120 | ptr_elem_ty, | 28041 | .reinterpret => |reinterpret| { |
| 28121 | parent.decl_ref_mut, | 28042 | if (!base_elem_ty.hasWellDefinedLayout(mod)) { |
| 28122 | ), | 28043 | // Even though the parent value type has well-defined memory layout, our |
| 28123 | .repeated => { | 28044 | // pointer type does not. |
| 28124 | const arena = parent.beginArena(sema.mod); | 28045 | return ComptimePtrMutationKit{ |
| 28125 | defer parent.finishArena(sema.mod); | 28046 | .mut_decl = parent.mut_decl, |
| | 28047 | .pointee = .bad_ptr_ty, |
| | 28048 | .ty = base_elem_ty, |
| | 28049 | }; |
| | 28050 | } |
| 28126 | | 28051 | |
| 28127 | const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | 28052 | const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); |
| 28128 | @memset(elems, val_ptr.castTag(.repeated).?.data); | 28053 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 28129 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | 28054 | return ComptimePtrMutationKit{ |
| | 28055 | .mut_decl = parent.mut_decl, |
| | 28056 | .pointee = .{ .reinterpret = .{ |
| | 28057 | .val_ptr = reinterpret.val_ptr, |
| | 28058 | .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_ptr.index, |
| | 28059 | } }, |
| | 28060 | .ty = parent.ty, |
| | 28061 | }; |
| | 28062 | }, |
| | 28063 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| | 28064 | } |
| | 28065 | }, |
| | 28066 | .field => |field_ptr| { |
| | 28067 | const base_child_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod); |
| | 28068 | const field_index = @intCast(u32, field_ptr.index); |
| | 28069 | |
| | 28070 | var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty); |
| | 28071 | switch (parent.pointee) { |
| | 28072 | .direct => |val_ptr| switch (val_ptr.ip_index) { |
| | 28073 | .undef => { |
| | 28074 | // A struct or union has been initialized to undefined at comptime and now we |
| | 28075 | // are for the first time setting a field. We must change the representation |
| | 28076 | // of the struct/union from `undef` to `struct`/`union`. |
| | 28077 | const arena = parent.beginArena(sema.mod); |
| | 28078 | defer parent.finishArena(sema.mod); |
| | 28079 | |
| | 28080 | switch (parent.ty.zigTypeTag(mod)) { |
| | 28081 | .Struct => { |
| | 28082 | const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); |
| | 28083 | @memset(fields, Value.undef); |
| | 28084 | |
| | 28085 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); |
| 28130 | | 28086 | |
| 28131 | return beginComptimePtrMutationInner( | 28087 | return beginComptimePtrMutationInner( |
| 28132 | sema, | 28088 | sema, |
| 28133 | block, | 28089 | block, |
| 28134 | src, | 28090 | src, |
| 28135 | parent.ty.structFieldType(field_index, mod), | 28091 | parent.ty.structFieldType(field_index, mod), |
| 28136 | &elems[field_index], | 28092 | &fields[field_index], |
| 28137 | ptr_elem_ty, | 28093 | ptr_elem_ty, |
| 28138 | parent.decl_ref_mut, | 28094 | parent.mut_decl, |
| 28139 | ); | 28095 | ); |
| 28140 | }, | 28096 | }, |
| 28141 | .@"union" => { | 28097 | .Union => { |
| 28142 | // We need to set the active field of the union. | 28098 | const payload = try arena.create(Value.Payload.Union); |
| 28143 | const union_tag_ty = field_ptr.container_ty.unionTagTypeHypothetical(mod); | 28099 | const tag_ty = parent.ty.unionTagTypeHypothetical(mod); |
| | 28100 | payload.* = .{ .data = .{ |
| | 28101 | .tag = try mod.enumValueFieldIndex(tag_ty, field_index), |
| | 28102 | .val = Value.undef, |
| | 28103 | } }; |
| 28144 | | 28104 | |
| 28145 | const payload = &val_ptr.castTag(.@"union").?.data; | 28105 | val_ptr.* = Value.initPayload(&payload.base); |
| 28146 | payload.tag = try mod.enumValueFieldIndex(union_tag_ty, field_index); | | |
| 28147 | | 28106 | |
| 28148 | return beginComptimePtrMutationInner( | 28107 | return beginComptimePtrMutationInner( |
| 28149 | sema, | 28108 | sema, |
| 28150 | block, | 28109 | block, |
| 28151 | src, | 28110 | src, |
| 28152 | parent.ty.structFieldType(field_index, mod), | 28111 | parent.ty.structFieldType(field_index, mod), |
| 28153 | &payload.val, | 28112 | &payload.data.val, |
| 28154 | ptr_elem_ty, | 28113 | ptr_elem_ty, |
| 28155 | parent.decl_ref_mut, | 28114 | parent.mut_decl, |
| 28156 | ); | 28115 | ); |
| 28157 | }, | 28116 | }, |
| 28158 | .slice => switch (field_index) { | 28117 | .Pointer => { |
| 28159 | Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner( | 28118 | assert(parent.ty.isSlice(mod)); |
| 28160 | sema, | 28119 | val_ptr.* = try Value.Tag.slice.create(arena, .{ |
| 28161 | block, | 28120 | .ptr = Value.undef, |
| 28162 | src, | 28121 | .len = Value.undef, |
| 28163 | parent.ty.slicePtrFieldType(mod), | 28122 | }); |
| 28164 | &val_ptr.castTag(.slice).?.data.ptr, | | |
| 28165 | ptr_elem_ty, | | |
| 28166 | parent.decl_ref_mut, | | |
| 28167 | ), | | |
| 28168 | | 28123 | |
| 28169 | Value.Payload.Slice.len_index => return beginComptimePtrMutationInner( | 28124 | switch (field_index) { |
| 28170 | sema, | 28125 | Value.slice_ptr_index => return beginComptimePtrMutationInner( |
| 28171 | block, | 28126 | sema, |
| 28172 | src, | 28127 | block, |
| 28173 | Type.usize, | 28128 | src, |
| 28174 | &val_ptr.castTag(.slice).?.data.len, | 28129 | parent.ty.slicePtrFieldType(mod), |
| 28175 | ptr_elem_ty, | 28130 | &val_ptr.castTag(.slice).?.data.ptr, |
| 28176 | parent.decl_ref_mut, | 28131 | ptr_elem_ty, |
| 28177 | ), | 28132 | parent.mut_decl, |
| | 28133 | ), |
| | 28134 | Value.slice_len_index => return beginComptimePtrMutationInner( |
| | 28135 | sema, |
| | 28136 | block, |
| | 28137 | src, |
| | 28138 | Type.usize, |
| | 28139 | &val_ptr.castTag(.slice).?.data.len, |
| | 28140 | ptr_elem_ty, |
| | 28141 | parent.mut_decl, |
| | 28142 | ), |
| 28178 | | 28143 | |
| 28179 | else => unreachable, | 28144 | else => unreachable, |
| | 28145 | } |
| 28180 | }, | 28146 | }, |
| 28181 | | | |
| 28182 | else => unreachable, | 28147 | else => unreachable, |
| 28183 | }, | 28148 | } |
| 28184 | else => unreachable, | | |
| 28185 | }, | 28149 | }, |
| 28186 | .reinterpret => |reinterpret| { | 28150 | .empty_struct => { |
| 28187 | const field_offset_u64 = field_ptr.container_ty.structFieldOffset(field_index, mod); | 28151 | const duped = try sema.arena.create(Value); |
| 28188 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); | 28152 | duped.* = val_ptr.*; |
| 28189 | return ComptimePtrMutationKit{ | 28153 | return beginComptimePtrMutationInner( |
| 28190 | .decl_ref_mut = parent.decl_ref_mut, | 28154 | sema, |
| 28191 | .pointee = .{ .reinterpret = .{ | 28155 | block, |
| 28192 | .val_ptr = reinterpret.val_ptr, | 28156 | src, |
| 28193 | .byte_offset = reinterpret.byte_offset + field_offset, | 28157 | parent.ty.structFieldType(field_index, mod), |
| 28194 | } }, | 28158 | duped, |
| 28195 | .ty = parent.ty, | 28159 | ptr_elem_ty, |
| 28196 | }; | 28160 | parent.mut_decl, |
| | 28161 | ); |
| 28197 | }, | 28162 | }, |
| 28198 | .bad_decl_ty, .bad_ptr_ty => return parent, | 28163 | .none => switch (val_ptr.tag()) { |
| 28199 | } | 28164 | .aggregate => return beginComptimePtrMutationInner( |
| 28200 | }, | 28165 | sema, |
| 28201 | .eu_payload_ptr => { | 28166 | block, |
| 28202 | const eu_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; | 28167 | src, |
| 28203 | var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.container_ptr, eu_ptr.container_ty); | 28168 | parent.ty.structFieldType(field_index, mod), |
| 28204 | switch (parent.pointee) { | 28169 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 28205 | .direct => |val_ptr| { | 28170 | ptr_elem_ty, |
| 28206 | const payload_ty = parent.ty.errorUnionPayload(mod); | 28171 | parent.mut_decl, |
| 28207 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { | 28172 | ), |
| 28208 | return ComptimePtrMutationKit{ | 28173 | .repeated => { |
| 28209 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28210 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, | | |
| 28211 | .ty = payload_ty, | | |
| 28212 | }; | | |
| 28213 | } else { | | |
| 28214 | // An error union has been initialized to undefined at comptime and now we | | |
| 28215 | // are for the first time setting the payload. We must change the | | |
| 28216 | // representation of the error union from `undef` to `opt_payload`. | | |
| 28217 | const arena = parent.beginArena(sema.mod); | 28174 | const arena = parent.beginArena(sema.mod); |
| 28218 | defer parent.finishArena(sema.mod); | 28175 | defer parent.finishArena(sema.mod); |
| 28219 | | 28176 | |
| 28220 | const payload = try arena.create(Value.Payload.SubValue); | 28177 | const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); |
| 28221 | payload.* = .{ | 28178 | @memset(elems, val_ptr.castTag(.repeated).?.data); |
| 28222 | .base = .{ .tag = .eu_payload }, | 28179 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); |
| 28223 | .data = Value.undef, | | |
| 28224 | }; | | |
| 28225 | | 28180 | |
| 28226 | val_ptr.* = Value.initPayload(&payload.base); | 28181 | return beginComptimePtrMutationInner( |
| | 28182 | sema, |
| | 28183 | block, |
| | 28184 | src, |
| | 28185 | parent.ty.structFieldType(field_index, mod), |
| | 28186 | &elems[field_index], |
| | 28187 | ptr_elem_ty, |
| | 28188 | parent.mut_decl, |
| | 28189 | ); |
| | 28190 | }, |
| | 28191 | .@"union" => { |
| | 28192 | // We need to set the active field of the union. |
| | 28193 | const union_tag_ty = base_child_ty.unionTagTypeHypothetical(mod); |
| 28227 | | 28194 | |
| 28228 | return ComptimePtrMutationKit{ | 28195 | const payload = &val_ptr.castTag(.@"union").?.data; |
| 28229 | .decl_ref_mut = parent.decl_ref_mut, | 28196 | payload.tag = try mod.enumValueFieldIndex(union_tag_ty, field_index); |
| 28230 | .pointee = .{ .direct = &payload.data }, | | |
| 28231 | .ty = payload_ty, | | |
| 28232 | }; | | |
| 28233 | } | | |
| 28234 | }, | | |
| 28235 | .bad_decl_ty, .bad_ptr_ty => return parent, | | |
| 28236 | // Even though the parent value type has well-defined memory layout, our | | |
| 28237 | // pointer type does not. | | |
| 28238 | .reinterpret => return ComptimePtrMutationKit{ | | |
| 28239 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28240 | .pointee = .bad_ptr_ty, | | |
| 28241 | .ty = eu_ptr.container_ty, | | |
| 28242 | }, | | |
| 28243 | } | | |
| 28244 | }, | | |
| 28245 | .opt_payload_ptr => { | | |
| 28246 | const opt_ptr = if (ptr_val.castTag(.opt_payload_ptr)) |some| some.data else { | | |
| 28247 | return sema.beginComptimePtrMutation(block, src, ptr_val, ptr_elem_ty.optionalChild(mod)); | | |
| 28248 | }; | | |
| 28249 | var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.container_ptr, opt_ptr.container_ty); | | |
| 28250 | switch (parent.pointee) { | | |
| 28251 | .direct => |val_ptr| { | | |
| 28252 | const payload_ty = parent.ty.optionalChild(mod); | | |
| 28253 | switch (val_ptr.toIntern()) { | | |
| 28254 | .undef, .null_value => { | | |
| 28255 | // An optional has been initialized to undefined at comptime and now we | | |
| 28256 | // are for the first time setting the payload. We must change the | | |
| 28257 | // representation of the optional from `undef` to `opt_payload`. | | |
| 28258 | const arena = parent.beginArena(sema.mod); | | |
| 28259 | defer parent.finishArena(sema.mod); | | |
| 28260 | | 28197 | |
| 28261 | const payload = try arena.create(Value.Payload.SubValue); | 28198 | return beginComptimePtrMutationInner( |
| 28262 | payload.* = .{ | 28199 | sema, |
| 28263 | .base = .{ .tag = .opt_payload }, | 28200 | block, |
| 28264 | .data = Value.undef, | 28201 | src, |
| 28265 | }; | 28202 | parent.ty.structFieldType(field_index, mod), |
| | 28203 | &payload.val, |
| | 28204 | ptr_elem_ty, |
| | 28205 | parent.mut_decl, |
| | 28206 | ); |
| | 28207 | }, |
| | 28208 | .slice => switch (field_index) { |
| | 28209 | Value.slice_ptr_index => return beginComptimePtrMutationInner( |
| | 28210 | sema, |
| | 28211 | block, |
| | 28212 | src, |
| | 28213 | parent.ty.slicePtrFieldType(mod), |
| | 28214 | &val_ptr.castTag(.slice).?.data.ptr, |
| | 28215 | ptr_elem_ty, |
| | 28216 | parent.mut_decl, |
| | 28217 | ), |
| 28266 | | 28218 | |
| 28267 | val_ptr.* = Value.initPayload(&payload.base); | 28219 | Value.slice_len_index => return beginComptimePtrMutationInner( |
| | 28220 | sema, |
| | 28221 | block, |
| | 28222 | src, |
| | 28223 | Type.usize, |
| | 28224 | &val_ptr.castTag(.slice).?.data.len, |
| | 28225 | ptr_elem_ty, |
| | 28226 | parent.mut_decl, |
| | 28227 | ), |
| 28268 | | 28228 | |
| 28269 | return ComptimePtrMutationKit{ | 28229 | else => unreachable, |
| 28270 | .decl_ref_mut = parent.decl_ref_mut, | 28230 | }, |
| 28271 | .pointee = .{ .direct = &payload.data }, | | |
| 28272 | .ty = payload_ty, | | |
| 28273 | }; | | |
| 28274 | }, | | |
| 28275 | .none => switch (val_ptr.tag()) { | | |
| 28276 | .opt_payload => return ComptimePtrMutationKit{ | | |
| 28277 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28278 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, | | |
| 28279 | .ty = payload_ty, | | |
| 28280 | }, | | |
| 28281 | | 28231 | |
| 28282 | else => return ComptimePtrMutationKit{ | 28232 | else => unreachable, |
| 28283 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28284 | .pointee = .{ .direct = val_ptr }, | | |
| 28285 | .ty = payload_ty, | | |
| 28286 | }, | | |
| 28287 | }, | | |
| 28288 | else => return ComptimePtrMutationKit{ | | |
| 28289 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28290 | .pointee = .{ .direct = val_ptr }, | | |
| 28291 | .ty = payload_ty, | | |
| 28292 | }, | | |
| 28293 | } | | |
| 28294 | }, | | |
| 28295 | .bad_decl_ty, .bad_ptr_ty => return parent, | | |
| 28296 | // Even though the parent value type has well-defined memory layout, our | | |
| 28297 | // pointer type does not. | | |
| 28298 | .reinterpret => return ComptimePtrMutationKit{ | | |
| 28299 | .decl_ref_mut = parent.decl_ref_mut, | | |
| 28300 | .pointee = .bad_ptr_ty, | | |
| 28301 | .ty = opt_ptr.container_ty, | | |
| 28302 | }, | 28233 | }, |
| 28303 | } | 28234 | else => unreachable, |
| 28304 | }, | 28235 | }, |
| 28305 | .decl_ref => unreachable, // isComptimeMutablePtr has been checked already | 28236 | .reinterpret => |reinterpret| { |
| 28306 | else => unreachable, | 28237 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); |
| 28307 | }, | 28238 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 28308 | else => switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr) { | 28239 | return ComptimePtrMutationKit{ |
| 28309 | else => unreachable, | 28240 | .mut_decl = parent.mut_decl, |
| | 28241 | .pointee = .{ .reinterpret = .{ |
| | 28242 | .val_ptr = reinterpret.val_ptr, |
| | 28243 | .byte_offset = reinterpret.byte_offset + field_offset, |
| | 28244 | } }, |
| | 28245 | .ty = parent.ty, |
| | 28246 | }; |
| | 28247 | }, |
| | 28248 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| | 28249 | } |
| 28310 | }, | 28250 | }, |
| 28311 | } | 28251 | } |
| 28312 | } | 28252 | } |
| ... | @@ -28418,6 +28358,7 @@ fn beginComptimePtrLoad( | ... | @@ -28418,6 +28358,7 @@ fn beginComptimePtrLoad( |
| 28418 | .mut_decl => |mut_decl| mut_decl.decl, | 28358 | .mut_decl => |mut_decl| mut_decl.decl, |
| 28419 | else => unreachable, | 28359 | else => unreachable, |
| 28420 | }; | 28360 | }; |
| | 28361 | const is_mutable = ptr.addr == .mut_decl; |
| 28421 | const decl = mod.declPtr(decl_index); | 28362 | const decl = mod.declPtr(decl_index); |
| 28422 | const decl_tv = try decl.typedValue(); | 28363 | const decl_tv = try decl.typedValue(); |
| 28423 | if (decl.getVariable(mod) != null) return error.RuntimeLoad; | 28364 | if (decl.getVariable(mod) != null) return error.RuntimeLoad; |
| ... | @@ -28426,7 +28367,7 @@ fn beginComptimePtrLoad( | ... | @@ -28426,7 +28367,7 @@ fn beginComptimePtrLoad( |
| 28426 | break :blk ComptimePtrLoadKit{ | 28367 | break :blk ComptimePtrLoadKit{ |
| 28427 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 28368 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, |
| 28428 | .pointee = decl_tv, | 28369 | .pointee = decl_tv, |
| 28429 | .is_mutable = false, | 28370 | .is_mutable = is_mutable, |
| 28430 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | 28371 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, |
| 28431 | }; | 28372 | }; |
| 28432 | }, | 28373 | }, |
| ... | @@ -29411,7 +29352,7 @@ fn analyzeDeclVal( | ... | @@ -29411,7 +29352,7 @@ fn analyzeDeclVal( |
| 29411 | const decl_ref = try sema.analyzeDeclRefInner(decl_index, false); | 29352 | const decl_ref = try sema.analyzeDeclRefInner(decl_index, false); |
| 29412 | const result = try sema.analyzeLoad(block, src, decl_ref, src); | 29353 | const result = try sema.analyzeLoad(block, src, decl_ref, src); |
| 29413 | if (Air.refToIndex(result)) |index| { | 29354 | if (Air.refToIndex(result)) |index| { |
| 29414 | if (sema.air_instructions.items(.tag)[index] == .constant and !block.is_typeof) { | 29355 | if (sema.air_instructions.items(.tag)[index] == .interned and !block.is_typeof) { |
| 29415 | try sema.decl_val_table.put(sema.gpa, decl_index, result); | 29356 | try sema.decl_val_table.put(sema.gpa, decl_index, result); |
| 29416 | } | 29357 | } |
| 29417 | } | 29358 | } |
| ... | @@ -30049,8 +29990,8 @@ fn analyzeSlice( | ... | @@ -30049,8 +29990,8 @@ fn analyzeSlice( |
| 30049 | const end_int = end_val.getUnsignedInt(mod).?; | 29990 | const end_int = end_val.getUnsignedInt(mod).?; |
| 30050 | const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int); | 29991 | const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int); |
| 30051 | | 29992 | |
| 30052 | const elem_ptr = try ptr_val.elemPtr(new_ptr_ty, sentinel_index, sema.mod); | 29993 | const elem_ptr = try ptr_val.elemPtr(try sema.elemPtrType(new_ptr_ty, sentinel_index), sentinel_index, sema.mod); |
| 30053 | const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false); | 29994 | const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty); |
| 30054 | const actual_sentinel = switch (res) { | 29995 | const actual_sentinel = switch (res) { |
| 30055 | .runtime_load => break :sentinel_check, | 29996 | .runtime_load => break :sentinel_check, |
| 30056 | .val => |v| v, | 29997 | .val => |v| v, |
| ... | @@ -33421,35 +33362,24 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { | ... | @@ -33421,35 +33362,24 @@ fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { |
| 33421 | } | 33362 | } |
| 33422 | | 33363 | |
| 33423 | pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref { | 33364 | pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref { |
| | 33365 | const mod = sema.mod; |
| 33424 | const gpa = sema.gpa; | 33366 | const gpa = sema.gpa; |
| 33425 | if (val.ip_index != .none) { | 33367 | |
| 33426 | if (@enumToInt(val.toIntern()) < Air.ref_start_index) | 33368 | // This assertion can be removed when the `ty` parameter is removed from |
| 33427 | return @intToEnum(Air.Inst.Ref, @enumToInt(val.toIntern())); | 33369 | // this function thanks to the InternPool transition being complete. |
| 33428 | try sema.air_instructions.append(gpa, .{ | 33370 | if (std.debug.runtime_safety) { |
| 33429 | .tag = .interned, | 33371 | const val_ty = mod.intern_pool.typeOf(val.toIntern()); |
| 33430 | .data = .{ .interned = val.toIntern() }, | 33372 | if (ty.toIntern() != val_ty) { |
| 33431 | }); | 33373 | std.debug.panic("addConstant type mismatch: '{}' vs '{}'\n", .{ |
| 33432 | const result = Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); | 33374 | ty.fmt(mod), val_ty.toType().fmt(mod), |
| 33433 | // This assertion can be removed when the `ty` parameter is removed from | 33375 | }); |
| 33434 | // this function thanks to the InternPool transition being complete. | | |
| 33435 | if (std.debug.runtime_safety) { | | |
| 33436 | const val_ty = sema.typeOf(result); | | |
| 33437 | if (!Type.eql(val_ty, ty, sema.mod)) { | | |
| 33438 | std.debug.panic("addConstant type mismatch: '{}' vs '{}'\n", .{ | | |
| 33439 | ty.fmt(sema.mod), val_ty.fmt(sema.mod), | | |
| 33440 | }); | | |
| 33441 | } | | |
| 33442 | } | 33376 | } |
| 33443 | return result; | | |
| 33444 | } | 33377 | } |
| 33445 | const ty_inst = try sema.addType(ty); | 33378 | if (@enumToInt(val.toIntern()) < Air.ref_start_index) |
| 33446 | try sema.air_values.append(gpa, val); | 33379 | return @intToEnum(Air.Inst.Ref, @enumToInt(val.toIntern())); |
| 33447 | try sema.air_instructions.append(gpa, .{ | 33380 | try sema.air_instructions.append(gpa, .{ |
| 33448 | .tag = .constant, | 33381 | .tag = .interned, |
| 33449 | .data = .{ .ty_pl = .{ | 33382 | .data = .{ .interned = val.toIntern() }, |
| 33450 | .ty = ty_inst, | | |
| 33451 | .payload = @intCast(u32, sema.air_values.items.len - 1), | | |
| 33452 | } }, | | |
| 33453 | }); | 33383 | }); |
| 33454 | return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); | 33384 | return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1)); |
| 33455 | } | 33385 | } |
| ... | @@ -33606,7 +33536,7 @@ pub fn analyzeAddressSpace( | ... | @@ -33606,7 +33536,7 @@ pub fn analyzeAddressSpace( |
| 33606 | fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value { | 33536 | fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value { |
| 33607 | const mod = sema.mod; | 33537 | const mod = sema.mod; |
| 33608 | const load_ty = ptr_ty.childType(mod); | 33538 | const load_ty = ptr_ty.childType(mod); |
| 33609 | const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty, true); | 33539 | const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty); |
| 33610 | switch (res) { | 33540 | switch (res) { |
| 33611 | .runtime_load => return null, | 33541 | .runtime_load => return null, |
| 33612 | .val => |v| return v, | 33542 | .val => |v| return v, |
| ... | @@ -33632,7 +33562,7 @@ const DerefResult = union(enum) { | ... | @@ -33632,7 +33562,7 @@ const DerefResult = union(enum) { |
| 33632 | out_of_bounds: Type, | 33562 | out_of_bounds: Type, |
| 33633 | }; | 33563 | }; |
| 33634 | | 33564 | |
| 33635 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult { | 33565 | fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type) CompileError!DerefResult { |
| 33636 | const mod = sema.mod; | 33566 | const mod = sema.mod; |
| 33637 | const target = mod.getTarget(); | 33567 | const target = mod.getTarget(); |
| 33638 | const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) { | 33568 | const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) { |
| ... | @@ -33647,13 +33577,8 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value | ... | @@ -33647,13 +33577,8 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value |
| 33647 | if (coerce_in_mem_ok) { | 33577 | if (coerce_in_mem_ok) { |
| 33648 | // We have a Value that lines up in virtual memory exactly with what we want to load, | 33578 | // We have a Value that lines up in virtual memory exactly with what we want to load, |
| 33649 | // and it is in-memory coercible to load_ty. It may be returned without modifications. | 33579 | // and it is in-memory coercible to load_ty. It may be returned without modifications. |
| 33650 | if (deref.is_mutable and want_mutable) { | 33580 | // Move mutable decl values to the InternPool and assert other decls are already in the InternPool. |
| 33651 | // The decl whose value we are obtaining here may be overwritten with | 33581 | return .{ .val = (if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern()).toValue() }; |
| 33652 | // a different value upon further semantic analysis, which would | | |
| 33653 | // invalidate this memory. So we must copy here. | | |
| 33654 | return DerefResult{ .val = try tv.val.copy(sema.arena) }; | | |
| 33655 | } | | |
| 33656 | return DerefResult{ .val = tv.val }; | | |
| 33657 | } | 33582 | } |
| 33658 | } | 33583 | } |
| 33659 | | 33584 | |