ir: analyze deref instruction

This commit is contained in:
Andrew Kelley
2020-04-21 21:33:55 -04:00
parent 2c11acf807
commit 8d3e4147d5
2 changed files with 67 additions and 3 deletions

View File

@@ -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) {

View File

@@ -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 {