diff --git a/src/Sema.zig b/src/Sema.zig index 5a77f81aa0..b01e4539b0 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -351,6 +351,24 @@ pub const Block = struct { }); } + pub fn addPtrElemPtr( + block: *Block, + array_ptr: Air.Inst.Ref, + elem_index: Air.Inst.Ref, + elem_ptr_ty: Type, + ) !Air.Inst.Ref { + return block.addInst(.{ + .tag = .ptr_elem_ptr, + .data = .{ .ty_pl = .{ + .ty = try block.sema.addType(elem_ptr_ty), + .payload = try block.sema.addExtra(Air.Bin{ + .lhs = array_ptr, + .rhs = elem_index, + }), + } }, + }); + } + pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { return Air.indexToRef(try block.addInstAsIndex(inst)); } @@ -11500,10 +11518,10 @@ fn elemPtr( switch (array_ty.zigTypeTag()) { .Pointer => { // In all below cases, we have to deref the ptr operand to get the actual array pointer. - const array = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src); + const array = try sema.analyzeLoad(block, array_ptr_src, array_ptr, array_ptr_src); + const result_ty = try array_ty.elemPtrType(sema.arena); switch (array_ty.ptrSize()) { .Slice => { - const result_ty = try array_ty.elemPtrType(sema.arena); const maybe_slice_val = try sema.resolveDefinedValue(block, array_ptr_src, array); const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); const runtime_src = if (maybe_slice_val) |slice_val| rs: { @@ -11516,14 +11534,28 @@ fn elemPtr( try sema.requireRuntimeBlock(block, runtime_src); return block.addSliceElemPtr(array, elem_index, result_ty); }, - .Many, .C => return sema.fail(block, src, "TODO implement Sema for elemPtr for many/c pointer", .{}), + .Many, .C => { + const maybe_ptr_val = try sema.resolveDefinedValue(block, array_ptr_src, array); + const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); + + const runtime_src = rs: { + const ptr_val = maybe_ptr_val orelse break :rs array_ptr_src; + const index_val = maybe_index_val orelse break :rs elem_index_src; + const index = @intCast(usize, index_val.toUnsignedInt()); + const elem_ptr = try ptr_val.elemPtr(sema.arena, index); + return sema.addConstant(result_ty, elem_ptr); + }; + + try sema.requireRuntimeBlock(block, runtime_src); + return block.addPtrElemPtr(array, elem_index, result_ty); + }, .One => { assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable - return sema.elemPtrArray(block, src, array, elem_index, elem_index_src); + return sema.elemPtrArray(block, array_ptr_src, array, elem_index, elem_index_src); }, } }, - .Array => return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src), + .Array => return sema.elemPtrArray(block, array_ptr_src, array_ptr, elem_index, elem_index_src), .Vector => return sema.fail(block, src, "TODO implement Sema for elemPtr for vector", .{}), else => unreachable, } @@ -11560,21 +11592,30 @@ fn elemVal( return block.addBinOp(.slice_elem_val, array, elem_index); }, .Many, .C => { - if (try sema.resolveDefinedValue(block, src, array)) |ptr_val| { - _ = ptr_val; - return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); - } - try sema.requireRuntimeBlock(block, src); + const maybe_ptr_val = try sema.resolveDefinedValue(block, array_src, array); + const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); + + const runtime_src = rs: { + const ptr_val = maybe_ptr_val orelse break :rs array_src; + const index_val = maybe_index_val orelse break :rs elem_index_src; + const index = @intCast(usize, index_val.toUnsignedInt()); + const maybe_array_val = try ptr_val.pointerDeref(sema.arena); + const array_val = maybe_array_val orelse break :rs array_src; + const elem_val = try array_val.elemValue(sema.arena, index); + return sema.addConstant(array_ty.elemType2(), elem_val); + }; + + try sema.requireRuntimeBlock(block, runtime_src); return block.addBinOp(.ptr_elem_val, array, elem_index); }, .One => { assert(array_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable - const elem_ptr = try sema.elemPtr(block, src, array, elem_index, elem_index_src); - return sema.analyzeLoad(block, src, elem_ptr, elem_index_src); + const elem_ptr = try sema.elemPtr(block, array_src, array, elem_index, elem_index_src); + return sema.analyzeLoad(block, array_src, elem_ptr, elem_index_src); }, }, .Array => { - if (try sema.resolveMaybeUndefVal(block, src, array)) |array_val| { + if (try sema.resolveMaybeUndefVal(block, array_src, array)) |array_val| { const elem_ty = array_ty.childType(); if (array_val.isUndef()) return sema.addConstUndef(elem_ty); const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index); @@ -11584,10 +11625,10 @@ fn elemVal( return sema.addConstant(elem_ty, elem_val); } } - try sema.requireRuntimeBlock(block, src); + try sema.requireRuntimeBlock(block, array_src); return block.addBinOp(.array_elem_val, array, elem_index); }, - .Vector => return sema.fail(block, src, "TODO implement Sema for elemVal for vector", .{}), + .Vector => return sema.fail(block, array_src, "TODO implement Sema for elemVal for vector", .{}), else => unreachable, } } @@ -11615,16 +11656,7 @@ fn elemPtrArray( } // TODO safety check for array bounds try sema.requireRuntimeBlock(block, src); - return block.addInst(.{ - .tag = .ptr_elem_ptr, - .data = .{ .ty_pl = .{ - .ty = try sema.addType(result_ty), - .payload = try sema.addExtra(Air.Bin{ - .lhs = array_ptr, - .rhs = elem_index, - }), - } }, - }); + return block.addPtrElemPtr(array_ptr, elem_index, result_ty); } fn coerce(