coerce in memory improvements

This commit is contained in:
Techatrix 2023-01-20 15:08:52 +01:00
parent bdf143eaa6
commit 3d95b203f2

View File

@ -1889,14 +1889,12 @@ const InMemoryCoercionResult = union(enum) {
} }
}; };
/// If pointers have the same representation in runtime memory /// If types have the same representation in runtime memory
/// * `const` attribute can be gained /// * int/float: same number of bits
/// * `volatile` attribute can be gained /// * pointer: see `coerceInMemoryAllowedPtrs`
/// * `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer) but only if dest_is_const /// * error union: coerceable error set and payload
/// * alignment can be decreased /// * error set: sub-set to super-set
/// * bit offset attributes must match exactly /// * array: same shape and coerceable child
/// * `*`/`[*]` must match exactly, but `[*c]` matches either one
/// * sentinel-terminated pointers can coerce into `[*]`
fn coerceInMemoryAllowed( fn coerceInMemoryAllowed(
ip: *InternPool, ip: *InternPool,
gpa: Allocator, gpa: Allocator,
@ -1928,12 +1926,19 @@ fn coerceInMemoryAllowed(
if (dest_info.signedness == src_info.signedness and dest_info.bits == src_info.bits) return .ok; if (dest_info.signedness == src_info.signedness and dest_info.bits == src_info.bits) return .ok;
return InMemoryCoercionResult{ .int_not_coercible = .{ if ((src_info.signedness == dest_info.signedness and dest_info.bits < src_info.bits) or
.actual_signedness = src_info.signedness, // small enough unsigned ints can get casted to large enough signed ints
.wanted_signedness = dest_info.signedness, (dest_info.signedness == .signed and (src_info.signedness == .unsigned or dest_info.bits <= src_info.bits)) or
.actual_bits = src_info.bits, (dest_info.signedness == .unsigned and src_info.signedness == .signed))
.wanted_bits = dest_info.bits, {
} }; return InMemoryCoercionResult{ .int_not_coercible = .{
.actual_signedness = src_info.signedness,
.wanted_signedness = dest_info.signedness,
.actual_bits = src_info.bits,
.wanted_bits = dest_info.bits,
} };
}
return .ok;
}, },
.Float => { .Float => {
const dest_bits = dest_key.floatBits(target); const dest_bits = dest_key.floatBits(target);
@ -2225,7 +2230,7 @@ fn coerceInMemoryAllowedFns(
dest_info: Function, dest_info: Function,
src_info: Function, src_info: Function,
target: std.Target, target: std.Target,
) !InMemoryCoercionResult { ) error{OutOfMemory}!InMemoryCoercionResult {
if (dest_info.is_var_args != src_info.is_var_args) { if (dest_info.is_var_args != src_info.is_var_args) {
return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args }; return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
} }
@ -2269,24 +2274,24 @@ fn coerceInMemoryAllowedFns(
} }; } };
} }
for (dest_info.args) |dest_param_ty, i| { if (!dest_info.args_is_comptime.eql(src_info.args_is_comptime)) {
const src_param_ty = src_info.args[i]; const index = dest_info.args_is_comptime.xorWith(src_info.args_is_comptime).findFirstSet().?;
return InMemoryCoercionResult{ .fn_param_comptime = .{
.index = index,
.wanted = dest_info.args_is_comptime.isSet(index),
} };
}
// TODO move outside of loop for (dest_info.args) |dest_arg_ty, i| {
if (i < 32 and dest_info.args_is_comptime.isSet(i) != src_info.args_is_comptime.isSet(i)) { const src_arg_ty = src_info.args[i];
return InMemoryCoercionResult{ .fn_param_comptime = .{
.index = i,
.wanted = dest_info.args_is_comptime.isSet(i),
} };
}
// Note: Cast direction is reversed here. // Note: Cast direction is reversed here.
const param = try ip.coerceInMemoryAllowed(gpa, arena, src_param_ty, dest_param_ty, true, target); const param = try ip.coerceInMemoryAllowed(gpa, arena, src_arg_ty, dest_arg_ty, true, target);
if (param != .ok) { if (param != .ok) {
return InMemoryCoercionResult{ .fn_param = .{ return InMemoryCoercionResult{ .fn_param = .{
.child = try param.dupe(arena), .child = try param.dupe(arena),
.actual = src_param_ty, .actual = src_arg_ty,
.wanted = dest_param_ty, .wanted = dest_arg_ty,
.index = i, .index = i,
} }; } };
} }
@ -2295,6 +2300,14 @@ fn coerceInMemoryAllowedFns(
return .ok; return .ok;
} }
/// If pointers have the same representation in runtime memory
/// * `const` attribute can be gained
/// * `volatile` attribute can be gained
/// * `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer) but only if dest_is_const
/// * alignment can be decreased
/// * bit offset attributes must match exactly
/// * `*`/`[*]` must match exactly, but `[*c]` matches either one
/// * sentinel-terminated pointers can coerce into `[*]`
fn coerceInMemoryAllowedPtrs( fn coerceInMemoryAllowedPtrs(
ip: *InternPool, ip: *InternPool,
gpa: Allocator, gpa: Allocator,
@ -2305,7 +2318,7 @@ fn coerceInMemoryAllowedPtrs(
src_ptr_info: Key, src_ptr_info: Key,
dest_is_const: bool, dest_is_const: bool,
target: std.Target, target: std.Target,
) !InMemoryCoercionResult { ) error{OutOfMemory}!InMemoryCoercionResult {
const dest_info = dest_ptr_info.pointer_type; const dest_info = dest_ptr_info.pointer_type;
const src_info = src_ptr_info.pointer_type; const src_info = src_ptr_info.pointer_type;