aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-05-20 09:35:11 -0400
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:53 -0700
commit115c08956278b79c848e04c2f4eefca40e6cd8a3 (patch)
tree8dfdced9bc1ba7499f7660e986bd82d0ae772347 /src/Sema.zig
parentbe78a12d7d5ac0a711fdf7237d7ccefba42be83c (diff)
downloadzig-115c08956278b79c848e04c2f4eefca40e6cd8a3.tar.gz
zig-115c08956278b79c848e04c2f4eefca40e6cd8a3.zip
Value: add `intern` and `unintern` to facilitate code conversion
This allows some code (like struct initializers) to use interned types while other code (such as comptime mutation) continues to use legacy types. With these changes, an `zig build-obj empty.zig` gets to a crash on missing interned error union types.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig93
1 files changed, 73 insertions, 20 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 145f514ebc..c98c61ddc4 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -13072,25 +13072,32 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// as zero-filling a byte array.
if (lhs_len == 1) {
const elem_val = try lhs_sub_val.elemValue(mod, 0);
- break :v try Value.Tag.repeated.create(sema.arena, elem_val);
+ break :v try mod.intern(.{ .aggregate = .{
+ .ty = result_ty.ip_index,
+ .storage = .{ .repeated_elem = elem_val.ip_index },
+ } });
}
- const element_vals = try sema.arena.alloc(Value, final_len_including_sent);
+ const element_vals = try sema.arena.alloc(InternPool.Index, final_len_including_sent);
var elem_i: usize = 0;
while (elem_i < result_len) {
var lhs_i: usize = 0;
while (lhs_i < lhs_len) : (lhs_i += 1) {
const elem_val = try lhs_sub_val.elemValue(mod, lhs_i);
- element_vals[elem_i] = elem_val;
+ assert(elem_val.ip_index != .none);
+ element_vals[elem_i] = elem_val.ip_index;
elem_i += 1;
}
}
if (lhs_info.sentinel) |sent_val| {
- element_vals[result_len] = sent_val;
+ element_vals[result_len] = sent_val.ip_index;
}
- break :v try Value.Tag.aggregate.create(sema.arena, element_vals);
+ break :v try mod.intern(.{ .aggregate = .{
+ .ty = result_ty.ip_index,
+ .storage = .{ .elems = element_vals },
+ } });
};
- return sema.addConstantMaybeRef(block, result_ty, val, ptr_addrspace != null);
+ return sema.addConstantMaybeRef(block, result_ty, val.toValue(), ptr_addrspace != null);
}
try sema.requireRuntimeBlock(block, src, lhs_src);
@@ -18111,12 +18118,16 @@ fn finishStructInit(
} else null;
const runtime_index = opt_runtime_index orelse {
- const values = try sema.arena.alloc(Value, field_inits.len);
- for (field_inits, 0..) |field_init, i| {
- values[i] = (sema.resolveMaybeUndefVal(field_init) catch unreachable).?;
- }
- const struct_val = try Value.Tag.aggregate.create(sema.arena, values);
- return sema.addConstantMaybeRef(block, struct_ty, struct_val, is_ref);
+ const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);
+ for (elems, field_inits, 0..) |*elem, field_init, field_i| {
+ elem.* = try (sema.resolveMaybeUndefVal(field_init) catch unreachable).?
+ .intern(struct_ty.structFieldType(field_i, mod), mod);
+ }
+ const struct_val = try mod.intern(.{ .aggregate = .{
+ .ty = struct_ty.ip_index,
+ .storage = .{ .elems = elems },
+ } });
+ return sema.addConstantMaybeRef(block, struct_ty, struct_val.toValue(), is_ref);
};
if (is_ref) {
@@ -18195,21 +18206,20 @@ fn zirStructInitAnon(
const init = try sema.resolveInst(item.data.init);
field_ty.* = sema.typeOf(init).ip_index;
- if (types[i].toType().zigTypeTag(mod) == .Opaque) {
+ if (field_ty.toType().zigTypeTag(mod) == .Opaque) {
const msg = msg: {
const decl = sema.mod.declPtr(block.src_decl);
const field_src = mod.initSrc(src.node_offset.x, decl, i);
const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
errdefer msg.destroy(sema.gpa);
- try sema.addDeclaredHereNote(msg, types[i].toType());
+ try sema.addDeclaredHereNote(msg, field_ty.toType());
break :msg msg;
};
return sema.failWithOwnedErrorMsg(msg);
}
if (try sema.resolveMaybeUndefVal(init)) |init_val| {
- assert(init_val.ip_index != .none);
- values[i] = init_val.ip_index;
+ values[i] = try init_val.intern(field_ty.toType(), mod);
} else {
values[i] = .none;
runtime_index = i;
@@ -24891,9 +24901,7 @@ fn structFieldVal(
if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
return sema.addConstant(field.ty, opv);
}
-
- const field_values = struct_val.castTag(.aggregate).?.data;
- return sema.addConstant(field.ty, field_values[field_index]);
+ return sema.addConstant(field.ty, try struct_val.fieldValue(field.ty, mod, field_index));
}
try sema.requireRuntimeBlock(block, src, null);
@@ -27925,7 +27933,24 @@ fn beginComptimePtrMutation(
ptr_elem_ty,
parent.decl_ref_mut,
),
+ .repeated => {
+ const arena = parent.beginArena(sema.mod);
+ defer parent.finishArena(sema.mod);
+
+ const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod));
+ @memset(elems, val_ptr.castTag(.repeated).?.data);
+ val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
+ return beginComptimePtrMutationInner(
+ sema,
+ block,
+ src,
+ parent.ty.structFieldType(field_index, mod),
+ &elems[field_index],
+ ptr_elem_ty,
+ parent.decl_ref_mut,
+ );
+ },
.@"union" => {
// We need to set the active field of the union.
const union_tag_ty = field_ptr.container_ty.unionTagTypeHypothetical(mod);
@@ -28107,6 +28132,13 @@ fn beginComptimePtrMutationInner(
const mod = sema.mod;
const target = mod.getTarget();
const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok;
+
+ const decl = mod.declPtr(decl_ref_mut.decl_index);
+ var decl_arena: std.heap.ArenaAllocator = undefined;
+ const allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena);
+ defer decl.value_arena.?.release(&decl_arena);
+ decl_val.* = try decl_val.unintern(allocator, mod);
+
if (coerce_ok) {
return ComptimePtrMutationKit{
.decl_ref_mut = decl_ref_mut,
@@ -28412,6 +28444,27 @@ fn beginComptimePtrLoad(
},
else => switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
.int => return error.RuntimeLoad,
+ .ptr => |ptr| switch (ptr.addr) {
+ .@"var", .int => return error.RuntimeLoad,
+ .decl, .mut_decl => blk: {
+ const decl_index = switch (ptr.addr) {
+ .decl => |decl| decl,
+ .mut_decl => |mut_decl| mut_decl.decl,
+ else => unreachable,
+ };
+ const decl = mod.declPtr(decl_index);
+ const decl_tv = try decl.typedValue();
+ if (decl_tv.val.tagIsVariable()) return error.RuntimeLoad;
+
+ const layout_defined = decl.ty.hasWellDefinedLayout(mod);
+ break :blk ComptimePtrLoadKit{
+ .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
+ .pointee = decl_tv,
+ .is_mutable = false,
+ .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
+ };
+ },
+ },
else => unreachable,
},
};
@@ -29425,7 +29478,7 @@ fn analyzeSlicePtr(
const result_ty = slice_ty.slicePtrFieldType(mod);
if (try sema.resolveMaybeUndefVal(slice)) |val| {
if (val.isUndef(mod)) return sema.addConstUndef(result_ty);
- return sema.addConstant(result_ty, val.slicePtr());
+ return sema.addConstant(result_ty, val.slicePtr(mod));
}
try sema.requireRuntimeBlock(block, slice_src, null);
return block.addTyOp(.slice_ptr, result_ty, slice);