| ... | @@ -4570,7 +4570,7 @@ fn zirOptionalPayloadPtr( | ... | @@ -4570,7 +4570,7 @@ fn zirOptionalPayloadPtr( |
| 4570 | }); | 4570 | }); |
| 4571 | | 4571 | |
| 4572 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { | 4572 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { |
| 4573 | if (try pointer_val.pointerDeref(sema.arena)) |val| { | 4573 | if (try sema.pointerDeref(block, src, pointer_val, optional_ptr_ty)) |val| { |
| 4574 | if (val.isNull()) { | 4574 | if (val.isNull()) { |
| 4575 | return sema.fail(block, src, "unable to unwrap null", .{}); | 4575 | return sema.fail(block, src, "unable to unwrap null", .{}); |
| 4576 | } | 4576 | } |
| ... | @@ -4689,7 +4689,7 @@ fn zirErrUnionPayloadPtr( | ... | @@ -4689,7 +4689,7 @@ fn zirErrUnionPayloadPtr( |
| 4689 | }); | 4689 | }); |
| 4690 | | 4690 | |
| 4691 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { | 4691 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 4692 | if (try pointer_val.pointerDeref(sema.arena)) |val| { | 4692 | if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| { |
| 4693 | if (val.getError()) |name| { | 4693 | if (val.getError()) |name| { |
| 4694 | return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); | 4694 | return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); |
| 4695 | } | 4695 | } |
| ... | @@ -4748,7 +4748,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE | ... | @@ -4748,7 +4748,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE |
| 4748 | const result_ty = operand_ty.elemType().errorUnionSet(); | 4748 | const result_ty = operand_ty.elemType().errorUnionSet(); |
| 4749 | | 4749 | |
| 4750 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { | 4750 | if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { |
| 4751 | if (try pointer_val.pointerDeref(sema.arena)) |val| { | 4751 | if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| { |
| 4752 | assert(val.getError() != null); | 4752 | assert(val.getError() != null); |
| 4753 | return sema.addConstant(result_ty, val); | 4753 | return sema.addConstant(result_ty, val); |
| 4754 | } | 4754 | } |
| ... | @@ -6912,8 +6912,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -6912,8 +6912,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 6912 | const final_len = lhs_info.len + rhs_info.len; | 6912 | const final_len = lhs_info.len + rhs_info.len; |
| 6913 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); | 6913 | const final_len_including_sent = final_len + @boolToInt(res_sent != null); |
| 6914 | const is_pointer = lhs_ty.zigTypeTag() == .Pointer; | 6914 | const is_pointer = lhs_ty.zigTypeTag() == .Pointer; |
| 6915 | const lhs_sub_val = if (is_pointer) (try lhs_val.pointerDeref(sema.arena)).? else lhs_val; | 6915 | const lhs_sub_val = if (is_pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; |
| 6916 | const rhs_sub_val = if (is_pointer) (try rhs_val.pointerDeref(sema.arena)).? else rhs_val; | 6916 | const rhs_sub_val = if (is_pointer) (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).? else rhs_val; |
| 6917 | var anon_decl = try block.startAnonDecl(); | 6917 | var anon_decl = try block.startAnonDecl(); |
| 6918 | defer anon_decl.deinit(); | 6918 | defer anon_decl.deinit(); |
| 6919 | | 6919 | |
| ... | @@ -6992,7 +6992,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -6992,7 +6992,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 6992 | const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null); | 6992 | const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null); |
| 6993 | | 6993 | |
| 6994 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { | 6994 | if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { |
| 6995 | const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try lhs_val.pointerDeref(sema.arena)).? else lhs_val; | 6995 | const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).? else lhs_val; |
| 6996 | | 6996 | |
| 6997 | var anon_decl = try block.startAnonDecl(); | 6997 | var anon_decl = try block.startAnonDecl(); |
| 6998 | defer anon_decl.deinit(); | 6998 | defer anon_decl.deinit(); |
| ... | @@ -10092,7 +10092,8 @@ fn zirCmpxchg( | ... | @@ -10092,7 +10092,8 @@ fn zirCmpxchg( |
| 10092 | const failure_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg5 = inst_data.src_node }; | 10092 | const failure_order_src: LazySrcLoc = .{ .node_offset_builtin_call_arg5 = inst_data.src_node }; |
| 10093 | // zig fmt: on | 10093 | // zig fmt: on |
| 10094 | const ptr = sema.resolveInst(extra.ptr); | 10094 | const ptr = sema.resolveInst(extra.ptr); |
| 10095 | const elem_ty = sema.typeOf(ptr).elemType(); | 10095 | const ptr_ty = sema.typeOf(ptr); |
| | 10096 | const elem_ty = ptr_ty.elemType(); |
| 10096 | try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); | 10097 | try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); |
| 10097 | if (elem_ty.zigTypeTag() == .Float) { | 10098 | if (elem_ty.zigTypeTag() == .Float) { |
| 10098 | return sema.fail( | 10099 | return sema.fail( |
| ... | @@ -10135,7 +10136,7 @@ fn zirCmpxchg( | ... | @@ -10135,7 +10136,7 @@ fn zirCmpxchg( |
| 10135 | // to become undef as well | 10136 | // to become undef as well |
| 10136 | return sema.addConstUndef(result_ty); | 10137 | return sema.addConstUndef(result_ty); |
| 10137 | } | 10138 | } |
| 10138 | const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src; | 10139 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; |
| 10139 | const result_val = if (stored_val.eql(expected_val, elem_ty)) blk: { | 10140 | const result_val = if (stored_val.eql(expected_val, elem_ty)) blk: { |
| 10140 | try sema.storePtr(block, src, ptr, new_value); | 10141 | try sema.storePtr(block, src, ptr, new_value); |
| 10141 | break :blk Value.@"null"; | 10142 | break :blk Value.@"null"; |
| ... | @@ -10197,7 +10198,8 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -10197,7 +10198,8 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10197 | const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; | 10198 | const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; |
| 10198 | // zig fmt: on | 10199 | // zig fmt: on |
| 10199 | const ptr = sema.resolveInst(extra.lhs); | 10200 | const ptr = sema.resolveInst(extra.lhs); |
| 10200 | const elem_ty = sema.typeOf(ptr).elemType(); | 10201 | const ptr_ty = sema.typeOf(ptr); |
| | 10202 | const elem_ty = ptr_ty.elemType(); |
| 10201 | try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); | 10203 | try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); |
| 10202 | const order = try sema.resolveAtomicOrder(block, order_src, extra.rhs); | 10204 | const order = try sema.resolveAtomicOrder(block, order_src, extra.rhs); |
| 10203 | | 10205 | |
| ... | @@ -10218,7 +10220,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -10218,7 +10220,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10218 | } | 10220 | } |
| 10219 | | 10221 | |
| 10220 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 10222 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 10221 | if (try ptr_val.pointerDeref(sema.arena)) |elem_val| { | 10223 | if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) |elem_val| { |
| 10222 | return sema.addConstant(elem_ty, elem_val); | 10224 | return sema.addConstant(elem_ty, elem_val); |
| 10223 | } | 10225 | } |
| 10224 | } | 10226 | } |
| ... | @@ -10245,7 +10247,8 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -10245,7 +10247,8 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10245 | const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg4 = inst_data.src_node }; | 10247 | const order_src : LazySrcLoc = .{ .node_offset_builtin_call_arg4 = inst_data.src_node }; |
| 10246 | // zig fmt: on | 10248 | // zig fmt: on |
| 10247 | const ptr = sema.resolveInst(extra.ptr); | 10249 | const ptr = sema.resolveInst(extra.ptr); |
| 10248 | const operand_ty = sema.typeOf(ptr).elemType(); | 10250 | const ptr_ty = sema.typeOf(ptr); |
| | 10251 | const operand_ty = ptr_ty.elemType(); |
| 10249 | try sema.checkAtomicOperandType(block, operand_ty_src, operand_ty); | 10252 | try sema.checkAtomicOperandType(block, operand_ty_src, operand_ty); |
| 10250 | const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); | 10253 | const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation); |
| 10251 | | 10254 | |
| ... | @@ -10282,7 +10285,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -10282,7 +10285,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 10282 | }; | 10285 | }; |
| 10283 | if (ptr_val.isComptimeMutablePtr()) { | 10286 | if (ptr_val.isComptimeMutablePtr()) { |
| 10284 | const target = sema.mod.getTarget(); | 10287 | const target = sema.mod.getTarget(); |
| 10285 | const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src; | 10288 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; |
| 10286 | const new_val = switch (op) { | 10289 | const new_val = switch (op) { |
| 10287 | // zig fmt: off | 10290 | // zig fmt: off |
| 10288 | .Xchg => operand_val, | 10291 | .Xchg => operand_val, |
| ... | @@ -11785,7 +11788,7 @@ fn elemVal( | ... | @@ -11785,7 +11788,7 @@ fn elemVal( |
| 11785 | const ptr_val = maybe_ptr_val orelse break :rs array_src; | 11788 | const ptr_val = maybe_ptr_val orelse break :rs array_src; |
| 11786 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 11789 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 11787 | const index = @intCast(usize, index_val.toUnsignedInt()); | 11790 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| 11788 | const maybe_array_val = try ptr_val.pointerDeref(sema.arena); | 11791 | const maybe_array_val = try sema.pointerDeref(block, array_src, ptr_val, array_ty); |
| 11789 | const array_val = maybe_array_val orelse break :rs array_src; | 11792 | const array_val = maybe_array_val orelse break :rs array_src; |
| 11790 | const elem_val = try array_val.elemValue(sema.arena, index); | 11793 | const elem_val = try array_val.elemValue(sema.arena, index); |
| 11791 | return sema.addConstant(array_ty.elemType2(), elem_val); | 11794 | return sema.addConstant(array_ty.elemType2(), elem_val); |
| ... | @@ -11887,6 +11890,8 @@ fn coerce( | ... | @@ -11887,6 +11890,8 @@ fn coerce( |
| 11887 | assert(inst_ty.zigTypeTag() != .Undefined); | 11890 | assert(inst_ty.zigTypeTag() != .Undefined); |
| 11888 | | 11891 | |
| 11889 | // comptime known number to other number | 11892 | // comptime known number to other number |
| | 11893 | // TODO why is this a separate function? should just be flattened into the |
| | 11894 | // switch expression below. |
| 11890 | if (try sema.coerceNum(block, dest_ty, inst, inst_src)) |some| | 11895 | if (try sema.coerceNum(block, dest_ty, inst, inst_src)) |some| |
| 11891 | return some; | 11896 | return some; |
| 11892 | | 11897 | |
| ... | @@ -12514,6 +12519,122 @@ fn beginComptimePtrMutation( | ... | @@ -12514,6 +12519,122 @@ fn beginComptimePtrMutation( |
| 12514 | } | 12519 | } |
| 12515 | } | 12520 | } |
| 12516 | | 12521 | |
| | 12522 | const ComptimePtrLoadKit = struct { |
| | 12523 | /// The Value of the Decl that owns this memory. |
| | 12524 | root_val: Value, |
| | 12525 | /// Parent Value. |
| | 12526 | val: Value, |
| | 12527 | /// The Type of the parent Value. |
| | 12528 | ty: Type, |
| | 12529 | /// The starting byte offset of `val` from `root_val`. |
| | 12530 | byte_offset: usize, |
| | 12531 | /// Whether the `root_val` could be mutated by further |
| | 12532 | /// semantic analysis and a copy must be performed. |
| | 12533 | is_mutable: bool, |
| | 12534 | }; |
| | 12535 | |
| | 12536 | const ComptimePtrLoadError = CompileError || error{ |
| | 12537 | RuntimeLoad, |
| | 12538 | }; |
| | 12539 | |
| | 12540 | fn beginComptimePtrLoad( |
| | 12541 | sema: *Sema, |
| | 12542 | block: *Block, |
| | 12543 | src: LazySrcLoc, |
| | 12544 | ptr_val: Value, |
| | 12545 | ) ComptimePtrLoadError!ComptimePtrLoadKit { |
| | 12546 | const target = sema.mod.getTarget(); |
| | 12547 | switch (ptr_val.tag()) { |
| | 12548 | .decl_ref => { |
| | 12549 | const decl = ptr_val.castTag(.decl_ref).?.data; |
| | 12550 | const decl_val = try decl.value(); |
| | 12551 | if (decl_val.tag() == .variable) return error.RuntimeLoad; |
| | 12552 | return ComptimePtrLoadKit{ |
| | 12553 | .root_val = decl_val, |
| | 12554 | .val = decl_val, |
| | 12555 | .ty = decl.ty, |
| | 12556 | .byte_offset = 0, |
| | 12557 | .is_mutable = false, |
| | 12558 | }; |
| | 12559 | }, |
| | 12560 | .decl_ref_mut => { |
| | 12561 | const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl; |
| | 12562 | const decl_val = try decl.value(); |
| | 12563 | if (decl_val.tag() == .variable) return error.RuntimeLoad; |
| | 12564 | return ComptimePtrLoadKit{ |
| | 12565 | .root_val = decl_val, |
| | 12566 | .val = decl_val, |
| | 12567 | .ty = decl.ty, |
| | 12568 | .byte_offset = 0, |
| | 12569 | .is_mutable = true, |
| | 12570 | }; |
| | 12571 | }, |
| | 12572 | .elem_ptr => { |
| | 12573 | const elem_ptr = ptr_val.castTag(.elem_ptr).?.data; |
| | 12574 | const parent = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr); |
| | 12575 | const elem_ty = parent.ty.childType(); |
| | 12576 | const elem_size = elem_ty.abiSize(target); |
| | 12577 | return ComptimePtrLoadKit{ |
| | 12578 | .root_val = parent.root_val, |
| | 12579 | .val = try parent.val.elemValue(sema.arena, elem_ptr.index), |
| | 12580 | .ty = elem_ty, |
| | 12581 | .byte_offset = parent.byte_offset + elem_size * elem_ptr.index, |
| | 12582 | .is_mutable = parent.is_mutable, |
| | 12583 | }; |
| | 12584 | }, |
| | 12585 | .field_ptr => { |
| | 12586 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| | 12587 | const parent = try beginComptimePtrLoad(sema, block, src, field_ptr.container_ptr); |
| | 12588 | const field_index = @intCast(u32, field_ptr.field_index); |
| | 12589 | try sema.resolveTypeLayout(block, src, parent.ty); |
| | 12590 | const field_offset = parent.ty.structFieldOffset(field_index, target); |
| | 12591 | return ComptimePtrLoadKit{ |
| | 12592 | .root_val = parent.root_val, |
| | 12593 | .val = try parent.val.fieldValue(sema.arena, field_index), |
| | 12594 | .ty = parent.ty.structFieldType(field_index), |
| | 12595 | .byte_offset = parent.byte_offset + field_offset, |
| | 12596 | .is_mutable = parent.is_mutable, |
| | 12597 | }; |
| | 12598 | }, |
| | 12599 | .eu_payload_ptr => { |
| | 12600 | const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; |
| | 12601 | const parent = try beginComptimePtrLoad(sema, block, src, err_union_ptr); |
| | 12602 | return ComptimePtrLoadKit{ |
| | 12603 | .root_val = parent.root_val, |
| | 12604 | .val = parent.val.castTag(.eu_payload).?.data, |
| | 12605 | .ty = parent.ty.errorUnionPayload(), |
| | 12606 | .byte_offset = undefined, |
| | 12607 | .is_mutable = parent.is_mutable, |
| | 12608 | }; |
| | 12609 | }, |
| | 12610 | .opt_payload_ptr => { |
| | 12611 | const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; |
| | 12612 | const parent = try beginComptimePtrLoad(sema, block, src, opt_ptr); |
| | 12613 | var buf: Type.Payload.ElemType = undefined; |
| | 12614 | return ComptimePtrLoadKit{ |
| | 12615 | .root_val = parent.root_val, |
| | 12616 | .val = parent.val.castTag(.opt_payload).?.data, |
| | 12617 | .ty = parent.ty.optionalChild(&buf), |
| | 12618 | .byte_offset = undefined, |
| | 12619 | .is_mutable = parent.is_mutable, |
| | 12620 | }; |
| | 12621 | }, |
| | 12622 | |
| | 12623 | .zero, |
| | 12624 | .one, |
| | 12625 | .int_u64, |
| | 12626 | .int_i64, |
| | 12627 | .int_big_positive, |
| | 12628 | .int_big_negative, |
| | 12629 | .variable, |
| | 12630 | .extern_fn, |
| | 12631 | .function, |
| | 12632 | => return error.RuntimeLoad, |
| | 12633 | |
| | 12634 | else => unreachable, |
| | 12635 | } |
| | 12636 | } |
| | 12637 | |
| 12517 | fn bitCast( | 12638 | fn bitCast( |
| 12518 | sema: *Sema, | 12639 | sema: *Sema, |
| 12519 | block: *Block, | 12640 | block: *Block, |
| ... | @@ -12819,7 +12940,7 @@ fn analyzeLoad( | ... | @@ -12819,7 +12940,7 @@ fn analyzeLoad( |
| 12819 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty}), | 12940 | else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty}), |
| 12820 | }; | 12941 | }; |
| 12821 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { | 12942 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 12822 | if (try ptr_val.pointerDeref(sema.arena)) |elem_val| { | 12943 | if (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) |elem_val| { |
| 12823 | return sema.addConstant(elem_ty, elem_val); | 12944 | return sema.addConstant(elem_ty, elem_val); |
| 12824 | } | 12945 | } |
| 12825 | } | 12946 | } |
| ... | @@ -14539,3 +14660,45 @@ pub fn analyzeAddrspace( | ... | @@ -14539,3 +14660,45 @@ pub fn analyzeAddrspace( |
| 14539 | | 14660 | |
| 14540 | return address_space; | 14661 | return address_space; |
| 14541 | } | 14662 | } |
| | 14663 | |
| | 14664 | /// Asserts the value is a pointer and dereferences it. |
| | 14665 | /// Returns `null` if the pointer contents cannot be loaded at comptime. |
| | 14666 | fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value { |
| | 14667 | const target = sema.mod.getTarget(); |
| | 14668 | const load_ty = ptr_ty.childType(); |
| | 14669 | const parent = sema.beginComptimePtrLoad(block, src, ptr_val) catch |err| switch (err) { |
| | 14670 | error.RuntimeLoad => return null, |
| | 14671 | else => |e| return e, |
| | 14672 | }; |
| | 14673 | // We have a Value that lines up in virtual memory exactly with what we want to load. |
| | 14674 | // If the Type is in-memory coercable to `load_ty`, it may be returned without modifications. |
| | 14675 | const coerce_in_mem_ok = |
| | 14676 | coerceInMemoryAllowed(load_ty, parent.ty, false, target) == .ok or |
| | 14677 | coerceInMemoryAllowed(parent.ty, load_ty, false, target) == .ok; |
| | 14678 | if (coerce_in_mem_ok) { |
| | 14679 | if (parent.is_mutable) { |
| | 14680 | // The decl whose value we are obtaining here may be overwritten with |
| | 14681 | // a different value upon further semantic analysis, which would |
| | 14682 | // invalidate this memory. So we must copy here. |
| | 14683 | return try parent.val.copy(sema.arena); |
| | 14684 | } |
| | 14685 | return parent.val; |
| | 14686 | } |
| | 14687 | |
| | 14688 | // The type is not in-memory coercable, so it must be bitcasted according |
| | 14689 | // to the pointer type we are performing the load through. |
| | 14690 | |
| | 14691 | // TODO emit a compile error if the types are not allowed to be bitcasted |
| | 14692 | |
| | 14693 | if (parent.ty.abiSize(target) >= load_ty.abiSize(target)) { |
| | 14694 | // The Type it is stored as in the compiler has an ABI size greater or equal to |
| | 14695 | // the ABI size of `load_ty`. We may perform the bitcast based on |
| | 14696 | // `parent.val` alone (more efficient). |
| | 14697 | return try parent.val.bitCast(parent.ty, load_ty, target, sema.gpa, sema.arena); |
| | 14698 | } |
| | 14699 | |
| | 14700 | // The Type it is stored as in the compiler has an ABI size less than the ABI size |
| | 14701 | // of `load_ty`. The bitcast must be performed based on the `parent.root_val` |
| | 14702 | // and reinterpreted starting at `parent.byte_offset`. |
| | 14703 | return sema.fail(block, src, "TODO: implement bitcast with index offset", .{}); |
| | 14704 | } |