| ... | @@ -351,6 +351,24 @@ pub const Block = struct { | ... | @@ -351,6 +351,24 @@ pub const Block = struct { |
| 351 | }); | 351 | }); |
| 352 | } | 352 | } |
| 353 | | 353 | |
| | 354 | pub fn addPtrElemPtr( |
| | 355 | block: *Block, |
| | 356 | array_ptr: Air.Inst.Ref, |
| | 357 | elem_index: Air.Inst.Ref, |
| | 358 | elem_ptr_ty: Type, |
| | 359 | ) !Air.Inst.Ref { |
| | 360 | return block.addInst(.{ |
| | 361 | .tag = .ptr_elem_ptr, |
| | 362 | .data = .{ .ty_pl = .{ |
| | 363 | .ty = try block.sema.addType(elem_ptr_ty), |
| | 364 | .payload = try block.sema.addExtra(Air.Bin{ |
| | 365 | .lhs = array_ptr, |
| | 366 | .rhs = elem_index, |
| | 367 | }), |
| | 368 | } }, |
| | 369 | }); |
| | 370 | } |
| | 371 | |
| 354 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { | 372 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { |
| 355 | return Air.indexToRef(try block.addInstAsIndex(inst)); | 373 | return Air.indexToRef(try block.addInstAsIndex(inst)); |
| 356 | } | 374 | } |
| ... | @@ -11500,10 +11518,10 @@ fn elemPtr( | ... | @@ -11500,10 +11518,10 @@ fn elemPtr( |
| 11500 | switch (array_ty.zigTypeTag()) { | 11518 | switch (array_ty.zigTypeTag()) { |
| 11501 | .Pointer => { | 11519 | .Pointer => { |
| 11502 | // In all below cases, we have to deref the ptr operand to get the actual array pointer. | 11520 | // In all below cases, we have to deref the ptr operand to get the actual array pointer. |
| 11503 | const array = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src); | 11521 | const array = try sema.analyzeLoad(block, array_ptr_src, array_ptr, array_ptr_src); |
| | 11522 | const result_ty = try array_ty.elemPtrType(sema.arena); |
| 11504 | switch (array_ty.ptrSize()) { | 11523 | switch (array_ty.ptrSize()) { |
| 11505 | .Slice => { | 11524 | .Slice => { |
| 11506 | const result_ty = try array_ty.elemPtrType(sema.arena); | | |
| 11507 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array); | 11525 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array); |
| 11508 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | 11526 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11509 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { | 11527 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { |
| ... | @@ -11516,14 +11534,28 @@ fn elemPtr( | ... | @@ -11516,14 +11534,28 @@ fn elemPtr( |
| 11516 | try sema.requireRuntimeBlock(block, runtime_src); | 11534 | try sema.requireRuntimeBlock(block, runtime_src); |
| 11517 | return block.addSliceElemPtr(array, elem_index, result_ty); | 11535 | return block.addSliceElemPtr(array, elem_index, result_ty); |
| 11518 | }, | 11536 | }, |
| 11519 | .Many, .C => return sema.fail(block, src, "TODO implement Sema for elemPtr for many/c pointer", .{}), | 11537 | .Many, .C => { |
| | 11538 | const maybe_ptr_val = try sema.resolveDefinedValue(block, array_ptr_src, array); |
| | 11539 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| | 11540 | |
| | 11541 | const runtime_src = rs: { |
| | 11542 | const ptr_val = maybe_ptr_val orelse break :rs array_ptr_src; |
| | 11543 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| | 11544 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| | 11545 | const elem_ptr = try ptr_val.elemPtr(sema.arena, index); |
| | 11546 | return sema.addConstant(result_ty, elem_ptr); |
| | 11547 | }; |
| | 11548 | |
| | 11549 | try sema.requireRuntimeBlock(block, runtime_src); |
| | 11550 | return block.addPtrElemPtr(array, elem_index, result_ty); |
| | 11551 | }, |
| 11520 | .One => { | 11552 | .One => { |
| 11521 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable | 11553 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable |
| 11522 | return sema.elemPtrArray(block, src, array, elem_index, elem_index_src); | 11554 | return sema.elemPtrArray(block, array_ptr_src, array, elem_index, elem_index_src); |
| 11523 | }, | 11555 | }, |
| 11524 | } | 11556 | } |
| 11525 | }, | 11557 | }, |
| 11526 | .Array => return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src), | 11558 | .Array => return sema.elemPtrArray(block, array_ptr_src, array_ptr, elem_index, elem_index_src), |
| 11527 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemPtr for vector", .{}), | 11559 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemPtr for vector", .{}), |
| 11528 | else => unreachable, | 11560 | else => unreachable, |
| 11529 | } | 11561 | } |
| ... | @@ -11560,21 +11592,30 @@ fn elemVal( | ... | @@ -11560,21 +11592,30 @@ fn elemVal( |
| 11560 | return block.addBinOp(.slice_elem_val, array, elem_index); | 11592 | return block.addBinOp(.slice_elem_val, array, elem_index); |
| 11561 | }, | 11593 | }, |
| 11562 | .Many, .C => { | 11594 | .Many, .C => { |
| 11563 | if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| { | 11595 | const maybe_ptr_val = try sema.resolveDefinedValue(block, array_src, array); |
| 11564 | _ = ptr_val; | 11596 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11565 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); | 11597 | |
| 11566 | } | 11598 | const runtime_src = rs: { |
| 11567 | try sema.requireRuntimeBlock(block, src); | 11599 | const ptr_val = maybe_ptr_val orelse break :rs array_src; |
| | 11600 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| | 11601 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| | 11602 | const maybe_array_val = try ptr_val.pointerDeref(sema.arena); |
| | 11603 | const array_val = maybe_array_val orelse break :rs array_src; |
| | 11604 | const elem_val = try array_val.elemValue(sema.arena, index); |
| | 11605 | return sema.addConstant(array_ty.elemType2(), elem_val); |
| | 11606 | }; |
| | 11607 | |
| | 11608 | try sema.requireRuntimeBlock(block, runtime_src); |
| 11568 | return block.addBinOp(.ptr_elem_val, array, elem_index); | 11609 | return block.addBinOp(.ptr_elem_val, array, elem_index); |
| 11569 | }, | 11610 | }, |
| 11570 | .One => { | 11611 | .One => { |
| 11571 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable | 11612 | assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable |
| 11572 | const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); | 11613 | const elem_ptr = try sema.elemPtr(block, array_src, array, elem_index, elem_index_src); |
| 11573 | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); | 11614 | return sema.analyzeLoad(block, array_src, elem_ptr, elem_index_src); |
| 11574 | }, | 11615 | }, |
| 11575 | }, | 11616 | }, |
| 11576 | .Array => { | 11617 | .Array => { |
| 11577 | if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| { | 11618 | if (try sema.resolveMaybeUndefVal(block, array_src, array)) |array_val| { |
| 11578 | const elem_ty = array_ty.childType(); | 11619 | const elem_ty = array_ty.childType(); |
| 11579 | if (array_val.isUndef()) return sema.addConstUndef(elem_ty); | 11620 | if (array_val.isUndef()) return sema.addConstUndef(elem_ty); |
| 11580 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | 11621 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| ... | @@ -11584,10 +11625,10 @@ fn elemVal( | ... | @@ -11584,10 +11625,10 @@ fn elemVal( |
| 11584 | return sema.addConstant(elem_ty, elem_val); | 11625 | return sema.addConstant(elem_ty, elem_val); |
| 11585 | } | 11626 | } |
| 11586 | } | 11627 | } |
| 11587 | try sema.requireRuntimeBlock(block, src); | 11628 | try sema.requireRuntimeBlock(block, array_src); |
| 11588 | return block.addBinOp(.array_elem_val, array, elem_index); | 11629 | return block.addBinOp(.array_elem_val, array, elem_index); |
| 11589 | }, | 11630 | }, |
| 11590 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}), | 11631 | .Vector => return sema.fail(block, array_src, "TODO implement Sema for elemVal for vector", .{}), |
| 11591 | else => unreachable, | 11632 | else => unreachable, |
| 11592 | } | 11633 | } |
| 11593 | } | 11634 | } |
| ... | @@ -11615,16 +11656,7 @@ fn elemPtrArray( | ... | @@ -11615,16 +11656,7 @@ fn elemPtrArray( |
| 11615 | } | 11656 | } |
| 11616 | // TODO safety check for array bounds | 11657 | // TODO safety check for array bounds |
| 11617 | try sema.requireRuntimeBlock(block, src); | 11658 | try sema.requireRuntimeBlock(block, src); |
| 11618 | return block.addInst(.{ | 11659 | return block.addPtrElemPtr(array_ptr, elem_index, result_ty); |
| 11619 | .tag = .ptr_elem_ptr, | | |
| 11620 | .data = .{ .ty_pl = .{ | | |
| 11621 | .ty = try sema.addType(result_ty), | | |
| 11622 | .payload = try sema.addExtra(Air.Bin{ | | |
| 11623 | .lhs = array_ptr, | | |
| 11624 | .rhs = elem_index, | | |
| 11625 | }), | | |
| 11626 | } }, | | |
| 11627 | }); | | |
| 11628 | } | 11660 | } |
| 11629 | | 11661 | |
| 11630 | fn coerce( | 11662 | fn coerce( |