Sema: make check for whether call should be memoized more thorough

This commit is contained in:
Veikka Tuominen 2022-03-11 16:48:44 +02:00
parent 01cd4119b0
commit 03b8206f27
2 changed files with 32 additions and 3 deletions

View File

@ -4618,7 +4618,7 @@ fn analyzeCall(
},
else => {},
}
should_memoize = should_memoize and !arg_val.isComptimeMutablePtr();
should_memoize = should_memoize and !arg_val.canMutateComptimeVarState();
memoized_call_key.args[arg_i] = .{
.ty = param_ty,
.val = arg_val,
@ -4644,7 +4644,7 @@ fn analyzeCall(
},
else => {},
}
should_memoize = should_memoize and !arg_val.isComptimeMutablePtr();
should_memoize = should_memoize and !arg_val.canMutateComptimeVarState();
memoized_call_key.args[arg_i] = .{
.ty = sema.typeOf(uncasted_arg),
.val = arg_val,
@ -13603,7 +13603,8 @@ fn analyzeShuffle(
// in 1 call because these calls to analyzeShuffle guarantee a_len == b_len.
if (a_len != b_len) {
const min_len = std.math.min(a_len, b_len);
const max_len = std.math.max(a_len, b_len);
const max_src = if (a_len > b_len) a_src else b_src;
const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));
const expand_mask_values = try sema.arena.alloc(Value, max_len);
i = 0;

View File

@ -1157,6 +1157,7 @@ pub const Value = extern union {
) Allocator.Error!Value {
switch (ty.zigTypeTag()) {
.Int => {
if (buffer.len == 0) return Value.zero;
const int_info = ty.intInfo(target);
const endian = target.cpu.arch.endian();
const Limb = std.math.big.Limb;
@ -2185,6 +2186,33 @@ pub const Value = extern union {
};
}
pub fn canMutateComptimeVarState(val: Value) bool {
if (val.isComptimeMutablePtr()) return true;
switch (val.tag()) {
.repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),
.array => {
const elems = val.cast(Payload.Array).?.data;
for (elems) |elem| {
if (elem.canMutateComptimeVarState()) return true;
}
return false;
},
.eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),
.eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.canMutateComptimeVarState(),
.opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),
.opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.canMutateComptimeVarState(),
.@"struct" => {
const fields = val.cast(Payload.Struct).?.data;
for (fields) |field| {
if (field.canMutateComptimeVarState()) return true;
}
return false;
},
.@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(),
else => return false,
}
}
/// Gets the decl referenced by this pointer. If the pointer does not point
/// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
/// this function returns null.