ir: type coercion skeleton
parent
8e0bcaca9b
commit
fb63ba2577
|
@ -232,6 +232,18 @@ const Analyze = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {
|
fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst {
|
||||||
|
// *[N]T to []T
|
||||||
|
if (inst.ty.isSinglePointer() and dest_type.isSlice() and
|
||||||
|
(!inst.ty.pointerIsConst() or dest_type.pointerIsConst()))
|
||||||
|
{
|
||||||
|
const array_type = inst.ty.elemType();
|
||||||
|
const dst_elem_type = dest_type.elemType();
|
||||||
|
if (array_type.zigTypeTag() == .Array and
|
||||||
|
coerceInMemoryAllowed(dst_elem_type, array_type.elemType()) == .ok)
|
||||||
|
{
|
||||||
|
return self.fail(inst.src_offset, "TODO do the type coercion", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
return self.fail(inst.src_offset, "TODO implement type coercion", .{});
|
return self.fail(inst.src_offset, "TODO implement type coercion", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +256,21 @@ const Analyze = struct {
|
||||||
};
|
};
|
||||||
return error.AnalysisFail;
|
return error.AnalysisFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const InMemoryCoercionResult = enum {
|
||||||
|
ok,
|
||||||
|
no_match,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn coerceInMemoryAllowed(dest_type: Type, src_type: Type) InMemoryCoercionResult {
|
||||||
|
// As a shortcut, if the small tags / addresses match, we're done.
|
||||||
|
if (dest_type.tag_if_small_enough == src_type.tag_if_small_enough)
|
||||||
|
return .ok;
|
||||||
|
|
||||||
|
// TODO: implement more of this function
|
||||||
|
|
||||||
|
return .no_match;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() anyerror!void {
|
pub fn main() anyerror!void {
|
||||||
|
|
|
@ -72,6 +72,17 @@ pub const Type = extern union {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast(self: Type, comptime T: type) ?*T {
|
||||||
|
if (self.tag_if_small_enough < Tag.no_payload_count)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
const expected_tag = std.meta.fieldInfo(T, "base").default_value.?.tag;
|
||||||
|
if (self.ptr_otherwise.tag != expected_tag)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return @fieldParentPtr(T, "base", self.ptr_otherwise);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn format(
|
pub fn format(
|
||||||
self: Type,
|
self: Type,
|
||||||
comptime fmt: []const u8,
|
comptime fmt: []const u8,
|
||||||
|
@ -133,6 +144,150 @@ pub const Type = extern union {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn isSinglePointer(self: Type) bool {
|
||||||
|
return switch (self.tag()) {
|
||||||
|
.@"u8",
|
||||||
|
.@"i8",
|
||||||
|
.@"isize",
|
||||||
|
.@"usize",
|
||||||
|
.@"c_short",
|
||||||
|
.@"c_ushort",
|
||||||
|
.@"c_int",
|
||||||
|
.@"c_uint",
|
||||||
|
.@"c_long",
|
||||||
|
.@"c_ulong",
|
||||||
|
.@"c_longlong",
|
||||||
|
.@"c_ulonglong",
|
||||||
|
.@"c_longdouble",
|
||||||
|
.@"f16",
|
||||||
|
.@"f32",
|
||||||
|
.@"f64",
|
||||||
|
.@"f128",
|
||||||
|
.@"c_void",
|
||||||
|
.@"bool",
|
||||||
|
.@"void",
|
||||||
|
.@"type",
|
||||||
|
.@"anyerror",
|
||||||
|
.@"comptime_int",
|
||||||
|
.@"comptime_float",
|
||||||
|
.@"noreturn",
|
||||||
|
.array,
|
||||||
|
.array_u8_sentinel_0,
|
||||||
|
.const_slice_u8,
|
||||||
|
=> false,
|
||||||
|
|
||||||
|
.single_const_pointer => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isSlice(self: Type) bool {
|
||||||
|
return switch (self.tag()) {
|
||||||
|
.@"u8",
|
||||||
|
.@"i8",
|
||||||
|
.@"isize",
|
||||||
|
.@"usize",
|
||||||
|
.@"c_short",
|
||||||
|
.@"c_ushort",
|
||||||
|
.@"c_int",
|
||||||
|
.@"c_uint",
|
||||||
|
.@"c_long",
|
||||||
|
.@"c_ulong",
|
||||||
|
.@"c_longlong",
|
||||||
|
.@"c_ulonglong",
|
||||||
|
.@"c_longdouble",
|
||||||
|
.@"f16",
|
||||||
|
.@"f32",
|
||||||
|
.@"f64",
|
||||||
|
.@"f128",
|
||||||
|
.@"c_void",
|
||||||
|
.@"bool",
|
||||||
|
.@"void",
|
||||||
|
.@"type",
|
||||||
|
.@"anyerror",
|
||||||
|
.@"comptime_int",
|
||||||
|
.@"comptime_float",
|
||||||
|
.@"noreturn",
|
||||||
|
.array,
|
||||||
|
.array_u8_sentinel_0,
|
||||||
|
.single_const_pointer,
|
||||||
|
=> false,
|
||||||
|
|
||||||
|
.const_slice_u8 => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts the type is a pointer type.
|
||||||
|
pub fn pointerIsConst(self: Type) bool {
|
||||||
|
return switch (self.tag()) {
|
||||||
|
.@"u8",
|
||||||
|
.@"i8",
|
||||||
|
.@"isize",
|
||||||
|
.@"usize",
|
||||||
|
.@"c_short",
|
||||||
|
.@"c_ushort",
|
||||||
|
.@"c_int",
|
||||||
|
.@"c_uint",
|
||||||
|
.@"c_long",
|
||||||
|
.@"c_ulong",
|
||||||
|
.@"c_longlong",
|
||||||
|
.@"c_ulonglong",
|
||||||
|
.@"c_longdouble",
|
||||||
|
.@"f16",
|
||||||
|
.@"f32",
|
||||||
|
.@"f64",
|
||||||
|
.@"f128",
|
||||||
|
.@"c_void",
|
||||||
|
.@"bool",
|
||||||
|
.@"void",
|
||||||
|
.@"type",
|
||||||
|
.@"anyerror",
|
||||||
|
.@"comptime_int",
|
||||||
|
.@"comptime_float",
|
||||||
|
.@"noreturn",
|
||||||
|
.array,
|
||||||
|
.array_u8_sentinel_0,
|
||||||
|
=> unreachable,
|
||||||
|
|
||||||
|
.single_const_pointer, .const_slice_u8 => true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts the type is a pointer or array type.
|
||||||
|
pub fn elemType(self: Type) Type {
|
||||||
|
return switch (self.tag()) {
|
||||||
|
.@"u8",
|
||||||
|
.@"i8",
|
||||||
|
.@"isize",
|
||||||
|
.@"usize",
|
||||||
|
.@"c_short",
|
||||||
|
.@"c_ushort",
|
||||||
|
.@"c_int",
|
||||||
|
.@"c_uint",
|
||||||
|
.@"c_long",
|
||||||
|
.@"c_ulong",
|
||||||
|
.@"c_longlong",
|
||||||
|
.@"c_ulonglong",
|
||||||
|
.@"c_longdouble",
|
||||||
|
.@"f16",
|
||||||
|
.@"f32",
|
||||||
|
.@"f64",
|
||||||
|
.@"f128",
|
||||||
|
.@"c_void",
|
||||||
|
.@"bool",
|
||||||
|
.@"void",
|
||||||
|
.@"type",
|
||||||
|
.@"anyerror",
|
||||||
|
.@"comptime_int",
|
||||||
|
.@"comptime_float",
|
||||||
|
.@"noreturn",
|
||||||
|
=> unreachable,
|
||||||
|
|
||||||
|
.array => self.cast(Payload.Array).?.elem_type,
|
||||||
|
.single_const_pointer => self.cast(Payload.SingleConstPointer).?.pointee_type,
|
||||||
|
.array_u8_sentinel_0, .const_slice_u8 => Type.initTag(.@"u8"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// This enum does not directly correspond to `std.builtin.TypeId` because
|
/// This enum does not directly correspond to `std.builtin.TypeId` because
|
||||||
/// it has extra enum tags in it, as a way of using less memory. For example,
|
/// it has extra enum tags in it, as a way of using less memory. For example,
|
||||||
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
|
/// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
|
||||||
|
|
Loading…
Reference in New Issue