Commit 8d3e4147d5

Andrew Kelley <andrew@ziglang.org>
2020-04-22 03:33:55
ir: analyze deref instruction
1 parent 2c11acf
Changed files (2)
src-self-hosted
src-self-hosted/ir.zig
@@ -383,7 +383,7 @@ const Analyze = struct {
             },
             .ptrtoint => return self.analyzeInstPtrToInt(func, old_inst.cast(text.Inst.PtrToInt).?),
             .fieldptr => return self.analyzeInstFieldPtr(func, old_inst.cast(text.Inst.FieldPtr).?),
-            .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
+            .deref => return self.analyzeInstDeref(func, old_inst.cast(text.Inst.Deref).?),
             .as => return self.analyzeInstAs(func, old_inst.cast(text.Inst.As).?),
             .@"asm" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
             .@"unreachable" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
@@ -476,7 +476,7 @@ const Analyze = struct {
 
         const elem_ty = switch (object_ptr.ty.zigTypeTag()) {
             .Pointer => object_ptr.ty.elemType(),
-            else => return self.fail(fieldptr.base.src, "expected pointer, found '{}'", .{object_ptr.ty}),
+            else => return self.fail(fieldptr.positionals.object_ptr.src, "expected pointer, found '{}'", .{object_ptr.ty}),
         };
         switch (elem_ty.zigTypeTag()) {
             .Array => {
@@ -535,6 +535,22 @@ const Analyze = struct {
         return self.fail(intcast.base.src, "TODO implement analyze widen or shorten int", .{});
     }
 
+    fn analyzeInstDeref(self: *Analyze, func: ?*Fn, deref: *text.Inst.Deref) InnerError!*Inst {
+        const ptr = try self.resolveInst(func, deref.positionals.ptr);
+        const elem_ty = switch (ptr.ty.zigTypeTag()) {
+            .Pointer => ptr.ty.elemType(),
+            else => return self.fail(deref.positionals.ptr.src, "expected pointer, found '{}'", .{ptr.ty}),
+        };
+        if (ptr.value()) |val| {
+            return self.constInst(deref.base.src, .{
+                .ty = elem_ty,
+                .val = val.pointerDeref(),
+            });
+        }
+
+        return self.fail(deref.base.src, "TODO implement runtime deref", .{});
+    }
+
     fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {
         const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty);
         if (in_memory_result == .ok) {
src-self-hosted/value.zig
@@ -284,6 +284,54 @@ pub const Value = extern union {
         }
     }
 
+    /// Asserts the value is a pointer and dereferences it.
+    pub fn pointerDeref(self: Value) Value {
+        switch (self.tag()) {
+            .ty,
+            .u8_type,
+            .i8_type,
+            .isize_type,
+            .usize_type,
+            .c_short_type,
+            .c_ushort_type,
+            .c_int_type,
+            .c_uint_type,
+            .c_long_type,
+            .c_ulong_type,
+            .c_longlong_type,
+            .c_ulonglong_type,
+            .c_longdouble_type,
+            .f16_type,
+            .f32_type,
+            .f64_type,
+            .f128_type,
+            .c_void_type,
+            .bool_type,
+            .void_type,
+            .type_type,
+            .anyerror_type,
+            .comptime_int_type,
+            .comptime_float_type,
+            .noreturn_type,
+            .fn_naked_noreturn_no_args_type,
+            .single_const_pointer_to_comptime_int_type,
+            .const_slice_u8_type,
+            .void_value,
+            .noreturn_value,
+            .bool_true,
+            .bool_false,
+            .function,
+            .int_u64,
+            .int_i64,
+            .int_big,
+            .bytes,
+            => unreachable,
+
+            .ref => return self.cast(Payload.Ref).?.cell.contents,
+            .ref_val => return self.cast(Payload.RefVal).?.val,
+        }
+    }
+
     /// This type is not copyable since it may contain pointers to its inner data.
     pub const Payload = struct {
         tag: Tag,
@@ -321,7 +369,7 @@ pub const Value = extern union {
 
         pub const Ref = struct {
             base: Payload = Payload{ .tag = .ref },
-            pointee: *MemoryCell,
+            cell: *MemoryCell,
         };
 
         pub const RefVal = struct {