Commit fc034ca94f

Robin Voetter <robin@voetter.nl>
2021-10-21 16:54:34
stage2: comptime elemVal and elemPtr for Many/C pointers
1 parent 09c7d5a
Changed files (1)
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(