| ... | ... | @@ -11494,117 +11494,62 @@ fn elemVal( |
| 11494 | 11494 | sema: *Sema, |
| 11495 | 11495 | block: *Block, |
| 11496 | 11496 | src: LazySrcLoc, |
| 11497 | | array_maybe_ptr: Air.Inst.Ref, |
| 11497 | array: Air.Inst.Ref, |
| 11498 | 11498 | elem_index: Air.Inst.Ref, |
| 11499 | 11499 | elem_index_src: LazySrcLoc, |
| 11500 | 11500 | ) CompileError!Air.Inst.Ref { |
| 11501 | | const array_ptr_src = src; // TODO better source location |
| 11502 | | const maybe_ptr_ty = sema.typeOf(array_maybe_ptr); |
| 11503 | | switch (maybe_ptr_ty.zigTypeTag()) { |
| 11504 | | .Pointer => switch (maybe_ptr_ty.ptrSize()) { |
| 11501 | const array_src = src; // TODO better source location |
| 11502 | const array_ty = sema.typeOf(array); |
| 11503 | |
| 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 | 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 | 11512 | const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11508 | 11513 | const runtime_src = if (maybe_slice_val) |slice_val| rs: { |
| 11509 | 11514 | const index_val = maybe_index_val orelse break :rs elem_index_src; |
| 11510 | 11515 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| 11511 | 11516 | const elem_val = try slice_val.elemValue(sema.arena, index); |
| 11512 | | return sema.addConstant(maybe_ptr_ty.elemType2(), elem_val); |
| 11513 | | } else array_ptr_src; |
| 11517 | return sema.addConstant(array_ty.elemType2(), elem_val); |
| 11518 | } else array_src; |
| 11514 | 11519 | |
| 11515 | 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 | 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 | 11525 | _ = ptr_val; |
| 11521 | 11526 | return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); |
| 11522 | 11527 | } |
| 11523 | 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 | 11531 | .One => { |
| 11527 | | const indexable_ty = maybe_ptr_ty.childType(); |
| 11528 | | switch (indexable_ty.zigTypeTag()) { |
| 11529 | | .Pointer => switch (indexable_ty.ptrSize()) { |
| 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 | | } |
| 11532 | assert(array_ty.childType().zigTypeTag() == .Array); |
| 11533 | const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); |
| 11534 | return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); |
| 11586 | 11535 | }, |
| 11587 | 11536 | }, |
| 11588 | 11537 | .Array => { |
| 11589 | | if (try sema.resolveMaybeUndefVal(block, src, array_maybe_ptr)) |array_val| { |
| 11590 | | const elem_ty = maybe_ptr_ty.childType(); |
| 11591 | | const opt_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); |
| 11538 | if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| { |
| 11539 | const elem_ty = array_ty.childType(); |
| 11592 | 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 | 11543 | const index = @intCast(usize, index_val.toUnsignedInt()); |
| 11595 | 11544 | const elem_val = try array_val.elemValue(sema.arena, index); |
| 11596 | 11545 | return sema.addConstant(elem_ty, elem_val); |
| 11597 | 11546 | } |
| 11598 | 11547 | } |
| 11599 | 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( |
| 11603 | | block, |
| 11604 | | array_ptr_src, |
| 11605 | | "expected pointer or array; found '{}'", |
| 11606 | | .{maybe_ptr_ty}, |
| 11607 | | ), |
| 11551 | .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}), |
| 11552 | else => unreachable, |
| 11608 | 11553 | } |
| 11609 | 11554 | } |
| 11610 | 11555 | |