| ... | @@ -11494,117 +11494,62 @@ fn elemVal( | ... | @@ -11494,117 +11494,62 @@ fn elemVal( |
| 11494 | sema: *Sema, | 11494 | sema: *Sema, |
| 11495 | block: *Block, | 11495 | block: *Block, |
| 11496 | src: LazySrcLoc, | 11496 | src: LazySrcLoc, |
| 11497 | array_maybe_ptr: Air.Inst.Ref, | 11497 | array: Air.Inst.Ref, |
| 11498 | elem_index: Air.Inst.Ref, | 11498 | elem_index: Air.Inst.Ref, |
| 11499 | elem_index_src: LazySrcLoc, | 11499 | elem_index_src: LazySrcLoc, |
| 11500 | ) CompileError!Air.Inst.Ref { | 11500 | ) CompileError!Air.Inst.Ref { |
| 11501 | const array_ptr_src = src; // TODO better source location | 11501 | const array_src = src; // TODO better source location |
| 11502 | const maybe_ptr_ty = sema.typeOf(array_maybe_ptr); | 11502 | const array_ty = sema.typeOf(array); |
| 11503 | switch (maybe_ptr_ty.zigTypeTag()) { | 11503 | |
| 11504 | .Pointer => switch (maybe_ptr_ty.ptrSize()) { | 11504 | if (!array_ty.isIndexable()) { |
| | 11505 | return sema.fail(block, src, "array access of non-indexable type '{}'", .{array_ty}); |
| | 11506 | } |
| | 11507 | |
| | 11508 | switch (array_ty.zigTypeTag()) { |
| | 11509 | .Pointer => switch (array_ty.ptrSize()) { |
| 11505 | .Slice => { | 11510 | .Slice => { |
| 11506 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array_maybe_ptr); | 11511 | const maybe_slice_val = try sema.resolveDefinedValue(block, array_src, array); |
| 11507 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | 11512 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11508 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { | 11513 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { |
| 11509 | const index_val = maybe_index_val orelse break :rs elem_index_src; | 11514 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 11510 | const index = @intCast(usize, index_val.toUnsignedInt()); | 11515 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| 11511 | const elem_val = try slice_val.elemValue(sema.arena, index); | 11516 | const elem_val = try slice_val.elemValue(sema.arena, index); |
| 11512 | return sema.addConstant(maybe_ptr_ty.elemType2(), elem_val); | 11517 | return sema.addConstant(array_ty.elemType2(), elem_val); |
| 11513 | } else array_ptr_src; | 11518 | } else array_src; |
| 11514 | | 11519 | |
| 11515 | try sema.requireRuntimeBlock(block, runtime_src); | 11520 | try sema.requireRuntimeBlock(block, runtime_src); |
| 11516 | return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index); | 11521 | return block.addBinOp(.slice_elem_val, array, elem_index); |
| 11517 | }, | 11522 | }, |
| 11518 | .Many, .C => { | 11523 | .Many, .C => { |
| 11519 | if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |ptr_val| { | 11524 | if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| { |
| 11520 | _ = ptr_val; | 11525 | _ = ptr_val; |
| 11521 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); | 11526 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); |
| 11522 | } | 11527 | } |
| 11523 | try sema.requireRuntimeBlock(block, src); | 11528 | try sema.requireRuntimeBlock(block, src); |
| 11524 | return block.addBinOp(.ptr_elem_val, array_maybe_ptr, elem_index); | 11529 | return block.addBinOp(.ptr_elem_val, array, elem_index); |
| 11525 | }, | 11530 | }, |
| 11526 | .One => { | 11531 | .One => { |
| 11527 | const indexable_ty = maybe_ptr_ty.childType(); | 11532 | assert(array_ty.childType().zigTypeTag() == .Array); |
| 11528 | switch (indexable_ty.zigTypeTag()) { | 11533 | const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); |
| 11529 | .Pointer => switch (indexable_ty.ptrSize()) { | 11534 | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); |
| 11530 | .Slice => { | | |
| 11531 | // We have a pointer to a slice and we want an element value. | | |
| 11532 | if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) { | | |
| 11533 | const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); | | |
| 11534 | if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| { | | |
| 11535 | _ = slice_val; | | |
| 11536 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{}); | | |
| 11537 | } | | |
| 11538 | try sema.requireRuntimeBlock(block, src); | | |
| 11539 | return block.addBinOp(.slice_elem_val, slice, elem_index); | | |
| 11540 | } | | |
| 11541 | try sema.requireRuntimeBlock(block, src); | | |
| 11542 | return block.addBinOp(.ptr_slice_elem_val, array_maybe_ptr, elem_index); | | |
| 11543 | }, | | |
| 11544 | .Many, .C => { | | |
| 11545 | // We have a pointer to a pointer and we want an element value. | | |
| 11546 | if (try sema.isComptimeKnown(block, src, array_maybe_ptr)) { | | |
| 11547 | const ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); | | |
| 11548 | if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| { | | |
| 11549 | _ = ptr_val; | | |
| 11550 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); | | |
| 11551 | } | | |
| 11552 | try sema.requireRuntimeBlock(block, src); | | |
| 11553 | return block.addBinOp(.ptr_elem_val, ptr, elem_index); | | |
| 11554 | } | | |
| 11555 | try sema.requireRuntimeBlock(block, src); | | |
| 11556 | return block.addBinOp(.ptr_ptr_elem_val, array_maybe_ptr, elem_index); | | |
| 11557 | }, | | |
| 11558 | .One => { | | |
| 11559 | const array_ty = indexable_ty.childType(); | | |
| 11560 | if (array_ty.zigTypeTag() == .Array) { | | |
| 11561 | // We have a double pointer to an array, and we want an element | | |
| 11562 | // value. This can happen with this code for example: | | |
| 11563 | // var a: *[1]u8 = undefined; _ = a[0]; | | |
| 11564 | const array_ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); | | |
| 11565 | const ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); | | |
| 11566 | return sema.analyzeLoad(block, src, ptr, elem_index_src); | | |
| 11567 | } else return sema.fail( | | |
| 11568 | block, | | |
| 11569 | array_ptr_src, | | |
| 11570 | "expected pointer, found '{}'", | | |
| 11571 | .{array_ty}, | | |
| 11572 | ); | | |
| 11573 | }, | | |
| 11574 | }, | | |
| 11575 | .Array => { | | |
| 11576 | const ptr = try sema.elemPtr(block, src, array_maybe_ptr, elem_index, elem_index_src); | | |
| 11577 | return sema.analyzeLoad(block, src, ptr, elem_index_src); | | |
| 11578 | }, | | |
| 11579 | else => return sema.fail( | | |
| 11580 | block, | | |
| 11581 | array_ptr_src, | | |
| 11582 | "expected pointer, found '{}'", | | |
| 11583 | .{indexable_ty}, | | |
| 11584 | ), | | |
| 11585 | } | | |
| 11586 | }, | 11535 | }, |
| 11587 | }, | 11536 | }, |
| 11588 | .Array => { | 11537 | .Array => { |
| 11589 | if (try sema.resolveMaybeUndefVal(block, src, array_maybe_ptr)) |array_val| { | 11538 | if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| { |
| 11590 | const elem_ty = maybe_ptr_ty.childType(); | 11539 | const elem_ty = array_ty.childType(); |
| 11591 | const opt_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); | | |
| 11592 | if (array_val.isUndef()) return sema.addConstUndef(elem_ty); | 11540 | if (array_val.isUndef()) return sema.addConstUndef(elem_ty); |
| 11593 | if (opt_index_val) |index_val| { | 11541 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| | 11542 | if (maybe_index_val) |index_val| { |
| 11594 | const index = @intCast(usize, index_val.toUnsignedInt()); | 11543 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| 11595 | const elem_val = try array_val.elemValue(sema.arena, index); | 11544 | const elem_val = try array_val.elemValue(sema.arena, index); |
| 11596 | return sema.addConstant(elem_ty, elem_val); | 11545 | return sema.addConstant(elem_ty, elem_val); |
| 11597 | } | 11546 | } |
| 11598 | } | 11547 | } |
| 11599 | try sema.requireRuntimeBlock(block, src); | 11548 | try sema.requireRuntimeBlock(block, src); |
| 11600 | return block.addBinOp(.array_elem_val, array_maybe_ptr, elem_index); | 11549 | return block.addBinOp(.array_elem_val, array, elem_index); |
| 11601 | }, | 11550 | }, |
| 11602 | else => return sema.fail( | 11551 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}), |
| 11603 | block, | 11552 | else => unreachable, |
| 11604 | array_ptr_src, | | |
| 11605 | "expected pointer or array; found '{}'", | | |
| 11606 | .{maybe_ptr_ty}, | | |
| 11607 | ), | | |
| 11608 | } | 11553 | } |
| 11609 | } | 11554 | } |
| 11610 | | 11555 | |