aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-03-11 16:48:44 +0200
committerVeikka Tuominen <git@vexu.eu>2022-03-11 16:56:33 +0200
commit03b8206f27485f871fc489f884ffbc276d61877c (patch)
tree88163b5e6adf255f8b85bddbf77e1d0d4cb5e746 /src
parent01cd4119b032f13899e9b7b30c7e093620058dfd (diff)
downloadzig-03b8206f27485f871fc489f884ffbc276d61877c.tar.gz
zig-03b8206f27485f871fc489f884ffbc276d61877c.zip
Sema: make check for whether call should be memoized more thorough
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig7
-rw-r--r--src/value.zig28
2 files changed, 32 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index fb45c9e9d3..a33861c74c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -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;
diff --git a/src/value.zig b/src/value.zig
index 973e477099..9117ef78df 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -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.