| ... | ... | @@ -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 | 372 | pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { |
| 355 | 373 | return Air.indexToRef(try block.addInstAsIndex(inst)); |
| 356 | 374 | } |
| ... | ... | @@ -11500,10 +11518,10 @@ fn elemPtr( |
| 11500 | 11518 | switch (array_ty.zigTypeTag()) { |
| 11501 | 11519 | .Pointer => { |
| 11502 | 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 | 11523 | switch (array_ty.ptrSize()) { |
| 11505 | 11524 | .Slice => { |
| 11506 | | const result_ty = try array_ty.elemPtrType(sema.arena); |
| 11507 | 11525 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array); |
| 11508 | 11526 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11509 | 11527 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { |
| ... | ... | @@ -11516,14 +11534,28 @@ fn elemPtr( |
| 11516 | 11534 | try sema.requireRuntimeBlock(block, runtime_src); |
| 11517 | 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 | 11552 | .One => { |
| 11521 | 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 | 11559 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemPtr for vector", .{}), |
| 11528 | 11560 | else => unreachable, |
| 11529 | 11561 | } |
| ... | ... | @@ -11560,21 +11592,30 @@ fn elemVal( |
| 11560 | 11592 | return block.addBinOp(.slice_elem_val, array, elem_index); |
| 11561 | 11593 | }, |
| 11562 | 11594 | .Many, .C => { |
| 11563 | | if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| { |
| 11564 | | _ = ptr_val; |
| 11565 | | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); |
| 11566 | | } |
| 11567 | | try sema.requireRuntimeBlock(block, src); |
| 11595 | const maybe_ptr_val = try sema.resolveDefinedValue(block, array_src, array); |
| 11596 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11597 | |
| 11598 | const runtime_src = rs: { |
| 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 | 11609 | return block.addBinOp(.ptr_elem_val, array, elem_index); |
| 11569 | 11610 | }, |
| 11570 | 11611 | .One => { |
| 11571 | 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); |
| 11573 | | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); |
| 11613 | const elem_ptr = try sema.elemPtr(block, array_src, array, elem_index, elem_index_src); |
| 11614 | return sema.analyzeLoad(block, array_src, elem_ptr, elem_index_src); |
| 11574 | 11615 | }, |
| 11575 | 11616 | }, |
| 11576 | 11617 | .Array => { |
| 11577 | | if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| { |
| 11618 | if (try sema.resolveMaybeUndefVal(block, array_src, array)) |array_val| { |
| 11578 | 11619 | const elem_ty = array_ty.childType(); |
| 11579 | 11620 | if (array_val.isUndef()) return sema.addConstUndef(elem_ty); |
| 11580 | 11621 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| ... | ... | @@ -11584,10 +11625,10 @@ fn elemVal( |
| 11584 | 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 | 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 | 11632 | else => unreachable, |
| 11592 | 11633 | } |
| 11593 | 11634 | } |
| ... | ... | @@ -11615,16 +11656,7 @@ fn elemPtrArray( |
| 11615 | 11656 | } |
| 11616 | 11657 | // TODO safety check for array bounds |
| 11617 | 11658 | try sema.requireRuntimeBlock(block, src); |
| 11618 | | return block.addInst(.{ |
| 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 | | }); |
| 11659 | return block.addPtrElemPtr(array_ptr, elem_index, result_ty); |
| 11628 | 11660 | } |
| 11629 | 11661 | |
| 11630 | 11662 | fn coerce( |