aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-05-22 07:58:02 -0400
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:54 -0700
commit6e0de1d11694a58745da76d601ebab7562feed09 (patch)
treecd6cf352788d8f47bad97a95e4390dd3f6a309c5 /src/Sema.zig
parent5555bdca047f8dbf8d7adfa8f248f5ce9b692b9e (diff)
downloadzig-6e0de1d11694a58745da76d601ebab7562feed09.tar.gz
zig-6e0de1d11694a58745da76d601ebab7562feed09.zip
InternPool: port most of value tags
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig2882
1 files changed, 1338 insertions, 1544 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 7df6e44898..d9b346e638 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -28,10 +28,12 @@ owner_decl_index: Decl.Index,
/// For an inline or comptime function call, this will be the root parent function
/// which contains the callsite. Corresponds to `owner_decl`.
owner_func: ?*Module.Fn,
+owner_func_index: Module.Fn.OptionalIndex,
/// The function this ZIR code is the body of, according to the source code.
/// This starts out the same as `owner_func` and then diverges in the case of
/// an inline or comptime function call.
func: ?*Module.Fn,
+func_index: Module.Fn.OptionalIndex,
/// Used to restore the error return trace when returning a non-error from a function.
error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
/// When semantic analysis needs to know the return type of the function whose body
@@ -65,7 +67,7 @@ comptime_args_fn_inst: Zir.Inst.Index = 0,
/// to use this instead of allocating a fresh one. This avoids an unnecessary
/// extra hash table lookup in the `monomorphed_funcs` set.
/// Sema will set this to null when it takes ownership.
-preallocated_new_func: ?*Module.Fn = null,
+preallocated_new_func: Module.Fn.OptionalIndex = .none,
/// The key is types that must be fully resolved prior to machine code
/// generation pass. Types are added to this set when resolving them
/// immediately could cause a dependency loop, but they do need to be resolved
@@ -92,7 +94,7 @@ unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{}
const std = @import("std");
const math = std.math;
const mem = std.mem;
-const Allocator = std.mem.Allocator;
+const Allocator = mem.Allocator;
const assert = std.debug.assert;
const log = std.log.scoped(.sema);
@@ -1777,7 +1779,7 @@ pub fn resolveConstString(
reason: []const u8,
) ![]u8 {
const air_inst = try sema.resolveInst(zir_ref);
- const wanted_type = Type.const_slice_u8;
+ const wanted_type = Type.slice_const_u8;
const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);
@@ -1866,11 +1868,10 @@ fn resolveConstMaybeUndefVal(
if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
switch (val.ip_index) {
.generic_poison => return error.GenericPoison,
- .none => switch (val.tag()) {
+ else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
.variable => return sema.failWithNeededComptime(block, src, reason),
else => return val,
},
- else => return val,
}
}
return sema.failWithNeededComptime(block, src, reason);
@@ -1889,11 +1890,11 @@ fn resolveConstValue(
switch (val.ip_index) {
.generic_poison => return error.GenericPoison,
.undef => return sema.failWithUseOfUndef(block, src),
- .none => switch (val.tag()) {
+ else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
+ .undef => return sema.failWithUseOfUndef(block, src),
.variable => return sema.failWithNeededComptime(block, src, reason),
else => return val,
},
- else => return val,
}
}
return sema.failWithNeededComptime(block, src, reason);
@@ -1928,11 +1929,11 @@ fn resolveMaybeUndefVal(
const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
switch (val.ip_index) {
.generic_poison => return error.GenericPoison,
- .none => switch (val.tag()) {
+ .none => return val,
+ else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
.variable => return null,
else => return val,
},
- else => return val,
}
}
@@ -1948,21 +1949,20 @@ fn resolveMaybeUndefValIntable(
var check = val;
while (true) switch (check.ip_index) {
.generic_poison => return error.GenericPoison,
- .none => switch (check.tag()) {
- .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null,
- .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
- .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
- .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
- else => {
- try sema.resolveLazyValue(val);
- return val;
+ .none => break,
+ else => switch (sema.mod.intern_pool.indexToKey(check.ip_index)) {
+ .variable => return null,
+ .ptr => |ptr| switch (ptr.addr) {
+ .decl, .mut_decl, .comptime_field => return null,
+ .int => break,
+ .eu_payload, .opt_payload => |base| check = base.toValue(),
+ .elem, .field => |base_index| check = base_index.base.toValue(),
},
- },
- else => {
- try sema.resolveLazyValue(val);
- return val;
+ else => break,
},
};
+ try sema.resolveLazyValue(val);
+ return val;
}
/// Returns all Value tags including `variable` and `undef`.
@@ -1994,7 +1994,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
if (air_tags[i] == .constant) {
const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
const val = sema.air_values.items[ty_pl.payload];
- if (val.tagIsVariable()) return val;
+ if (val.getVariable(sema.mod) != null) return val;
}
return opv;
}
@@ -2003,7 +2003,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
.constant => {
const ty_pl = air_datas[i].ty_pl;
const val = sema.air_values.items[ty_pl.payload];
- if (val.isRuntimeValue()) make_runtime.* = true;
+ if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;
if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
return val;
},
@@ -2489,13 +2489,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
.@"addrspace" = addr_space,
});
try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
- return sema.addConstant(
- ptr_ty,
- try Value.Tag.decl_ref_mut.create(sema.arena, .{
- .decl_index = iac.data.decl_index,
+ return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{
+ .ty = ptr_ty.ip_index,
+ .addr = .{ .mut_decl = .{
+ .decl = iac.data.decl_index,
.runtime_index = block.runtime_index,
- }),
- );
+ } },
+ } })).toValue());
},
else => {},
}
@@ -2949,12 +2949,18 @@ fn zirEnumDecl(
}
const prev_owner_func = sema.owner_func;
+ const prev_owner_func_index = sema.owner_func_index;
sema.owner_func = null;
+ sema.owner_func_index = .none;
defer sema.owner_func = prev_owner_func;
+ defer sema.owner_func_index = prev_owner_func_index;
const prev_func = sema.func;
+ const prev_func_index = sema.func_index;
sema.func = null;
+ sema.func_index = .none;
defer sema.func = prev_func;
+ defer sema.func_index = prev_func_index;
var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
defer wip_captures.deinit();
@@ -3735,14 +3741,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
try sema.maybeQueueFuncBodyAnalysis(decl_index);
- if (var_is_mut) {
- sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{
- .decl_index = decl_index,
+ sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
+ .ty = final_ptr_ty.ip_index,
+ .addr = if (var_is_mut) .{ .mut_decl = .{
+ .decl = decl_index,
.runtime_index = block.runtime_index,
- });
- } else {
- sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index);
- }
+ } } else .{ .decl = decl_index },
+ } })).toValue();
},
.inferred_alloc => {
assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
@@ -3836,7 +3841,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
// block so that codegen does not see it.
block.instructions.shrinkRetainingCapacity(search_index);
try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
- sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
+ sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
+ .ty = final_elem_ty.ip_index,
+ .addr = .{ .decl = new_decl_index },
+ } })).toValue();
// if bitcast ty ref needs to be made const, make_ptr_const
// ZIR handles it later, so we can just use the ty ref here.
air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
@@ -4332,12 +4340,16 @@ fn validateUnionInit(
// instead a single `store` to the result ptr with a comptime union value.
block.instructions.shrinkRetainingCapacity(first_block_index);
- var union_val = try Value.Tag.@"union".create(sema.arena, .{
- .tag = tag_val,
- .val = val,
- });
- if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);
- const union_init = try sema.addConstant(union_ty, union_val);
+ var union_val = try mod.intern(.{ .un = .{
+ .ty = union_ty.ip_index,
+ .tag = tag_val.ip_index,
+ .val = val.ip_index,
+ } });
+ if (make_runtime) union_val = try mod.intern(.{ .runtime_value = .{
+ .ty = union_ty.ip_index,
+ .val = union_val,
+ } });
+ const union_init = try sema.addConstant(union_ty, union_val.toValue());
try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
return;
} else if (try sema.typeRequiresComptime(union_ty)) {
@@ -4464,14 +4476,15 @@ fn validateStructInit(
// We collect the comptime field values in case the struct initialization
// ends up being comptime-known.
- const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount(mod));
+ const field_values = try sema.gpa.alloc(InternPool.Index, struct_ty.structFieldCount(mod));
+ defer sema.gpa.free(field_values);
field: for (found_fields, 0..) |field_ptr, i| {
if (field_ptr != 0) {
// Determine whether the value stored to this pointer is comptime-known.
const field_ty = struct_ty.structFieldType(i, mod);
if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
- field_values[i] = opv;
+ field_values[i] = opv.ip_index;
continue;
}
@@ -4536,7 +4549,7 @@ fn validateStructInit(
first_block_index = @min(first_block_index, block_index);
}
if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
- field_values[i] = val;
+ field_values[i] = val.ip_index;
} else if (require_comptime) {
const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
@@ -4570,7 +4583,7 @@ fn validateStructInit(
}
continue;
}
- field_values[i] = default_val;
+ field_values[i] = default_val.ip_index;
}
if (root_msg) |msg| {
@@ -4593,9 +4606,15 @@ fn validateStructInit(
// instead a single `store` to the struct_ptr with a comptime struct value.
block.instructions.shrinkRetainingCapacity(first_block_index);
- var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);
- if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);
- const struct_init = try sema.addConstant(struct_ty, struct_val);
+ var struct_val = try mod.intern(.{ .aggregate = .{
+ .ty = struct_ty.ip_index,
+ .storage = .{ .elems = field_values },
+ } });
+ if (make_runtime) struct_val = try mod.intern(.{ .runtime_value = .{
+ .ty = struct_ty.ip_index,
+ .val = struct_val,
+ } });
+ const struct_init = try sema.addConstant(struct_ty, struct_val.toValue());
try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
return;
}
@@ -4611,7 +4630,7 @@ fn validateStructInit(
else
try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
const field_ty = sema.typeOf(default_field_ptr).childType(mod);
- const init = try sema.addConstant(field_ty, field_values[i]);
+ const init = try sema.addConstant(field_ty, field_values[i].toValue());
try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
}
}
@@ -4691,7 +4710,8 @@ fn zirValidateArrayInit(
// Collect the comptime element values in case the array literal ends up
// being comptime-known.
const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel(mod));
- const element_vals = try sema.arena.alloc(Value, array_len_s);
+ const element_vals = try sema.gpa.alloc(InternPool.Index, array_len_s);
+ defer sema.gpa.free(element_vals);
const opt_opv = try sema.typeHasOnePossibleValue(array_ty);
const air_tags = sema.air_instructions.items(.tag);
const air_datas = sema.air_instructions.items(.data);
@@ -4701,13 +4721,13 @@ fn zirValidateArrayInit(
if (array_ty.isTuple(mod)) {
if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
- element_vals[i] = opv;
+ element_vals[i] = opv.ip_index;
continue;
}
} else {
// Array has one possible value, so value is always comptime-known
if (opt_opv) |opv| {
- element_vals[i] = opv;
+ element_vals[i] = opv.ip_index;
continue;
}
}
@@ -4768,7 +4788,7 @@ fn zirValidateArrayInit(
first_block_index = @min(first_block_index, block_index);
}
if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
- element_vals[i] = val;
+ element_vals[i] = val.ip_index;
} else {
array_is_comptime = false;
}
@@ -4780,9 +4800,12 @@ fn zirValidateArrayInit(
if (array_is_comptime) {
if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {
- if (ptr_val.tag() == .comptime_field_ptr) {
- // This store was validated by the individual elem ptrs.
- return;
+ switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
+ .ptr => |ptr| switch (ptr.addr) {
+ .comptime_field => return, // This store was validated by the individual elem ptrs.
+ else => {},
+ },
+ else => {},
}
}
@@ -4790,14 +4813,20 @@ fn zirValidateArrayInit(
// instead a single `store` to the array_ptr with a comptime struct value.
// Also to populate the sentinel value, if any.
if (array_ty.sentinel(mod)) |sentinel_val| {
- element_vals[instrs.len] = sentinel_val;
+ element_vals[instrs.len] = sentinel_val.ip_index;
}
block.instructions.shrinkRetainingCapacity(first_block_index);
- var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);
- if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);
- const array_init = try sema.addConstant(array_ty, array_val);
+ var array_val = try mod.intern(.{ .aggregate = .{
+ .ty = array_ty.ip_index,
+ .storage = .{ .elems = element_vals },
+ } });
+ if (make_runtime) array_val = try mod.intern(.{ .runtime_value = .{
+ .ty = array_ty.ip_index,
+ .val = array_val,
+ } });
+ const array_init = try sema.addConstant(array_ty, array_val.toValue());
try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
}
}
@@ -5029,7 +5058,7 @@ fn storeToInferredAllocComptime(
// There will be only one store_to_inferred_ptr because we are running at comptime.
// The alloc will turn into a Decl.
if (try sema.resolveMaybeUndefValAllowVariables(operand)) |operand_val| store: {
- if (operand_val.tagIsVariable()) break :store;
+ if (operand_val.getVariable(sema.mod) != null) break :store;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
iac.data.decl_index = try anon_decl.finish(
@@ -5717,8 +5746,8 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
{
try mod.ensureDeclAnalyzed(decl_index);
const exported_decl = mod.declPtr(decl_index);
- if (exported_decl.val.castTag(.function)) |some| {
- return sema.analyzeExport(block, src, options, some.data.owner_decl);
+ if (exported_decl.getFunction(mod)) |function| {
+ return sema.analyzeExport(block, src, options, function.owner_decl);
}
}
try sema.analyzeExport(block, src, options, decl_index);
@@ -5741,17 +5770,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
},
else => |e| return e,
};
- const decl_index = switch (operand.val.tag()) {
- .function => operand.val.castTag(.function).?.data.owner_decl,
- else => blk: {
- var anon_decl = try block.startAnonDecl();
- defer anon_decl.deinit();
- break :blk try anon_decl.finish(
- operand.ty,
- try operand.val.copy(anon_decl.arena()),
- 0,
- );
- },
+ const decl_index = if (operand.val.getFunction(sema.mod)) |function| function.owner_decl else blk: {
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ break :blk try anon_decl.finish(
+ operand.ty,
+ try operand.val.copy(anon_decl.arena()),
+ 0,
+ );
};
try sema.analyzeExport(block, src, options, decl_index);
}
@@ -5788,7 +5814,7 @@ pub fn analyzeExport(
}
// TODO: some backends might support re-exporting extern decls
- if (exported_decl.isExtern()) {
+ if (exported_decl.isExtern(mod)) {
return sema.fail(block, src, "export target cannot be extern", .{});
}
@@ -5796,7 +5822,7 @@ pub fn analyzeExport(
mod.markDeclAlive(exported_decl);
try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
- const gpa = mod.gpa;
+ const gpa = sema.gpa;
try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
try mod.export_owners.ensureUnusedCapacity(gpa, 1);
@@ -5852,8 +5878,9 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
alignment,
});
}
- const func = sema.func orelse
+ const func_index = sema.func_index.unwrap() orelse
return sema.fail(block, src, "@setAlignStack outside function body", .{});
+ const func = mod.funcPtr(func_index);
const fn_owner_decl = mod.declPtr(func.owner_decl);
switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
@@ -5864,7 +5891,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
},
}
- const gop = try mod.align_stack_fns.getOrPut(mod.gpa, func);
+ const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);
if (gop.found_existing) {
const msg = msg: {
const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
@@ -6191,10 +6218,13 @@ fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
const mod = sema.mod;
const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
if (func_val.isUndef(mod)) return null;
- const owner_decl_index = switch (func_val.tag()) {
- .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,
- .function => func_val.castTag(.function).?.data.owner_decl,
- .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
+ const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
+ .extern_func => |extern_func| extern_func.decl,
+ .func => |func| mod.funcPtr(func.index).owner_decl,
+ .ptr => |ptr| switch (ptr.addr) {
+ .decl => |decl| decl,
+ else => return null,
+ },
else => return null,
};
return mod.declPtr(owner_decl_index);
@@ -6576,20 +6606,22 @@ const GenericCallAdapter = struct {
is_anytype: bool,
};
- pub fn eql(ctx: @This(), adapted_key: void, other_key: *Module.Fn) bool {
+ pub fn eql(ctx: @This(), adapted_key: void, other_key: Module.Fn.Index) bool {
_ = adapted_key;
+ const other_func = ctx.module.funcPtr(other_key);
+
// Checking for equality may happen on an item that has been inserted
// into the map but is not yet fully initialized. In such case, the
// two initialized fields are `hash` and `generic_owner_decl`.
- if (ctx.generic_fn.owner_decl != other_key.generic_owner_decl.unwrap().?) return false;
+ if (ctx.generic_fn.owner_decl != other_func.generic_owner_decl.unwrap().?) return false;
- const other_comptime_args = other_key.comptime_args.?;
+ const other_comptime_args = other_func.comptime_args.?;
for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {
const this_arg = ctx.args[i];
const this_is_comptime = !this_arg.val.isGenericPoison();
const other_is_comptime = !other_arg.val.isGenericPoison();
const this_is_anytype = this_arg.is_anytype;
- const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i));
+ const other_is_anytype = other_func.isAnytypeParam(ctx.module, @intCast(u32, i));
if (other_is_anytype != this_is_anytype) return false;
if (other_is_comptime != this_is_comptime) return false;
@@ -6663,7 +6695,7 @@ fn analyzeCall(
);
errdefer msg.destroy(sema.gpa);
- if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
+ if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
break :msg msg;
};
return sema.failWithOwnedErrorMsg(msg);
@@ -6760,18 +6792,21 @@ fn analyzeCall(
if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
return err;
};
- const module_fn = switch (func_val.tag()) {
- .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
- .function => func_val.castTag(.function).?.data,
- .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{
+ const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
+ .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
@as([]const u8, if (is_comptime_call) "comptime" else "inline"),
}),
- else => {
- assert(callee_ty.isPtrAtRuntime(mod));
- return sema.fail(block, call_src, "{s} call of function pointer", .{
- @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
- });
+ .func => |function| function.index,
+ .ptr => |ptr| switch (ptr.addr) {
+ .decl => |decl| mod.declPtr(decl).getFunctionIndex(mod).unwrap().?,
+ else => {
+ assert(callee_ty.isPtrAtRuntime(mod));
+ return sema.fail(block, call_src, "{s} call of function pointer", .{
+ @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
+ });
+ },
},
+ else => unreachable,
};
if (func_ty_info.is_var_args) {
return sema.fail(block, call_src, "{s} call of variadic function", .{
@@ -6804,6 +6839,7 @@ fn analyzeCall(
// In order to save a bit of stack space, directly modify Sema rather
// than create a child one.
const parent_zir = sema.code;
+ const module_fn = mod.funcPtr(module_fn_index);
const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
sema.code = fn_owner_decl.getFileScope(mod).zir;
defer sema.code = parent_zir;
@@ -6819,8 +6855,11 @@ fn analyzeCall(
}
const parent_func = sema.func;
+ const parent_func_index = sema.func_index;
sema.func = module_fn;
+ sema.func_index = module_fn_index.toOptional();
defer sema.func = parent_func;
+ defer sema.func_index = parent_func_index;
const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
@@ -6856,7 +6895,7 @@ fn analyzeCall(
defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);
if (is_comptime_call) {
memoized_call_key = .{
- .func = module_fn,
+ .func = module_fn_index,
.args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
};
delete_memoized_call_key = true;
@@ -6889,7 +6928,7 @@ fn analyzeCall(
&child_block,
.unneeded,
inst,
- new_fn_info,
+ &new_fn_info,
&arg_i,
uncasted_args,
is_comptime_call,
@@ -6907,7 +6946,7 @@ fn analyzeCall(
&child_block,
mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
inst,
- new_fn_info,
+ &new_fn_info,
&arg_i,
uncasted_args,
is_comptime_call,
@@ -6950,7 +6989,7 @@ fn analyzeCall(
const fn_ret_ty = blk: {
if (module_fn.hasInferredErrorSet(mod)) {
const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
- .func = module_fn,
+ .func = module_fn_index,
});
const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
@@ -6982,7 +7021,7 @@ fn analyzeCall(
const new_func_resolved_ty = try mod.funcType(new_fn_info);
if (!is_comptime_call and !block.is_typeof) {
- try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
+ try sema.emitDbgInline(block, parent_func_index.unwrap().?, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
const zir_tags = sema.code.instructions.items(.tag);
for (fn_info.param_body) |param| switch (zir_tags[param]) {
@@ -7014,7 +7053,7 @@ fn analyzeCall(
error.ComptimeReturn => break :result inlining.comptime_result,
error.AnalysisFail => {
const err_msg = sema.err orelse return err;
- if (std.mem.eql(u8, err_msg.msg, recursive_msg)) return err;
+ if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;
try sema.errNote(block, call_src, err_msg, "called from here", .{});
err_msg.clearTrace(sema.gpa);
return err;
@@ -7027,8 +7066,8 @@ fn analyzeCall(
if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {
try sema.emitDbgInline(
block,
- module_fn,
- parent_func.?,
+ module_fn_index,
+ parent_func_index.unwrap().?,
mod.declPtr(parent_func.?.owner_decl).ty,
.dbg_inline_end,
);
@@ -7120,8 +7159,8 @@ fn analyzeCall(
}
if (try sema.resolveMaybeUndefVal(func)) |func_val| {
- if (func_val.castTag(.function)) |func_obj| {
- try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);
+ if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
+ try sema.mod.ensureFuncBodyAnalysisQueued(func_index);
}
}
@@ -7147,9 +7186,9 @@ fn analyzeCall(
// Function pointers and extern functions aren't guaranteed to
// actually be noreturn so we add a safety check for them.
check: {
- var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
- switch (func_val.tag()) {
- .function, .decl_ref => {
+ const func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
+ switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
+ .func, .extern_func, .ptr => {
_ = try block.addNoOp(.unreach);
return Air.Inst.Ref.unreachable_value;
},
@@ -7196,7 +7235,7 @@ fn analyzeInlineCallArg(
param_block: *Block,
arg_src: LazySrcLoc,
inst: Zir.Inst.Index,
- new_fn_info: InternPool.Key.FuncType,
+ new_fn_info: *InternPool.Key.FuncType,
arg_i: *usize,
uncasted_args: []const Air.Inst.Ref,
is_comptime_call: bool,
@@ -7263,7 +7302,7 @@ fn analyzeInlineCallArg(
try sema.resolveLazyValue(arg_val);
},
}
- should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
+ should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
memoized_call_key.args[arg_i.*] = .{
.ty = param_ty.toType(),
.val = arg_val,
@@ -7302,7 +7341,7 @@ fn analyzeInlineCallArg(
try sema.resolveLazyValue(arg_val);
},
}
- should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
+ should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
memoized_call_key.args[arg_i.*] = .{
.ty = sema.typeOf(uncasted_arg),
.val = arg_val,
@@ -7387,11 +7426,11 @@ fn instantiateGenericCall(
const gpa = sema.gpa;
const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");
- const module_fn = switch (func_val.tag()) {
- .function => func_val.castTag(.function).?.data,
- .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
+ const module_fn = mod.funcPtr(switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
+ .func => |function| function.index,
+ .ptr => |ptr| mod.declPtr(ptr.addr.decl).getFunctionIndex(mod).unwrap().?,
else => unreachable,
- };
+ });
// Check the Module's generic function map with an adapted context, so that we
// can match against `uncasted_args` rather than doing the work below to create a
// generic Scope only to junk it if it matches an existing instantiation.
@@ -7496,16 +7535,17 @@ fn instantiateGenericCall(
.args = generic_args,
.module = mod,
};
- const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);
- const callee = if (!gop.found_existing) callee: {
- const new_module_func = try gpa.create(Module.Fn);
+ const gop = try mod.monomorphed_funcs.getOrPutContextAdapted(gpa, {}, adapter, .{ .mod = mod });
+ const callee_index = if (!gop.found_existing) callee: {
+ const new_module_func_index = try mod.createFunc(undefined);
+ const new_module_func = mod.funcPtr(new_module_func_index);
// This ensures that we can operate on the hash map before the Module.Fn
// struct is fully initialized.
new_module_func.hash = precomputed_hash;
new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
new_module_func.comptime_args = null;
- gop.key_ptr.* = new_module_func;
+ gop.key_ptr.* = new_module_func_index;
try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
@@ -7549,7 +7589,7 @@ fn instantiateGenericCall(
new_decl_index,
uncasted_args,
module_fn,
- new_module_func,
+ new_module_func_index,
namespace_index,
func_ty_info,
call_src,
@@ -7565,12 +7605,12 @@ fn instantiateGenericCall(
}
assert(namespace.anon_decls.orderedRemove(new_decl_index));
mod.destroyDecl(new_decl_index);
- assert(mod.monomorphed_funcs.remove(new_module_func));
- gpa.destroy(new_module_func);
+ assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
+ mod.destroyFunc(new_module_func_index);
return err;
},
else => {
- assert(mod.monomorphed_funcs.remove(new_module_func));
+ assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
{
errdefer new_decl_arena.deinit();
try new_decl.finalizeNewArena(&new_decl_arena);
@@ -7590,6 +7630,7 @@ fn instantiateGenericCall(
try new_decl.finalizeNewArena(&new_decl_arena);
break :callee new_func;
} else gop.key_ptr.*;
+ const callee = mod.funcPtr(callee_index);
callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
@@ -7645,7 +7686,7 @@ fn instantiateGenericCall(
sema.owner_func.?.calls_or_awaits_errorable_fn = true;
}
- try sema.mod.ensureFuncBodyAnalysisQueued(callee);
+ try sema.mod.ensureFuncBodyAnalysisQueued(callee_index);
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
runtime_args_len);
@@ -7682,12 +7723,12 @@ fn resolveGenericInstantiationType(
new_decl_index: Decl.Index,
uncasted_args: []const Air.Inst.Ref,
module_fn: *Module.Fn,
- new_module_func: *Module.Fn,
+ new_module_func: Module.Fn.Index,
namespace: Namespace.Index,
func_ty_info: InternPool.Key.FuncType,
call_src: LazySrcLoc,
bound_arg_src: ?LazySrcLoc,
-) !*Module.Fn {
+) !Module.Fn.Index {
const mod = sema.mod;
const gpa = sema.gpa;
@@ -7707,11 +7748,13 @@ fn resolveGenericInstantiationType(
.owner_decl = new_decl,
.owner_decl_index = new_decl_index,
.func = null,
+ .func_index = .none,
.fn_ret_ty = Type.void,
.owner_func = null,
+ .owner_func_index = .none,
.comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
.comptime_args_fn_inst = module_fn.zir_body_inst,
- .preallocated_new_func = new_module_func,
+ .preallocated_new_func = new_module_func.toOptional(),
.is_generic_instantiation = true,
.branch_quota = sema.branch_quota,
.branch_count = sema.branch_count,
@@ -7802,8 +7845,8 @@ fn resolveGenericInstantiationType(
const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
- const new_func = new_func_val.castTag(.function).?.data;
- errdefer new_func.deinit(gpa);
+ const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
+ errdefer mod.destroyFunc(new_func);
assert(new_func == new_module_func);
arg_i = 0;
@@ -7867,7 +7910,10 @@ fn resolveGenericInstantiationType(
return error.GenericPoison;
}
- new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
+ new_decl.val = (try mod.intern(.{ .func = .{
+ .ty = new_decl.ty.ip_index,
+ .index = new_func,
+ } })).toValue();
new_decl.@"align" = 0;
new_decl.has_tv = true;
new_decl.owns_tv = true;
@@ -7900,8 +7946,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
fn emitDbgInline(
sema: *Sema,
block: *Block,
- old_func: *Module.Fn,
- new_func: *Module.Fn,
+ old_func: Module.Fn.Index,
+ new_func: Module.Fn.Index,
new_func_ty: Type,
tag: Air.Inst.Tag,
) CompileError!void {
@@ -7910,7 +7956,10 @@ fn emitDbgInline(
// Recursive inline call; no dbg_inline needed.
if (old_func == new_func) return;
- try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
+ try sema.air_values.append(sema.gpa, (try sema.mod.intern(.{ .func = .{
+ .ty = new_func_ty.ip_index,
+ .index = new_func,
+ } })).toValue());
_ = try block.addInst(.{
.tag = tag,
.data = .{ .ty_pl = .{
@@ -8078,12 +8127,11 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
const name = inst_data.get(sema.code);
// Create an error set type with only this error value, and return the value.
const kv = try sema.mod.getErrorValue(name);
- return sema.addConstant(
- try mod.singleErrorSetType(kv.key),
- try Value.Tag.@"error".create(sema.arena, .{
- .name = kv.key,
- }),
- );
+ const error_set_type = try mod.singleErrorSetType(kv.key);
+ return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
+ .ty = error_set_type.ip_index,
+ .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
+ } })).toValue());
}
fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
@@ -8101,23 +8149,11 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
if (val.isUndef(mod)) {
return sema.addConstUndef(Type.err_int);
}
- switch (val.tag()) {
- .@"error" => {
- return sema.addConstant(
- Type.err_int,
- try mod.intValue(
- Type.err_int,
- (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,
- ),
- );
- },
-
- // This is not a valid combination with the type `anyerror`.
- .the_only_possible_value => unreachable,
-
- // Assume it's already encoded as an integer.
- else => return sema.addConstant(Type.err_int, val),
- }
+ const err_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
+ return sema.addConstant(Type.err_int, try mod.intValue(
+ Type.err_int,
+ (try mod.getErrorValue(mod.intern_pool.stringToSlice(err_name))).value,
+ ));
}
const op_ty = sema.typeOf(uncasted_operand);
@@ -8142,23 +8178,21 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
const tracy = trace(@src());
defer tracy.end();
+ const mod = sema.mod;
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src = LazySrcLoc.nodeOffset(extra.node);
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
const uncasted_operand = try sema.resolveInst(extra.operand);
const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
- const mod = sema.mod;
if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
if (int > sema.mod.global_error_set.count() or int == 0)
return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
- const payload = try sema.arena.create(Value.Payload.Error);
- payload.* = .{
- .base = .{ .tag = .@"error" },
- .data = .{ .name = sema.mod.error_name_list.items[int] },
- };
- return sema.addConstant(Type.anyerror, Value.initPayload(&payload.base));
+ return sema.addConstant(Type.anyerror, (try mod.intern(.{ .err = .{
+ .ty = .anyerror_type,
+ .name = mod.intern_pool.getString(sema.mod.error_name_list.items[int]).unwrap().?,
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, src, operand_src);
if (block.wantSafety()) {
@@ -8234,12 +8268,12 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const tracy = trace(@src());
defer tracy.end();
+ const mod = sema.mod;
const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
- const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));
- return sema.addConstant(
- .{ .ip_index = .enum_literal_type },
- try Value.Tag.enum_literal.create(sema.arena, duped_name),
- );
+ const name = inst_data.get(sema.code);
+ return sema.addConstant(.{ .ip_index = .enum_literal_type }, (try mod.intern(.{
+ .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name),
+ })).toValue());
}
fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -8404,32 +8438,26 @@ fn analyzeOptionalPayloadPtr(
if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
if (initializing) {
- if (!ptr_val.isComptimeMutablePtr()) {
+ if (!ptr_val.isComptimeMutablePtr(mod)) {
// If the pointer resulting from this function was stored at comptime,
// the optional non-null bit would be set that way. But in this case,
// we need to emit a runtime instruction to do it.
_ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
}
- return sema.addConstant(
- child_pointer,
- try Value.Tag.opt_payload_ptr.create(sema.arena, .{
- .container_ptr = ptr_val,
- .container_ty = optional_ptr_ty.childType(mod),
- }),
- );
+ return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
+ .ty = child_pointer.ip_index,
+ .addr = .{ .opt_payload = ptr_val.ip_index },
+ } })).toValue());
}
if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
if (val.isNull(mod)) {
return sema.fail(block, src, "unable to unwrap null", .{});
}
// The same Value represents the pointer to the optional and the payload.
- return sema.addConstant(
- child_pointer,
- try Value.Tag.opt_payload_ptr.create(sema.arena, .{
- .container_ptr = ptr_val,
- .container_ty = optional_ptr_ty.childType(mod),
- }),
- );
+ return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
+ .ty = child_pointer.ip_index,
+ .addr = .{ .opt_payload = ptr_val.ip_index },
+ } })).toValue());
}
}
@@ -8532,11 +8560,13 @@ fn analyzeErrUnionPayload(
const mod = sema.mod;
const payload_ty = err_union_ty.errorUnionPayload(mod);
if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
- if (val.getError()) |name| {
+ if (val.getError(mod)) |name| {
return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
}
- const data = val.castTag(.eu_payload).?.data;
- return sema.addConstant(payload_ty, data);
+ return sema.addConstant(
+ payload_ty,
+ mod.intern_pool.indexToKey(val.ip_index).error_union.val.payload.toValue(),
+ );
}
try sema.requireRuntimeBlock(block, src, null);
@@ -8595,33 +8625,26 @@ fn analyzeErrUnionPayloadPtr(
if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {
if (initializing) {
- if (!ptr_val.isComptimeMutablePtr()) {
+ if (!ptr_val.isComptimeMutablePtr(mod)) {
// If the pointer resulting from this function was stored at comptime,
// the error union error code would be set that way. But in this case,
// we need to emit a runtime instruction to do it.
try sema.requireRuntimeBlock(block, src, null);
_ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
}
- return sema.addConstant(
- operand_pointer_ty,
- try Value.Tag.eu_payload_ptr.create(sema.arena, .{
- .container_ptr = ptr_val,
- .container_ty = operand_ty.childType(mod),
- }),
- );
+ return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
+ .ty = operand_pointer_ty.ip_index,
+ .addr = .{ .eu_payload = ptr_val.ip_index },
+ } })).toValue());
}
if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
- if (val.getError()) |name| {
+ if (val.getError(mod)) |name| {
return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
}
-
- return sema.addConstant(
- operand_pointer_ty,
- try Value.Tag.eu_payload_ptr.create(sema.arena, .{
- .container_ptr = ptr_val,
- .container_ty = operand_ty.childType(mod),
- }),
- );
+ return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
+ .ty = operand_pointer_ty.ip_index,
+ .addr = .{ .eu_payload = ptr_val.ip_index },
+ } })).toValue());
}
}
@@ -8664,7 +8687,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
const result_ty = operand_ty.errorUnionSet(mod);
if (try sema.resolveDefinedValue(block, src, operand)) |val| {
- assert(val.getError() != null);
+ assert(val.getError(mod) != null);
return sema.addConstant(result_ty, val);
}
@@ -8694,7 +8717,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
- assert(val.getError() != null);
+ assert(val.getError(mod) != null);
return sema.addConstant(result_ty, val);
}
}
@@ -8931,20 +8954,21 @@ fn funcCommon(
}
var destroy_fn_on_error = false;
- const new_func: *Module.Fn = new_func: {
+ const new_func_index = new_func: {
if (!has_body) break :new_func undefined;
if (sema.comptime_args_fn_inst == func_inst) {
- const new_func = sema.preallocated_new_func.?;
- sema.preallocated_new_func = null; // take ownership
- break :new_func new_func;
+ const new_func_index = sema.preallocated_new_func.unwrap().?;
+ sema.preallocated_new_func = .none; // take ownership
+ break :new_func new_func_index;
}
destroy_fn_on_error = true;
- const new_func = try gpa.create(Module.Fn);
+ var new_func: Module.Fn = undefined;
// Set this here so that the inferred return type can be printed correctly if it appears in an error.
new_func.owner_decl = sema.owner_decl_index;
- break :new_func new_func;
+ const new_func_index = try mod.createFunc(new_func);
+ break :new_func new_func_index;
};
- errdefer if (destroy_fn_on_error) gpa.destroy(new_func);
+ errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
const target = sema.mod.getTarget();
const fn_ty: Type = fn_ty: {
@@ -9008,7 +9032,7 @@ fn funcCommon(
else blk: {
try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
- .func = new_func,
+ .func = new_func_index,
});
const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
@@ -9158,26 +9182,16 @@ fn funcCommon(
sema.owner_decl.@"addrspace" = address_space orelse .generic;
if (is_extern) {
- const new_extern_fn = try gpa.create(Module.ExternFn);
- errdefer gpa.destroy(new_extern_fn);
-
- new_extern_fn.* = Module.ExternFn{
- .owner_decl = sema.owner_decl_index,
- .lib_name = null,
- };
-
- if (opt_lib_name) |lib_name| {
- new_extern_fn.lib_name = try sema.handleExternLibName(block, .{
- .node_offset_lib_name = src_node_offset,
- }, lib_name);
- }
-
- const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn);
- extern_fn_payload.* = .{
- .base = .{ .tag = .extern_fn },
- .data = new_extern_fn,
- };
- return sema.addConstant(fn_ty, Value.initPayload(&extern_fn_payload.base));
+ return sema.addConstant(fn_ty, (try mod.intern(.{ .extern_func = .{
+ .ty = fn_ty.ip_index,
+ .decl = sema.owner_decl_index,
+ .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
+ gpa,
+ try sema.handleExternLibName(block, .{
+ .node_offset_lib_name = src_node_offset,
+ }, lib_name),
+ )).toOptional() else .none,
+ } })).toValue());
}
if (!has_body) {
@@ -9191,9 +9205,9 @@ fn funcCommon(
break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
} else null;
+ const new_func = mod.funcPtr(new_func_index);
const hash = new_func.hash;
const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
- const fn_payload = try sema.arena.create(Value.Payload.Function);
new_func.* = .{
.state = anal_state,
.zir_body_inst = func_inst,
@@ -9208,11 +9222,10 @@ fn funcCommon(
.branch_quota = default_branch_quota,
.is_noinline = is_noinline,
};
- fn_payload.* = .{
- .base = .{ .tag = .function },
- .data = new_func,
- };
- return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
+ return sema.addConstant(fn_ty, (try mod.intern(.{ .func = .{
+ .ty = fn_ty.ip_index,
+ .index = new_func_index,
+ } })).toValue());
}
fn analyzeParameter(
@@ -9312,7 +9325,7 @@ fn zirParam(
const prev_preallocated_new_func = sema.preallocated_new_func;
const prev_no_partial_func_type = sema.no_partial_func_ty;
block.params = .{};
- sema.preallocated_new_func = null;
+ sema.preallocated_new_func = .none;
sema.no_partial_func_ty = true;
defer {
block.params.deinit(sema.gpa);
@@ -9369,7 +9382,7 @@ fn zirParam(
else => |e| return e,
} or comptime_syntax;
if (sema.inst_map.get(inst)) |arg| {
- if (is_comptime and sema.preallocated_new_func != null) {
+ if (is_comptime and sema.preallocated_new_func != .none) {
// We have a comptime value for this parameter so it should be elided from the
// function type of the function instruction in this block.
const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
@@ -9392,7 +9405,7 @@ fn zirParam(
assert(sema.inst_map.remove(inst));
}
- if (sema.preallocated_new_func != null) {
+ if (sema.preallocated_new_func != .none) {
if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
// In this case we are instantiating a generic function call with a non-comptime
// non-anytype parameter that ended up being a one-possible-type.
@@ -9640,8 +9653,8 @@ fn intCast(
if (wanted_bits == 0) {
const ok = if (is_vector) ok: {
- const zeros = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
- const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
+ const zeros = try sema.splat(operand_ty, try mod.intValue(operand_scalar_ty, 0));
+ const zero_inst = try sema.addConstant(operand_ty, zeros);
const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
const all_in_range = try block.addInst(.{
.tag = .reduce,
@@ -9649,7 +9662,7 @@ fn intCast(
});
break :ok all_in_range;
} else ok: {
- const zero_inst = try sema.addConstant(sema.typeOf(operand), try mod.intValue(operand_ty, 0));
+ const zero_inst = try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0));
const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
break :ok is_in_range;
};
@@ -9673,10 +9686,7 @@ fn intCast(
// requirement: int value fits into target type
if (wanted_value_bits < actual_value_bits) {
const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_ty);
- const dest_max_val = if (is_vector)
- try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar)
- else
- dest_max_val_scalar;
+ const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
const dest_max = try sema.addConstant(operand_ty, dest_max_val);
const diff = try block.addBinOp(.subwrap, dest_max, operand);
@@ -9732,7 +9742,8 @@ fn intCast(
// no shrinkage, yes sign loss
// requirement: signed to unsigned >= 0
const ok = if (is_vector) ok: {
- const zero_val = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
+ const scalar_zero = try mod.intValue(operand_scalar_ty, 0);
+ const zero_val = try sema.splat(operand_ty, scalar_zero);
const zero_inst = try sema.addConstant(operand_ty, zero_val);
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
const all_in_range = try block.addInst(.{
@@ -10139,17 +10150,18 @@ fn zirSwitchCapture(
.@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
.@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
});
- return sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = union_val,
- .container_ty = operand_ty,
- .field_index = field_index,
- }),
- );
+ return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = union_val.ip_index,
+ .index = field_index,
+ } },
+ } })).toValue());
}
- const tag_and_val = union_val.castTag(.@"union").?.data;
- return sema.addConstant(field_ty, tag_and_val.val);
+ return sema.addConstant(
+ field_ty,
+ mod.intern_pool.indexToKey(union_val.ip_index).un.val.toValue(),
+ );
}
if (is_ref) {
const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
@@ -10243,14 +10255,13 @@ fn zirSwitchCapture(
});
if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
- return sema.addConstant(
- field_ty_ptr,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = op_ptr_val,
- .container_ty = operand_ty,
- .field_index = first_field_index,
- }),
- );
+ return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
+ .ty = field_ty_ptr.ip_index,
+ .addr = .{ .field = .{
+ .base = op_ptr_val.ip_index,
+ .index = first_field_index,
+ } },
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, operand_src, null);
return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
@@ -10273,7 +10284,7 @@ fn zirSwitchCapture(
const item_ref = try sema.resolveInst(item);
// Previous switch validation ensured this will succeed
const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
- const name_ip = try mod.intern_pool.getOrPutString(gpa, item_val.getError().?);
+ const name_ip = try mod.intern_pool.getOrPutString(gpa, item_val.getError(mod).?);
names.putAssumeCapacityNoClobber(name_ip, {});
}
const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
@@ -10284,7 +10295,7 @@ fn zirSwitchCapture(
// Previous switch validation ensured this will succeed
const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
- const item_ty = try mod.singleErrorSetType(item_val.getError().?);
+ const item_ty = try mod.singleErrorSetType(item_val.getError(mod).?);
return sema.bitCast(block, item_ty, operand, operand_src, null);
}
},
@@ -10809,10 +10820,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
check_range: {
if (operand_ty.zigTypeTag(mod) == .Int) {
- var arena = std.heap.ArenaAllocator.init(gpa);
- defer arena.deinit();
-
- const min_int = try operand_ty.minInt(arena.allocator(), mod);
+ const min_int = try operand_ty.minInt(mod);
const max_int = try operand_ty.maxIntScalar(mod, Type.comptime_int);
if (try range_set.spans(min_int, max_int, operand_ty)) {
if (special_prong == .@"else") {
@@ -11493,8 +11501,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
if (seen_errors.contains(error_name)) continue;
cases_len += 1;
- const item_val = try Value.Tag.@"error".create(sema.arena, .{ .name = error_name });
- const item_ref = try sema.addConstant(operand_ty, item_val);
+ const item_val = try mod.intern(.{ .err = .{
+ .ty = operand_ty.ip_index,
+ .name = error_name_ip,
+ } });
+ const item_ref = try sema.addConstant(operand_ty, item_val.toValue());
case_block.inline_case_capture = item_ref;
case_block.instructions.shrinkRetainingCapacity(0);
@@ -11665,7 +11676,7 @@ const RangeSetUnhandledIterator = struct {
fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
const mod = sema.mod;
- const min = try ty.minInt(sema.arena, mod);
+ const min = try ty.minInt(mod);
const max = try ty.maxIntScalar(mod, Type.comptime_int);
return RangeSetUnhandledIterator{
@@ -11788,9 +11799,10 @@ fn validateSwitchItemError(
src_node_offset: i32,
switch_prong_src: Module.SwitchProngSrc,
) CompileError!void {
+ const ip = &sema.mod.intern_pool;
const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
// TODO: Do i need to typecheck here?
- const error_name = item_tv.val.castTag(.@"error").?.data.name;
+ const error_name = ip.stringToSlice(ip.indexToKey(item_tv.val.ip_index).err.name);
const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
prev.value
else
@@ -11983,7 +11995,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind
}
if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
if (!operand_ty.isError(mod)) return;
- if (val.getError() == null) return;
+ if (val.getError(mod) == null) return;
try sema.maybeErrorUnwrapComptime(block, body, err_operand);
}
}
@@ -12005,7 +12017,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
const src = inst_data.src();
if (try sema.resolveDefinedValue(block, src, operand)) |val| {
- if (val.getError()) |name| {
+ if (val.getError(sema.mod)) |name| {
return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
}
}
@@ -12172,11 +12184,11 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
// Return the error code from the function.
const kv = try mod.getErrorValue(err_name);
- const result_inst = try sema.addConstant(
- try mod.singleErrorSetType(kv.key),
- try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
- );
- return result_inst;
+ const error_set_type = try mod.singleErrorSetType(kv.key);
+ return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
+ .ty = error_set_type.ip_index,
+ .name = mod.intern_pool.getString(kv.key).unwrap().?,
+ } })).toValue());
}
fn zirShl(
@@ -12301,7 +12313,7 @@ fn zirShl(
{
const max_int = try sema.addConstant(
lhs_ty,
- try lhs_ty.maxInt(sema.arena, mod, lhs_ty),
+ try lhs_ty.maxInt(mod, lhs_ty),
);
const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });
break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
@@ -12316,7 +12328,7 @@ fn zirShl(
if (!std.math.isPowerOfTwo(bit_count)) {
const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);
const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
- const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
+ const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
break :ok try block.addInst(.{
.tag = .reduce,
@@ -12466,7 +12478,7 @@ fn zirShr(
const bit_count_val = try mod.intValue(scalar_ty, bit_count);
const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
- const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
+ const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
break :ok try block.addInst(.{
.tag = .reduce,
@@ -13179,11 +13191,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
}
- const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
- try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
- else
- try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
-
+ const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
}
@@ -13203,11 +13211,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),
}
- const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
- try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
- else
- try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
-
+ const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
}
@@ -13254,8 +13258,6 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
});
- const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
-
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
@@ -13325,9 +13327,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
else => unreachable,
};
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
}
@@ -13427,8 +13427,6 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
});
- const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
-
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
@@ -13469,9 +13467,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
else => unreachable,
};
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
}
@@ -13555,7 +13551,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
else => unreachable,
};
if (resolved_type.zigTypeTag(mod) == .Vector) {
- const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
const zero = try sema.addConstant(resolved_type, zero_val);
const eql = try block.addCmpVector(remainder, zero, .eq);
break :ok try block.addInst(.{
@@ -13600,8 +13596,6 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
});
- const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
-
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
@@ -13644,9 +13638,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
else => unreachable,
};
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
}
@@ -13721,8 +13713,6 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
});
- const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
-
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
@@ -13765,9 +13755,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
else => unreachable,
};
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
}
@@ -13843,12 +13831,9 @@ fn addDivIntOverflowSafety(
return;
}
- const min_int = try resolved_type.minInt(sema.arena, mod);
+ const min_int = try resolved_type.minInt(mod);
const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
- const neg_one = if (resolved_type.zigTypeTag(mod) == .Vector)
- try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
- else
- neg_one_scalar;
+ const neg_one = try sema.splat(resolved_type, neg_one_scalar);
// If the LHS is comptime-known to be not equal to the min int,
// no overflow is possible.
@@ -13924,7 +13909,7 @@ fn addDivByZeroSafety(
else
try mod.floatValue(resolved_type.scalarType(mod), 0);
const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
- const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
const zero = try sema.addConstant(resolved_type, zero_val);
const ok = try block.addCmpVector(casted_rhs, zero, .neq);
break :ok try block.addInst(.{
@@ -14012,9 +13997,10 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
else => unreachable,
};
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = if (is_vector) (try mod.intern(.{ .aggregate = .{
+ .ty = resolved_type.ip_index,
+ .storage = .{ .repeated_elem = scalar_zero.ip_index },
+ } })).toValue() else scalar_zero;
return sema.addConstant(resolved_type, zero_val);
}
} else if (lhs_scalar_ty.isSignedInt(mod)) {
@@ -14399,12 +14385,12 @@ fn zirOverflowArithmetic(
// Otherwise, if either of the argument is undefined, undefined is returned.
if (maybe_lhs_val) |lhs_val| {
if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
}
}
if (maybe_rhs_val) |rhs_val| {
if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
}
}
if (maybe_lhs_val) |lhs_val| {
@@ -14425,7 +14411,7 @@ fn zirOverflowArithmetic(
if (rhs_val.isUndef(mod)) {
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
} else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
} else if (maybe_lhs_val) |lhs_val| {
if (lhs_val.isUndef(mod)) {
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
@@ -14444,9 +14430,9 @@ fn zirOverflowArithmetic(
if (maybe_lhs_val) |lhs_val| {
if (!lhs_val.isUndef(mod)) {
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
- } else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
+ } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
}
}
}
@@ -14454,9 +14440,9 @@ fn zirOverflowArithmetic(
if (maybe_rhs_val) |rhs_val| {
if (!rhs_val.isUndef(mod)) {
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
- } else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
+ } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
}
}
}
@@ -14478,12 +14464,12 @@ fn zirOverflowArithmetic(
// Oterhwise if either of the arguments is undefined, both results are undefined.
if (maybe_lhs_val) |lhs_val| {
if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
}
}
if (maybe_rhs_val) |rhs_val| {
if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
- break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
+ break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
}
}
if (maybe_lhs_val) |lhs_val| {
@@ -14544,10 +14530,14 @@ fn zirOverflowArithmetic(
return block.addAggregateInit(tuple_ty, element_refs);
}
-fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {
+fn splat(sema: *Sema, ty: Type, val: Value) !Value {
const mod = sema.mod;
if (ty.zigTypeTag(mod) != .Vector) return val;
- return Value.Tag.repeated.create(sema.arena, val);
+ const repeated = try mod.intern(.{ .aggregate = .{
+ .ty = ty.ip_index,
+ .storage = .{ .repeated_elem = val.ip_index },
+ } });
+ return repeated.toValue();
}
fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
@@ -14603,8 +14593,6 @@ fn analyzeArithmetic(
.override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
});
- const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
-
const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
@@ -14853,9 +14841,7 @@ fn analyzeArithmetic(
} else if (resolved_type.isAnyFloat()) {
break :lz;
}
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -14886,9 +14872,7 @@ fn analyzeArithmetic(
} else if (resolved_type.isAnyFloat()) {
break :rz;
}
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -14931,9 +14915,7 @@ fn analyzeArithmetic(
if (maybe_lhs_val) |lhs_val| {
if (!lhs_val.isUndef(mod)) {
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -14947,9 +14929,7 @@ fn analyzeArithmetic(
return sema.addConstUndef(resolved_type);
}
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -14979,9 +14959,7 @@ fn analyzeArithmetic(
if (maybe_lhs_val) |lhs_val| {
if (!lhs_val.isUndef(mod)) {
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -14994,9 +14972,7 @@ fn analyzeArithmetic(
return sema.addConstUndef(resolved_type);
}
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
- const zero_val = if (is_vector) b: {
- break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
- } else scalar_zero;
+ const zero_val = try sema.splat(resolved_type, scalar_zero);
return sema.addConstant(resolved_type, zero_val);
}
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
@@ -15138,7 +15114,7 @@ fn analyzePtrArithmetic(
if (air_tag == .ptr_sub) {
return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
}
- const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int, sema.mod);
+ const new_ptr_val = try ptr_val.elemPtr(ptr_ty, offset_int, sema.mod);
return sema.addConstant(new_ptr_ty, new_ptr_val);
} else break :rs offset_src;
} else break :rs ptr_src;
@@ -15184,7 +15160,7 @@ fn zirAsm(
const inputs_len = @truncate(u5, extended.small >> 5);
const clobbers_len = @truncate(u5, extended.small >> 10);
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
- const is_global_assembly = sema.func == null;
+ const is_global_assembly = sema.func_index == .none;
const asm_source: []const u8 = if (tmpl_is_expr) blk: {
const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);
@@ -15387,12 +15363,7 @@ fn zirCmpEq(
if (lval.isUndef(mod) or rval.isUndef(mod)) {
return sema.addConstUndef(Type.bool);
}
- // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
- // or calling to Module.getErrorValue to get the values and then compare them is
- // faster.
- const lhs_name = lval.castTag(.@"error").?.data.name;
- const rhs_name = rval.castTag(.@"error").?.data.name;
- if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
+ if (lval.toIntern() == rval.toIntern()) {
return Air.Inst.Ref.bool_true;
} else {
return Air.Inst.Ref.bool_false;
@@ -15650,8 +15621,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
.AnyFrame,
=> {},
}
- const val = try ty.lazyAbiSize(mod, sema.arena);
- if (val.isLazySize()) {
+ const val = try ty.lazyAbiSize(mod);
+ if (val.isLazySize(mod)) {
try sema.queueFullTypeResolution(ty);
}
return sema.addConstant(Type.comptime_int, val);
@@ -15760,11 +15731,11 @@ fn zirClosureGet(
scope = scope.parent.?;
};
- if (tv.val.ip_index == .unreachable_value and !block.is_typeof and sema.func == null) {
+ if (tv.val.ip_index == .unreachable_value and !block.is_typeof and sema.func_index == .none) {
const msg = msg: {
const name = name: {
const file = sema.owner_decl.getFileScope(mod);
- const tree = file.getTree(mod.gpa) catch |err| {
+ const tree = file.getTree(sema.gpa) catch |err| {
// In this case we emit a warning + a less precise source location.
log.warn("unable to load {s}: {s}", .{
file.sub_file_path, @errorName(err),
@@ -15788,11 +15759,11 @@ fn zirClosureGet(
return sema.failWithOwnedErrorMsg(msg);
}
- if (tv.val.ip_index == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) {
+ if (tv.val.ip_index == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func_index != .none) {
const msg = msg: {
const name = name: {
const file = sema.owner_decl.getFileScope(mod);
- const tree = file.getTree(mod.gpa) catch |err| {
+ const tree = file.getTree(sema.gpa) catch |err| {
// In this case we emit a warning + a less precise source location.
log.warn("unable to load {s}: {s}", .{
file.sub_file_path, @errorName(err),
@@ -15868,14 +15839,17 @@ fn zirBuiltinSrc(
const func_name_val = blk: {
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
- const name = std.mem.span(fn_owner_decl.name);
+ const name = mem.span(fn_owner_decl.name);
const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
const new_decl = try anon_decl.finish(
try Type.array(anon_decl.arena(), bytes.len - 1, try mod.intValue(Type.u8, 0), Type.u8, mod),
try Value.Tag.bytes.create(anon_decl.arena(), bytes),
0, // default alignment
);
- break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
+ break :blk try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_sentinel_0_type,
+ .addr = .{ .decl = new_decl },
+ } });
};
const file_name_val = blk: {
@@ -15888,27 +15862,35 @@ fn zirBuiltinSrc(
try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
0, // default alignment
);
- break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
+ break :blk try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_sentinel_0_type,
+ .addr = .{ .decl = new_decl },
+ } });
};
- const field_values = try sema.arena.alloc(Value, 4);
- // file: [:0]const u8,
- field_values[0] = file_name_val;
- // fn_name: [:0]const u8,
- field_values[1] = func_name_val;
- // line: u32
- field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try mod.intValue(Type.u32, extra.line + 1));
- // column: u32,
- field_values[3] = try mod.intValue(Type.u32, extra.column + 1);
-
- return sema.addConstant(
- try sema.getBuiltinType("SourceLocation"),
- try Value.Tag.aggregate.create(sema.arena, field_values),
- );
+ const src_loc_ty = try sema.getBuiltinType("SourceLocation");
+ const fields = .{
+ // file: [:0]const u8,
+ file_name_val,
+ // fn_name: [:0]const u8,
+ func_name_val,
+ // line: u32,
+ try mod.intern(.{ .runtime_value = .{
+ .ty = .u32_type,
+ .val = (try mod.intValue(Type.u32, extra.line + 1)).ip_index,
+ } }),
+ // column: u32,
+ (try mod.intValue(Type.u32, extra.column + 1)).ip_index,
+ };
+ return sema.addConstant(src_loc_ty, (try mod.intern(.{ .aggregate = .{
+ .ty = src_loc_ty.ip_index,
+ .storage = .{ .elems = &fields },
+ } })).toValue());
}
fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const mod = sema.mod;
+ const gpa = sema.gpa;
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
const ty = try sema.resolveType(block, src, inst_data.operand);
@@ -15916,69 +15898,20 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const type_info_tag_ty = type_info_ty.unionTagType(mod).?;
switch (ty.zigTypeTag(mod)) {
- .Type => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Type)),
- .val = Value.void,
- }),
- ),
- .Void => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Void)),
- .val = Value.void,
- }),
- ),
- .Bool => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Bool)),
- .val = Value.void,
- }),
- ),
- .NoReturn => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.NoReturn)),
- .val = Value.void,
- }),
- ),
- .ComptimeFloat => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ComptimeFloat)),
- .val = Value.void,
- }),
- ),
- .ComptimeInt => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ComptimeInt)),
- .val = Value.void,
- }),
- ),
- .Undefined => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Undefined)),
- .val = Value.void,
- }),
- ),
- .Null => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Null)),
- .val = Value.void,
- }),
- ),
- .EnumLiteral => return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.EnumLiteral)),
- .val = Value.void,
- }),
- ),
+ .Type,
+ .Void,
+ .Bool,
+ .NoReturn,
+ .ComptimeFloat,
+ .ComptimeInt,
+ .Undefined,
+ .Null,
+ .EnumLiteral,
+ => |type_info_tag| return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(type_info_tag))).ip_index,
+ .val = .void_value,
+ } })).toValue()),
.Fn => {
// TODO: look into memoizing this result.
const info = mod.typeToFunc(ty).?;
@@ -15986,11 +15919,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
var params_anon_decl = try block.startAnonDecl();
defer params_anon_decl.deinit();
- const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
+ const fn_info_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Fn",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
+ try sema.ensureDeclAnalyzed(fn_info_decl_index);
+ const fn_info_decl = mod.declPtr(fn_info_decl_index);
+ const fn_info_ty = fn_info_decl.val.toType();
+
+ const param_info_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ fn_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Param",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
+ try sema.ensureDeclAnalyzed(param_info_decl_index);
+ const param_info_decl = mod.declPtr(param_info_decl_index);
+ const param_info_ty = param_info_decl.val.toType();
+
+ const param_vals = try gpa.alloc(InternPool.Index, info.param_types.len);
+ defer gpa.free(param_vals);
for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {
const is_generic = param_ty == .generic_poison_type;
- const param_ty_val = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
- .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
+ const param_ty_val = try mod.intern_pool.get(gpa, .{ .opt = .{
+ .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
.val = if (is_generic) .none else param_ty,
} });
@@ -15999,87 +15955,74 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
break :blk @truncate(u1, info.noalias_bits >> index) != 0;
};
- const param_fields = try params_anon_decl.arena().create([3]Value);
- param_fields.* = .{
+ const param_fields = .{
// is_generic: bool,
- Value.makeBool(is_generic),
+ Value.makeBool(is_generic).ip_index,
// is_noalias: bool,
- Value.makeBool(is_noalias),
+ Value.makeBool(is_noalias).ip_index,
// type: ?type,
- param_ty_val.toValue(),
+ param_ty_val,
};
- param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);
+ param_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = param_info_ty.ip_index,
+ .storage = .{ .elems = &param_fields },
+ } });
}
const args_val = v: {
- const fn_info_decl_index = (try sema.namespaceLookup(
- block,
- src,
- type_info_ty.getNamespaceIndex(mod).unwrap().?,
- "Fn",
- )).?;
- try mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
- try sema.ensureDeclAnalyzed(fn_info_decl_index);
- const fn_info_decl = mod.declPtr(fn_info_decl_index);
- const fn_ty = fn_info_decl.val.toType();
- const param_info_decl_index = (try sema.namespaceLookup(
- block,
- src,
- fn_ty.getNamespaceIndex(mod).unwrap().?,
- "Param",
- )).?;
- try mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
- try sema.ensureDeclAnalyzed(param_info_decl_index);
- const param_info_decl = mod.declPtr(param_info_decl_index);
- const param_ty = param_info_decl.val.toType();
+ const args_slice_ty = try mod.ptrType(.{
+ .elem_type = param_info_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ });
const new_decl = try params_anon_decl.finish(
try mod.arrayType(.{
.len = param_vals.len,
- .child = param_ty.ip_index,
+ .child = param_info_ty.ip_index,
.sentinel = .none,
}),
- try Value.Tag.aggregate.create(
- params_anon_decl.arena(),
- param_vals,
- ),
+ (try mod.intern(.{ .aggregate = .{
+ .ty = args_slice_ty.ip_index,
+ .storage = .{ .elems = param_vals },
+ } })).toValue(),
0, // default alignment
);
- break :v try Value.Tag.slice.create(sema.arena, .{
- .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
- .len = try mod.intValue(Type.usize, param_vals.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = args_slice_ty.ip_index,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, param_vals.len)).ip_index,
+ } });
};
- const ret_ty_opt = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
- .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
+ const ret_ty_opt = try mod.intern(.{ .opt = .{
+ .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
.val = if (info.return_type == .generic_poison_type) .none else info.return_type,
} });
const callconv_ty = try sema.getBuiltinType("CallingConvention");
- const field_values = try sema.arena.create([6]Value);
- field_values.* = .{
+ const field_values = .{
// calling_convention: CallingConvention,
- try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc)),
+ (try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc))).ip_index,
// alignment: comptime_int,
- try mod.intValue(Type.comptime_int, ty.abiAlignment(mod)),
+ (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).ip_index,
// is_generic: bool,
- Value.makeBool(info.is_generic),
+ Value.makeBool(info.is_generic).ip_index,
// is_var_args: bool,
- Value.makeBool(info.is_var_args),
+ Value.makeBool(info.is_var_args).ip_index,
// return_type: ?type,
- ret_ty_opt.toValue(),
+ ret_ty_opt,
// args: []const Fn.Param,
args_val,
};
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = fn_info_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Int => {
const signedness_ty = try sema.getBuiltinType("Signedness");
@@ -16099,24 +16042,36 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
);
},
.Float => {
- const field_values = try sema.arena.alloc(Value, 1);
- // bits: u16,
- field_values[0] = try mod.intValue(Type.u16, ty.bitSize(mod));
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ const float_info_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Float",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, float_info_decl_index);
+ try sema.ensureDeclAnalyzed(float_info_decl_index);
+ const float_info_decl = mod.declPtr(float_info_decl_index);
+ const float_ty = float_info_decl.val.toType();
+
+ const field_vals = .{
+ // bits: u16,
+ (try mod.intValue(Type.u16, ty.bitSize(mod))).ip_index,
+ };
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = float_ty.ip_index,
+ .storage = .{ .elems = &field_vals },
+ } }),
+ } })).toValue());
},
.Pointer => {
const info = ty.ptrInfo(mod);
const alignment = if (info.@"align" != 0)
try mod.intValue(Type.comptime_int, info.@"align")
else
- try info.pointee_type.lazyAbiAlignment(mod, sema.arena);
+ try info.pointee_type.lazyAbiAlignment(mod);
const addrspace_ty = try sema.getBuiltinType("AddressSpace");
const pointer_ty = t: {
@@ -16245,9 +16200,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// Build our list of Error values
// Optional value is only null if anyerror
// Value can be zero-length slice otherwise
- const error_field_vals: ?[]Value = if (ty.isAnyError(mod)) null else blk: {
+ const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
const names = ty.errorSetNames(mod);
- const vals = try fields_anon_decl.arena().alloc(Value, names.len);
+ const vals = try gpa.alloc(InternPool.Index, names.len);
+ defer gpa.free(vals);
for (vals, names) |*field_val, name_ip| {
const name = mod.intern_pool.stringToSlice(name_ip);
const name_val = v: {
@@ -16259,70 +16215,91 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ } });
};
- const error_field_fields = try fields_anon_decl.arena().create([1]Value);
- error_field_fields.* = .{
+ const error_field_fields = .{
// name: []const u8,
name_val,
};
-
- field_val.* = try Value.Tag.aggregate.create(
- fields_anon_decl.arena(),
- error_field_fields,
- );
+ field_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = error_field_ty.ip_index,
+ .storage = .{ .elems = &error_field_fields },
+ } });
}
break :blk vals;
};
// Build our ?[]const Error value
- const errors_val = if (error_field_vals) |vals| v: {
+ const slice_errors_ty = try mod.ptrType(.{
+ .elem_type = error_field_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ });
+ const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.ip_index);
+ const errors_payload_val: InternPool.Index = if (error_field_vals) |vals| v: {
+ const array_errors_ty = try mod.arrayType(.{
+ .len = vals.len,
+ .child = error_field_ty.ip_index,
+ .sentinel = .none,
+ });
const new_decl = try fields_anon_decl.finish(
- try mod.arrayType(.{
- .len = vals.len,
- .child = error_field_ty.ip_index,
- .sentinel = .none,
- }),
- try Value.Tag.aggregate.create(
- fields_anon_decl.arena(),
- vals,
- ),
+ array_errors_ty,
+ (try mod.intern(.{ .aggregate = .{
+ .ty = array_errors_ty.ip_index,
+ .storage = .{ .elems = vals },
+ } })).toValue(),
0, // default alignment
);
-
- const new_decl_val = try Value.Tag.decl_ref.create(sema.arena, new_decl);
- const slice_val = try Value.Tag.slice.create(sema.arena, .{
- .ptr = new_decl_val,
- .len = try mod.intValue(Type.usize, vals.len),
- });
- break :v try Value.Tag.opt_payload.create(sema.arena, slice_val);
- } else Value.null;
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = slice_errors_ty.ip_index,
+ .addr = .{ .decl = new_decl },
+ } });
+ } else .none;
+ const errors_val = try mod.intern(.{ .opt = .{
+ .ty = opt_slice_errors_ty.ip_index,
+ .val = errors_payload_val,
+ } });
// Construct Type{ .ErrorSet = errors_val }
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet)),
- .val = errors_val,
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet))).ip_index,
+ .val = errors_val,
+ } })).toValue());
},
.ErrorUnion => {
- const field_values = try sema.arena.alloc(Value, 2);
- // error_set: type,
- field_values[0] = ty.errorUnionSet(mod).toValue();
- // payload: type,
- field_values[1] = ty.errorUnionPayload(mod).toValue();
+ const error_union_field_ty = t: {
+ const error_union_field_ty_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "ErrorUnion",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, error_union_field_ty_decl_index);
+ try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index);
+ const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index);
+ break :t error_union_field_ty_decl.val.toType();
+ };
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ const field_values = .{
+ // error_set: type,
+ ty.errorUnionSet(mod).ip_index,
+ // payload: type,
+ ty.errorUnionPayload(mod).ip_index,
+ };
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = error_union_field_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Enum => {
// TODO: look into memoizing this result.
@@ -16346,7 +16323,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
break :t enum_field_ty_decl.val.toType();
};
- const enum_field_vals = try fields_anon_decl.arena().alloc(Value, enum_type.names.len);
+ const enum_field_vals = try gpa.alloc(InternPool.Index, enum_type.names.len);
+ defer gpa.free(enum_field_vals);
for (enum_field_vals, 0..) |*field_val, i| {
const name_ip = enum_type.names[i];
@@ -16360,56 +16338,81 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ } });
};
- const enum_field_fields = try fields_anon_decl.arena().create([2]Value);
- enum_field_fields.* = .{
+ const enum_field_fields = .{
// name: []const u8,
name_val,
// value: comptime_int,
- try mod.intValue(Type.comptime_int, i),
+ (try mod.intValue(Type.comptime_int, i)).ip_index,
};
- field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), enum_field_fields);
+ field_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = enum_field_ty.ip_index,
+ .storage = .{ .elems = &enum_field_fields },
+ } });
}
const fields_val = v: {
+ const fields_array_ty = try mod.arrayType(.{
+ .len = enum_field_vals.len,
+ .child = enum_field_ty.ip_index,
+ .sentinel = .none,
+ });
const new_decl = try fields_anon_decl.finish(
- try mod.arrayType(.{
- .len = enum_field_vals.len,
- .child = enum_field_ty.ip_index,
- .sentinel = .none,
- }),
- try Value.Tag.aggregate.create(
- fields_anon_decl.arena(),
- enum_field_vals,
- ),
+ fields_array_ty,
+ (try mod.intern(.{ .aggregate = .{
+ .ty = fields_array_ty.ip_index,
+ .storage = .{ .elems = enum_field_vals },
+ } })).toValue(),
0, // default alignment
);
- break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = (try mod.ptrType(.{
+ .elem_type = enum_field_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ })).ip_index,
+ .addr = .{ .decl = new_decl },
+ } });
};
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, enum_type.namespace);
- const field_values = try sema.arena.create([4]Value);
- field_values.* = .{
+ const type_enum_ty = t: {
+ const type_enum_ty_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Enum",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, type_enum_ty_decl_index);
+ try sema.ensureDeclAnalyzed(type_enum_ty_decl_index);
+ const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index);
+ break :t type_enum_ty_decl.val.toType();
+ };
+
+ const field_values = .{
// tag_type: type,
- enum_type.tag_ty.toValue(),
+ enum_type.tag_ty,
// fields: []const EnumField,
fields_val,
// decls: []const Declaration,
decls_val,
// is_exhaustive: bool,
- is_exhaustive,
+ is_exhaustive.ip_index,
};
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = type_enum_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Union => {
// TODO: look into memoizing this result.
@@ -16417,6 +16420,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
+ const type_union_ty = t: {
+ const type_union_ty_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Union",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, type_union_ty_decl_index);
+ try sema.ensureDeclAnalyzed(type_union_ty_decl_index);
+ const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index);
+ break :t type_union_ty_decl.val.toType();
+ };
+
const union_field_ty = t: {
const union_field_ty_decl_index = (try sema.namespaceLookup(
block,
@@ -16435,7 +16451,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const layout = union_ty.containerLayout(mod);
const union_fields = union_ty.unionFields(mod);
- const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());
+ const union_field_vals = try gpa.alloc(InternPool.Index, union_fields.count());
+ defer gpa.free(union_field_vals);
for (union_field_vals, 0..) |*field_val, i| {
const field = union_fields.values()[i];
@@ -16449,51 +16466,62 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ } });
};
- const union_field_fields = try fields_anon_decl.arena().create([3]Value);
const alignment = switch (layout) {
.Auto, .Extern => try sema.unionFieldAlignment(field),
.Packed => 0,
};
- union_field_fields.* = .{
+ const union_field_fields = .{
// name: []const u8,
name_val,
// type: type,
- field.ty.toValue(),
+ field.ty.ip_index,
// alignment: comptime_int,
- try mod.intValue(Type.comptime_int, alignment),
+ (try mod.intValue(Type.comptime_int, alignment)).ip_index,
};
- field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), union_field_fields);
+ field_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = union_field_ty.ip_index,
+ .storage = .{ .elems = &union_field_fields },
+ } });
}
const fields_val = v: {
+ const array_fields_ty = try mod.arrayType(.{
+ .len = union_field_vals.len,
+ .child = union_field_ty.ip_index,
+ .sentinel = .none,
+ });
const new_decl = try fields_anon_decl.finish(
- try mod.arrayType(.{
- .len = union_field_vals.len,
- .child = union_field_ty.ip_index,
- .sentinel = .none,
- }),
- try Value.Tag.aggregate.create(
- fields_anon_decl.arena(),
- try fields_anon_decl.arena().dupe(Value, union_field_vals),
- ),
+ array_fields_ty,
+ (try mod.intern(.{ .aggregate = .{
+ .ty = array_fields_ty.ip_index,
+ .storage = .{ .elems = union_field_vals },
+ } })).toValue(),
0, // default alignment
);
- break :v try Value.Tag.slice.create(sema.arena, .{
- .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
- .len = try mod.intValue(Type.usize, union_field_vals.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = (try mod.ptrType(.{
+ .elem_type = union_field_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ })).ip_index,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, union_field_vals.len)).ip_index,
+ } });
};
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespaceIndex(mod));
- const enum_tag_ty_val = if (union_ty.unionTagType(mod)) |tag_ty| v: {
- const ty_val = tag_ty.toValue();
- break :v try Value.Tag.opt_payload.create(sema.arena, ty_val);
- } else Value.null;
+ const enum_tag_ty_val = try mod.intern(.{ .opt = .{
+ .ty = (try mod.optionalType(.type_type)).ip_index,
+ .val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.ip_index else .none,
+ } });
const container_layout_ty = t: {
const decl_index = (try sema.namespaceLookup(
@@ -16508,10 +16536,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
break :t decl.val.toType();
};
- const field_values = try sema.arena.create([4]Value);
- field_values.* = .{
+ const field_values = .{
// layout: ContainerLayout,
- try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),
+ (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
// tag_type: ?type,
enum_tag_ty_val,
@@ -16520,14 +16547,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// decls: []const Declaration,
decls_val,
};
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = type_union_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Struct => {
// TODO: look into memoizing this result.
@@ -16535,6 +16562,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
var fields_anon_decl = try block.startAnonDecl();
defer fields_anon_decl.deinit();
+ const type_struct_ty = t: {
+ const type_struct_ty_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Struct",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, type_struct_ty_decl_index);
+ try sema.ensureDeclAnalyzed(type_struct_ty_decl_index);
+ const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index);
+ break :t type_struct_ty_decl.val.toType();
+ };
+
const struct_field_ty = t: {
const struct_field_ty_decl_index = (try sema.namespaceLookup(
block,
@@ -16547,14 +16587,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
break :t struct_field_ty_decl.val.toType();
};
+
const struct_ty = try sema.resolveTypeFields(ty);
try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
const layout = struct_ty.containerLayout(mod);
- const struct_field_vals = fv: {
+ var struct_field_vals: []InternPool.Index = &.{};
+ defer gpa.free(struct_field_vals);
+ fv: {
const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
.anon_struct_type => |tuple| {
- const struct_field_vals = try fields_anon_decl.arena().alloc(Value, tuple.types.len);
+ struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);
for (
tuple.types,
tuple.values,
@@ -16574,38 +16617,40 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.bytes.create(anon_decl.arena(), bytes.ptr[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
- .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
- .len = try mod.intValue(Type.usize, bytes.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
+ } });
};
- const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
const is_comptime = field_val != .none;
const opt_default_val = if (is_comptime) field_val.toValue() else null;
const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
- struct_field_fields.* = .{
+ const struct_field_fields = .{
// name: []const u8,
name_val,
// type: type,
- field_ty.toValue(),
+ field_ty,
// default_value: ?*const anyopaque,
- try default_val_ptr.copy(fields_anon_decl.arena()),
+ default_val_ptr.ip_index,
// is_comptime: bool,
- Value.makeBool(is_comptime),
+ Value.makeBool(is_comptime).ip_index,
// alignment: comptime_int,
- try field_ty.toType().lazyAbiAlignment(mod, fields_anon_decl.arena()),
+ (try mod.intValue(Type.comptime_int, field_ty.toType().abiAlignment(mod))).ip_index,
};
- struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
+ struct_field_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = struct_field_ty.ip_index,
+ .storage = .{ .elems = &struct_field_fields },
+ } });
}
- break :fv struct_field_vals;
+ break :fv;
},
.struct_type => |s| s,
else => unreachable,
};
- const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
- break :fv &[0]Value{};
- const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_obj.fields.count());
+ const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :fv;
+ struct_field_vals = try gpa.alloc(InternPool.Index, struct_obj.fields.count());
for (
struct_field_vals,
@@ -16621,13 +16666,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
- .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
- .len = try mod.intValue(Type.usize, bytes.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
+ } });
};
- const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
const opt_default_val = if (field.default_val.ip_index == .unreachable_value)
null
else
@@ -16635,55 +16680,61 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);
const alignment = field.alignment(mod, layout);
- struct_field_fields.* = .{
+ const struct_field_fields = .{
// name: []const u8,
name_val,
// type: type,
- field.ty.toValue(),
+ field.ty.ip_index,
// default_value: ?*const anyopaque,
- try default_val_ptr.copy(fields_anon_decl.arena()),
+ default_val_ptr.ip_index,
// is_comptime: bool,
- Value.makeBool(field.is_comptime),
+ Value.makeBool(field.is_comptime).ip_index,
// alignment: comptime_int,
- try mod.intValue(Type.comptime_int, alignment),
+ (try mod.intValue(Type.comptime_int, alignment)).ip_index,
};
- field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
+ field_val.* = try mod.intern(.{ .aggregate = .{
+ .ty = struct_field_ty.ip_index,
+ .storage = .{ .elems = &struct_field_fields },
+ } });
}
- break :fv struct_field_vals;
- };
+ }
const fields_val = v: {
+ const array_fields_ty = try mod.arrayType(.{
+ .len = struct_field_vals.len,
+ .child = struct_field_ty.ip_index,
+ .sentinel = .none,
+ });
const new_decl = try fields_anon_decl.finish(
- try mod.arrayType(.{
- .len = struct_field_vals.len,
- .child = struct_field_ty.ip_index,
- .sentinel = .none,
- }),
- try Value.Tag.aggregate.create(
- fields_anon_decl.arena(),
- try fields_anon_decl.arena().dupe(Value, struct_field_vals),
- ),
+ array_fields_ty,
+ (try mod.intern(.{ .aggregate = .{
+ .ty = array_fields_ty.ip_index,
+ .storage = .{ .elems = struct_field_vals },
+ } })).toValue(),
0, // default alignment
);
- break :v try Value.Tag.slice.create(sema.arena, .{
- .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
- .len = try mod.intValue(Type.usize, struct_field_vals.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = (try mod.ptrType(.{
+ .elem_type = struct_field_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ })).ip_index,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, struct_field_vals.len)).ip_index,
+ } });
};
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));
- const backing_integer_val = blk: {
- if (layout == .Packed) {
+ const backing_integer_val = try mod.intern(.{ .opt = .{
+ .ty = (try mod.optionalType(.type_type)).ip_index,
+ .val = if (layout == .Packed) val: {
const struct_obj = mod.typeToStruct(struct_ty).?;
assert(struct_obj.haveLayout());
assert(struct_obj.backing_int_ty.isInt(mod));
- const backing_int_ty_val = struct_obj.backing_int_ty.toValue();
- break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);
- } else {
- break :blk Value.null;
- }
- };
+ break :val struct_obj.backing_int_ty.ip_index;
+ } else .none,
+ } });
const container_layout_ty = t: {
const decl_index = (try sema.namespaceLookup(
@@ -16698,10 +16749,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
break :t decl.val.toType();
};
- const field_values = try sema.arena.create([5]Value);
- field_values.* = .{
+ const field_values = [_]InternPool.Index{
// layout: ContainerLayout,
- try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),
+ (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
// backing_integer: ?type,
backing_integer_val,
// fields: []const StructField,
@@ -16709,36 +16759,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// decls: []const Declaration,
decls_val,
// is_tuple: bool,
- Value.makeBool(struct_ty.isTuple(mod)),
+ Value.makeBool(struct_ty.isTuple(mod)).ip_index,
};
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = type_struct_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Opaque => {
// TODO: look into memoizing this result.
+ const type_opaque_ty = t: {
+ const type_opaque_ty_decl_index = (try sema.namespaceLookup(
+ block,
+ src,
+ type_info_ty.getNamespaceIndex(mod).unwrap().?,
+ "Opaque",
+ )).?;
+ try mod.declareDeclDependency(sema.owner_decl_index, type_opaque_ty_decl_index);
+ try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index);
+ const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index);
+ break :t type_opaque_ty_decl.val.toType();
+ };
+
const opaque_ty = try sema.resolveTypeFields(ty);
const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespaceIndex(mod));
- const field_values = try sema.arena.create([1]Value);
- field_values.* = .{
+ const field_values = .{
// decls: []const Declaration,
decls_val,
};
-
- return sema.addConstant(
- type_info_ty,
- try Value.Tag.@"union".create(sema.arena, .{
- .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque)),
- .val = try Value.Tag.aggregate.create(sema.arena, field_values),
- }),
- );
+ return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
+ .ty = type_info_ty.ip_index,
+ .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque))).ip_index,
+ .val = try mod.intern(.{ .aggregate = .{
+ .ty = type_opaque_ty.ip_index,
+ .storage = .{ .elems = &field_values },
+ } }),
+ } })).toValue());
},
.Frame => return sema.failWithUseOfAsync(block, src),
.AnyFrame => return sema.failWithUseOfAsync(block, src),
@@ -16751,7 +16813,7 @@ fn typeInfoDecls(
src: LazySrcLoc,
type_info_ty: Type,
opt_namespace: Module.Namespace.OptionalIndex,
-) CompileError!Value {
+) CompileError!InternPool.Index {
const mod = sema.mod;
var decls_anon_decl = try block.startAnonDecl();
defer decls_anon_decl.deinit();
@@ -16770,7 +16832,7 @@ fn typeInfoDecls(
};
try sema.queueFullTypeResolution(declaration_ty);
- var decl_vals = std.ArrayList(Value).init(sema.gpa);
+ var decl_vals = std.ArrayList(InternPool.Index).init(sema.gpa);
defer decl_vals.deinit();
var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
@@ -16778,33 +16840,39 @@ fn typeInfoDecls(
if (opt_namespace.unwrap()) |namespace_index| {
const namespace = mod.namespacePtr(namespace_index);
- try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), namespace, &decl_vals, &seen_namespaces);
+ try sema.typeInfoNamespaceDecls(block, namespace, declaration_ty, &decl_vals, &seen_namespaces);
}
+ const array_decl_ty = try mod.arrayType(.{
+ .len = decl_vals.items.len,
+ .child = declaration_ty.ip_index,
+ .sentinel = .none,
+ });
const new_decl = try decls_anon_decl.finish(
- try mod.arrayType(.{
- .len = decl_vals.items.len,
- .child = declaration_ty.ip_index,
- .sentinel = .none,
- }),
- try Value.Tag.aggregate.create(
- decls_anon_decl.arena(),
- try decls_anon_decl.arena().dupe(Value, decl_vals.items),
- ),
+ array_decl_ty,
+ (try mod.intern(.{ .aggregate = .{
+ .ty = array_decl_ty.ip_index,
+ .storage = .{ .elems = decl_vals.items },
+ } })).toValue(),
0, // default alignment
);
- return try Value.Tag.slice.create(sema.arena, .{
- .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
- .len = try mod.intValue(Type.usize, decl_vals.items.len),
- });
+ return try mod.intern(.{ .ptr = .{
+ .ty = (try mod.ptrType(.{
+ .elem_type = declaration_ty.ip_index,
+ .size = .Slice,
+ .is_const = true,
+ })).ip_index,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, decl_vals.items.len)).ip_index,
+ } });
}
fn typeInfoNamespaceDecls(
sema: *Sema,
block: *Block,
- decls_anon_decl: Allocator,
namespace: *Namespace,
- decl_vals: *std.ArrayList(Value),
+ declaration_ty: Type,
+ decl_vals: *std.ArrayList(InternPool.Index),
seen_namespaces: *std.AutoHashMap(*Namespace, void),
) !void {
const mod = sema.mod;
@@ -16817,7 +16885,7 @@ fn typeInfoNamespaceDecls(
if (decl.analysis == .in_progress) continue;
try mod.ensureDeclAnalyzed(decl_index);
const new_ns = decl.val.toType().getNamespace(mod).?;
- try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
+ try sema.typeInfoNamespaceDecls(block, new_ns, declaration_ty, decl_vals, seen_namespaces);
continue;
}
if (decl.kind != .named) continue;
@@ -16830,20 +16898,23 @@ fn typeInfoNamespaceDecls(
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
0, // default alignment
);
- break :v try Value.Tag.slice.create(decls_anon_decl, .{
- .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
- .len = try mod.intValue(Type.usize, bytes.len),
- });
+ break :v try mod.intern(.{ .ptr = .{
+ .ty = .slice_const_u8_type,
+ .addr = .{ .decl = new_decl },
+ .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
+ } });
};
- const fields = try decls_anon_decl.create([2]Value);
- fields.* = .{
+ const fields = .{
//name: []const u8,
name_val,
//is_pub: bool,
- Value.makeBool(decl.is_pub),
+ Value.makeBool(decl.is_pub).ip_index,
};
- try decl_vals.append(try Value.Tag.aggregate.create(decls_anon_decl, fields));
+ try decl_vals.append(try mod.intern(.{ .aggregate = .{
+ .ty = declaration_ty.ip_index,
+ .storage = .{ .elems = &fields },
+ } }));
}
}
@@ -17454,10 +17525,11 @@ fn zirRetErrValue(
// Return the error code from the function.
const kv = try mod.getErrorValue(err_name);
- const result_inst = try sema.addConstant(
- try mod.singleErrorSetType(err_name),
- try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
- );
+ const error_set_type = try mod.singleErrorSetType(err_name);
+ const result_inst = try sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
+ .ty = error_set_type.ip_index,
+ .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
+ } })).toValue());
return sema.analyzeRet(block, result_inst, src);
}
@@ -17782,10 +17854,12 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");
// Check if this happens to be the lazy alignment of our element type, in
// which case we can make this 0 without resolving it.
- if (val.castTag(.lazy_align)) |payload| {
- if (payload.data.eql(elem_ty, sema.mod)) {
- break :blk .none;
- }
+ switch (mod.intern_pool.indexToKey(val.ip_index)) {
+ .int => |int| switch (int.storage) {
+ .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.ip_index) break :blk .none,
+ else => {},
+ },
+ else => {},
}
const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);
try sema.validateAlign(block, align_src, abi_align);
@@ -17910,12 +17984,10 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com
return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});
}
}
- if (obj_ty.sentinel(mod)) |sentinel| {
- const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);
- return sema.addConstant(obj_ty, val);
- } else {
- return sema.addConstant(obj_ty, Value.initTag(.empty_array));
- }
+ return sema.addConstant(obj_ty, (try mod.intern(.{ .aggregate = .{
+ .ty = obj_ty.ip_index,
+ .storage = .{ .elems = &.{} },
+ } })).toValue());
}
fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -18679,8 +18751,8 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
if (ty.isNoReturn(mod)) {
return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
}
- const val = try ty.lazyAbiAlignment(mod, sema.arena);
- if (val.isLazyAlign()) {
+ const val = try ty.lazyAbiAlignment(mod);
+ if (val.isLazyAlign(mod)) {
try sema.queueFullTypeResolution(ty);
}
return sema.addConstant(Type.comptime_int, val);
@@ -18704,7 +18776,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
- const bytes = val.castTag(.@"error").?.data.name;
+ const err_name = sema.mod.intern_pool.indexToKey(val.ip_index).err.name;
+ const bytes = sema.mod.intern_pool.stringToSlice(err_name);
return sema.addStrLit(block, bytes);
}
@@ -18794,7 +18867,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
.EnumLiteral => {
const val = try sema.resolveConstValue(block, .unneeded, operand, "");
- const bytes = val.castTag(.enum_literal).?.data;
+ const tag_name = mod.intern_pool.indexToKey(val.ip_index).enum_literal;
+ const bytes = mod.intern_pool.stringToSlice(tag_name);
return sema.addStrLit(block, bytes);
},
.Enum => operand_ty,
@@ -18883,11 +18957,8 @@ fn zirReify(
.EnumLiteral => return Air.Inst.Ref.enum_literal_type,
.Int => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const signedness_index = fields.getIndex("signedness").?;
- const bits_index = fields.getIndex("bits").?;
-
- const signedness_val = try union_val.val.fieldValue(fields.values()[signedness_index].ty, mod, signedness_index);
- const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index);
+ const signedness_val = try union_val.val.fieldValue(mod, fields.getIndex("signedness").?);
+ const bits_val = try union_val.val.fieldValue(mod, fields.getIndex("bits").?);
const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
@@ -18896,11 +18967,8 @@ fn zirReify(
},
.Vector => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const len_index = fields.getIndex("len").?;
- const child_index = fields.getIndex("child").?;
-
- const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index);
- const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
+ const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
+ const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
const len = @intCast(u32, len_val.toUnsignedInt(mod));
const child_ty = child_val.toType();
@@ -18915,9 +18983,7 @@ fn zirReify(
},
.Float => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const bits_index = fields.getIndex("bits").?;
-
- const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index);
+ const bits_val = try union_val.val.fieldValue(mod, fields.getIndex("bits").?);
const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
const ty = switch (bits) {
@@ -18932,23 +18998,14 @@ fn zirReify(
},
.Pointer => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const size_index = fields.getIndex("size").?;
- const is_const_index = fields.getIndex("is_const").?;
- const is_volatile_index = fields.getIndex("is_volatile").?;
- const alignment_index = fields.getIndex("alignment").?;
- const address_space_index = fields.getIndex("address_space").?;
- const child_index = fields.getIndex("child").?;
- const is_allowzero_index = fields.getIndex("is_allowzero").?;
- const sentinel_index = fields.getIndex("sentinel").?;
-
- const size_val = try union_val.val.fieldValue(fields.values()[size_index].ty, mod, size_index);
- const is_const_val = try union_val.val.fieldValue(fields.values()[is_const_index].ty, mod, is_const_index);
- const is_volatile_val = try union_val.val.fieldValue(fields.values()[is_volatile_index].ty, mod, is_volatile_index);
- const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index);
- const address_space_val = try union_val.val.fieldValue(fields.values()[address_space_index].ty, mod, address_space_index);
- const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
- const is_allowzero_val = try union_val.val.fieldValue(fields.values()[is_allowzero_index].ty, mod, is_allowzero_index);
- const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index);
+ const size_val = try union_val.val.fieldValue(mod, fields.getIndex("size").?);
+ const is_const_val = try union_val.val.fieldValue(mod, fields.getIndex("is_const").?);
+ const is_volatile_val = try union_val.val.fieldValue(mod, fields.getIndex("is_volatile").?);
+ const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
+ const address_space_val = try union_val.val.fieldValue(mod, fields.getIndex("address_space").?);
+ const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
+ const is_allowzero_val = try union_val.val.fieldValue(mod, fields.getIndex("is_allowzero").?);
+ const sentinel_val = try union_val.val.fieldValue(mod, fields.getIndex("sentinel").?);
if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
return sema.fail(block, src, "alignment must fit in 'u32'", .{});
@@ -19032,22 +19089,18 @@ fn zirReify(
},
.Array => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const len_index = fields.getIndex("len").?;
- const child_index = fields.getIndex("child").?;
- const sentinel_index = fields.getIndex("sentinel").?;
-
- const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index);
- const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
- const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index);
+ const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
+ const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
+ const sentinel_val = try union_val.val.fieldValue(mod, fields.getIndex("sentinel").?);
const len = len_val.toUnsignedInt(mod);
const child_ty = child_val.toType();
- const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {
+ const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {
const ptr_ty = try Type.ptr(sema.arena, mod, .{
.@"addrspace" = .generic,
.pointee_type = child_ty,
});
- break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;
+ break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
} else null;
const ty = try Type.array(sema.arena, len, sentinel, child_ty, mod);
@@ -19055,9 +19108,7 @@ fn zirReify(
},
.Optional => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const child_index = fields.getIndex("child").?;
-
- const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
+ const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
const child_ty = child_val.toType();
@@ -19066,11 +19117,8 @@ fn zirReify(
},
.ErrorUnion => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const error_set_index = fields.getIndex("error_set").?;
- const payload_index = fields.getIndex("payload").?;
-
- const error_set_val = try union_val.val.fieldValue(fields.values()[error_set_index].ty, mod, error_set_index);
- const payload_val = try union_val.val.fieldValue(fields.values()[payload_index].ty, mod, payload_index);
+ const error_set_val = try union_val.val.fieldValue(mod, fields.getIndex("error_set").?);
+ const payload_val = try union_val.val.fieldValue(mod, fields.getIndex("payload").?);
const error_set_ty = error_set_val.toType();
const payload_ty = payload_val.toType();
@@ -19085,18 +19133,17 @@ fn zirReify(
.ErrorSet => {
const payload_val = union_val.val.optionalValue(mod) orelse
return sema.addType(Type.anyerror);
- const slice_val = payload_val.castTag(.slice).?.data;
- const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod));
+ const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
var names: Module.Fn.InferredErrorSet.NameMap = .{};
try names.ensureUnusedCapacity(sema.arena, len);
for (0..len) |i| {
- const elem_val = try slice_val.ptr.elemValue(mod, i);
+ const elem_val = try payload_val.elemValue(mod, i);
const struct_val = elem_val.castTag(.aggregate).?.data;
// TODO use reflection instead of magic numbers here
// error_set: type,
const name_val = struct_val[0];
- const name_str = try name_val.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
+ const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str);
const gop = names.getOrPutAssumeCapacity(name_ip);
if (gop.found_existing) {
@@ -19109,17 +19156,11 @@ fn zirReify(
},
.Struct => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const layout_index = fields.getIndex("layout").?;
- const backing_integer_index = fields.getIndex("backing_integer").?;
- const fields_index = fields.getIndex("fields").?;
- const decls_index = fields.getIndex("decls").?;
- const is_tuple_index = fields.getIndex("is_tuple").?;
-
- const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index);
- const backing_integer_val = try union_val.val.fieldValue(fields.values()[backing_integer_index].ty, mod, backing_integer_index);
- const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
- const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
- const is_tuple_val = try union_val.val.fieldValue(fields.values()[is_tuple_index].ty, mod, is_tuple_index);
+ const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
+ const backing_integer_val = try union_val.val.fieldValue(mod, fields.getIndex("backing_integer").?);
+ const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
+ const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
+ const is_tuple_val = try union_val.val.fieldValue(mod, fields.getIndex("is_tuple").?);
const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
@@ -19136,15 +19177,10 @@ fn zirReify(
},
.Enum => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const tag_type_index = fields.getIndex("tag_type").?;
- const fields_index = fields.getIndex("fields").?;
- const decls_index = fields.getIndex("decls").?;
- const is_exhaustive_index = fields.getIndex("is_exhaustive").?;
-
- const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index);
- const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
- const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
- const is_exhaustive_val = try union_val.val.fieldValue(fields.values()[is_exhaustive_index].ty, mod, is_exhaustive_index);
+ const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
+ const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
+ const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
+ const is_exhaustive_val = try union_val.val.fieldValue(mod, fields.getIndex("is_exhaustive").?);
// Decls
if (decls_val.sliceLen(mod) > 0) {
@@ -19195,7 +19231,7 @@ fn zirReify(
const value_val = field_struct_val[1];
const field_name = try name_val.toAllocatedBytes(
- Type.const_slice_u8,
+ Type.slice_const_u8,
sema.arena,
mod,
);
@@ -19237,9 +19273,7 @@ fn zirReify(
},
.Opaque => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const decls_index = fields.getIndex("decls").?;
-
- const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
+ const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
// Decls
if (decls_val.sliceLen(mod) > 0) {
@@ -19283,15 +19317,10 @@ fn zirReify(
},
.Union => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const layout_index = fields.getIndex("layout").?;
- const tag_type_index = fields.getIndex("tag_type").?;
- const fields_index = fields.getIndex("fields").?;
- const decls_index = fields.getIndex("decls").?;
-
- const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index);
- const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index);
- const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
- const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
+ const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
+ const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
+ const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
+ const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
// Decls
if (decls_val.sliceLen(mod) > 0) {
@@ -19386,7 +19415,7 @@ fn zirReify(
const alignment_val = field_struct_val[2];
const field_name = try name_val.toAllocatedBytes(
- Type.const_slice_u8,
+ Type.slice_const_u8,
new_decl_arena_allocator,
mod,
);
@@ -19489,19 +19518,12 @@ fn zirReify(
},
.Fn => {
const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
- const calling_convention_index = fields.getIndex("calling_convention").?;
- const alignment_index = fields.getIndex("alignment").?;
- const is_generic_index = fields.getIndex("is_generic").?;
- const is_var_args_index = fields.getIndex("is_var_args").?;
- const return_type_index = fields.getIndex("return_type").?;
- const params_index = fields.getIndex("params").?;
-
- const calling_convention_val = try union_val.val.fieldValue(fields.values()[calling_convention_index].ty, mod, calling_convention_index);
- const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index);
- const is_generic_val = try union_val.val.fieldValue(fields.values()[is_generic_index].ty, mod, is_generic_index);
- const is_var_args_val = try union_val.val.fieldValue(fields.values()[is_var_args_index].ty, mod, is_var_args_index);
- const return_type_val = try union_val.val.fieldValue(fields.values()[return_type_index].ty, mod, return_type_index);
- const params_val = try union_val.val.fieldValue(fields.values()[params_index].ty, mod, params_index);
+ const calling_convention_val = try union_val.val.fieldValue(mod, fields.getIndex("calling_convention").?);
+ const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
+ const is_generic_val = try union_val.val.fieldValue(mod, fields.getIndex("is_generic").?);
+ const is_var_args_val = try union_val.val.fieldValue(mod, fields.getIndex("is_var_args").?);
+ const return_type_val = try union_val.val.fieldValue(mod, fields.getIndex("return_type").?);
+ const params_val = try union_val.val.fieldValue(mod, fields.getIndex("params").?);
const is_generic = is_generic_val.toBool(mod);
if (is_generic) {
@@ -19528,14 +19550,12 @@ fn zirReify(
const return_type = return_type_val.optionalValue(mod) orelse
return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
- const args_slice_val = params_val.castTag(.slice).?.data;
- const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod));
-
+ const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));
const param_types = try sema.arena.alloc(InternPool.Index, args_len);
var noalias_bits: u32 = 0;
for (param_types, 0..) |*param_type, i| {
- const arg = try args_slice_val.ptr.elemValue(mod, i);
+ const arg = try params_val.elemValue(mod, i);
const arg_val = arg.castTag(.aggregate).?.data;
// TODO use reflection instead of magic numbers here
// is_generic: bool,
@@ -19676,7 +19696,7 @@ fn reifyStruct(
}
const field_name = try name_val.toAllocatedBytes(
- Type.const_slice_u8,
+ Type.slice_const_u8,
new_decl_arena_allocator,
mod,
);
@@ -19707,7 +19727,7 @@ fn reifyStruct(
}
const default_val = if (default_value_val.optionalValue(mod)) |opt_val| blk: {
- const payload_val = if (opt_val.pointerDecl()) |opt_decl|
+ const payload_val = if (opt_val.pointerDecl(mod)) |opt_decl|
mod.declPtr(opt_decl).val
else
opt_val;
@@ -20137,7 +20157,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
if (maybe_operand_val) |val| {
if (!dest_ty.isAnyError(mod)) {
- const error_name = val.castTag(.@"error").?.data.name;
+ const error_name = mod.intern_pool.stringToSlice(mod.intern_pool.indexToKey(val.ip_index).err.name);
if (!dest_ty.errorSetHasField(error_name, mod)) {
const msg = msg: {
const msg = try sema.errMsg(
@@ -20279,7 +20299,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
}
if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) {
- return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val));
+ return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{
+ .ty = dest_ty.ip_index,
+ .val = operand_val.toIntern(),
+ } })).toValue());
}
return sema.addConstant(aligned_dest_ty, operand_val);
}
@@ -20944,7 +20967,7 @@ fn checkPtrIsNotComptimeMutable(
operand_src: LazySrcLoc,
) CompileError!void {
_ = operand_src;
- if (ptr_val.isComptimeMutablePtr()) {
+ if (ptr_val.isComptimeMutablePtr(sema.mod)) {
return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});
}
}
@@ -20953,7 +20976,7 @@ fn checkComptimeVarStore(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
- decl_ref_mut: Value.Payload.DeclRefMut.Data,
+ decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
) CompileError!void {
if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {
if (block.runtime_cond) |cond_src| {
@@ -21159,7 +21182,7 @@ fn resolveExportOptions(
const name_operand = try sema.fieldVal(block, src, options, "name", name_src);
const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known");
- const name_ty = Type.const_slice_u8;
+ const name_ty = Type.slice_const_u8;
const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);
const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);
@@ -21168,7 +21191,7 @@ fn resolveExportOptions(
const section_operand = try sema.fieldVal(block, src, options, "section", section_src);
const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known");
- const section_ty = Type.const_slice_u8;
+ const section_ty = Type.slice_const_u8;
const section = if (section_opt_val.optionalValue(mod)) |section_val|
try section_val.toAllocatedBytes(section_ty, sema.arena, mod)
else
@@ -21298,12 +21321,14 @@ fn zirCmpxchg(
}
const ptr_ty = sema.typeOf(ptr);
const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
- const result_val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
- try sema.storePtr(block, src, ptr, new_value);
- break :blk Value.null;
- } else try Value.Tag.opt_payload.create(sema.arena, stored_val);
-
- return sema.addConstant(result_ty, result_val);
+ const result_val = try mod.intern(.{ .opt = .{
+ .ty = result_ty.ip_index,
+ .val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
+ try sema.storePtr(block, src, ptr, new_value);
+ break :blk .none;
+ } else stored_val.toIntern(),
+ } });
+ return sema.addConstant(result_ty, result_val.toValue());
} else break :rs new_value_src;
} else break :rs expected_src;
} else ptr_src;
@@ -21342,11 +21367,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
});
if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
-
- return sema.addConstant(
- vector_ty,
- try Value.Tag.repeated.create(sema.arena, scalar_val),
- );
+ return sema.addConstant(vector_ty, try sema.splat(vector_ty, scalar_val));
}
try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src);
@@ -21800,7 +21821,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
break :rs operand_src;
};
- if (ptr_val.isComptimeMutablePtr()) {
+ if (ptr_val.isComptimeMutablePtr(mod)) {
const ptr_ty = sema.typeOf(ptr);
const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
const new_val = switch (op) {
@@ -22081,10 +22102,15 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
- const payload = field_ptr_val.castTag(.field_ptr) orelse {
- return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
- };
- if (payload.data.field_index != field_index) {
+ const field = switch (mod.intern_pool.indexToKey(field_ptr_val.ip_index)) {
+ .ptr => |ptr| switch (ptr.addr) {
+ .field => |field| field,
+ else => null,
+ },
+ else => null,
+ } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
+
+ if (field.index != field_index) {
const msg = msg: {
const msg = try sema.errMsg(
block,
@@ -22093,7 +22119,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
.{
field_name,
field_index,
- payload.data.field_index,
+ field.index,
parent_ty.fmt(sema.mod),
},
);
@@ -22103,7 +22129,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
};
return sema.failWithOwnedErrorMsg(msg);
}
- return sema.addConstant(result_ptr, payload.data.container_ptr);
+ return sema.addConstant(result_ptr, field.base.toValue());
}
try sema.requireRuntimeBlock(block, src, ptr_src);
@@ -22335,13 +22361,13 @@ fn analyzeMinMax(
// Compute the final bounds based on the runtime type and the comptime-known bound type
const min_val = switch (air_tag) {
- .min => try unrefined_elem_ty.minInt(sema.arena, mod),
- .max => try comptime_elem_ty.minInt(sema.arena, mod), // @max(ct, rt) >= ct
+ .min => try unrefined_elem_ty.minInt(mod),
+ .max => try comptime_elem_ty.minInt(mod), // @max(ct, rt) >= ct
else => unreachable,
};
const max_val = switch (air_tag) {
- .min => try comptime_elem_ty.maxInt(sema.arena, mod, Type.comptime_int), // @min(ct, rt) <= ct
- .max => try unrefined_elem_ty.maxInt(sema.arena, mod, Type.comptime_int),
+ .min => try comptime_elem_ty.maxInt(mod, Type.comptime_int), // @min(ct, rt) <= ct
+ .max => try unrefined_elem_ty.maxInt(mod, Type.comptime_int),
else => unreachable,
};
@@ -22464,7 +22490,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
}
const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
- if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src;
+ if (!dest_ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;
const len = try sema.usizeCast(block, dest_src, len_u64);
@@ -22618,7 +22644,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
return;
}
- if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;
+ if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {
for (0..len) |i| {
const elem_index = try sema.addIntUnsigned(Type.usize, i);
@@ -22696,6 +22722,7 @@ fn zirVarExtended(
block: *Block,
extended: Zir.Inst.Extended.InstData,
) CompileError!Air.Inst.Ref {
+ const mod = sema.mod;
const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
@@ -22737,32 +22764,17 @@ fn zirVarExtended(
try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
- const new_var = try sema.gpa.create(Module.Var);
- errdefer sema.gpa.destroy(new_var);
-
- log.debug("created variable {*} owner_decl: {*} ({s})", .{
- new_var, sema.owner_decl, sema.owner_decl.name,
- });
-
- new_var.* = .{
- .owner_decl = sema.owner_decl_index,
- .init = init_val,
+ return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
+ .ty = var_ty.ip_index,
+ .init = init_val.toIntern(),
+ .decl = sema.owner_decl_index,
+ .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
+ sema.gpa,
+ try sema.handleExternLibName(block, ty_src, lname),
+ )).toOptional() else .none,
.is_extern = small.is_extern,
- .is_mutable = true,
.is_threadlocal = small.is_threadlocal,
- .is_weak_linkage = false,
- .lib_name = null,
- };
-
- if (lib_name) |lname| {
- new_var.lib_name = try sema.handleExternLibName(block, ty_src, lname);
- }
-
- const result = try sema.addConstant(
- var_ty,
- try Value.Tag.variable.create(sema.arena, new_var),
- );
- return result;
+ } })).toValue());
}
fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -22861,7 +22873,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const body = sema.code.extra[extra_index..][0..body_len];
extra_index += body.len;
- const ty = Type.const_slice_u8;
+ const ty = Type.slice_const_u8;
const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
if (val.isGenericPoison()) {
break :blk FuncLinkSection{ .generic = {} };
@@ -23133,10 +23145,10 @@ fn resolveExternOptions(
src: LazySrcLoc,
zir_ref: Zir.Inst.Ref,
) CompileError!std.builtin.ExternOptions {
+ const mod = sema.mod;
const options_inst = try sema.resolveInst(zir_ref);
const extern_options_ty = try sema.getBuiltinType("ExternOptions");
const options = try sema.coerce(block, extern_options_ty, options_inst, src);
- const mod = sema.mod;
const name_src = sema.maybeOptionsSrc(block, src, "name");
const library_src = sema.maybeOptionsSrc(block, src, "library");
@@ -23145,7 +23157,7 @@ fn resolveExternOptions(
const name_ref = try sema.fieldVal(block, src, options, "name", name_src);
const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime-known");
- const name = try name_val.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
+ const name = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);
const library_name_val = try sema.resolveConstValue(block, library_src, library_name_inst, "library in which extern symbol is must be comptime-known");
@@ -23157,9 +23169,8 @@ fn resolveExternOptions(
const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);
const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known");
- const library_name = if (!library_name_val.isNull(mod)) blk: {
- const payload = library_name_val.castTag(.opt_payload).?.data;
- const library_name = try payload.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
+ const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
+ const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
if (library_name.len == 0) {
return sema.fail(block, library_src, "library name cannot be empty", .{});
}
@@ -23227,40 +23238,36 @@ fn zirBuiltinExtern(
new_decl.name = try sema.gpa.dupeZ(u8, options.name);
{
- var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
- errdefer new_decl_arena.deinit();
- const new_decl_arena_allocator = new_decl_arena.allocator();
-
- const new_var = try new_decl_arena_allocator.create(Module.Var);
- new_var.* = .{
- .owner_decl = sema.owner_decl_index,
- .init = Value.@"unreachable",
+ const new_var = try mod.intern(.{ .variable = .{
+ .ty = ty.ip_index,
+ .init = .none,
+ .decl = sema.owner_decl_index,
.is_extern = true,
- .is_mutable = false,
+ .is_const = true,
.is_threadlocal = options.is_thread_local,
.is_weak_linkage = options.linkage == .Weak,
- .lib_name = null,
- };
+ } });
new_decl.src_line = sema.owner_decl.src_line;
// We only access this decl through the decl_ref with the correct type created
// below, so this type doesn't matter
- new_decl.ty = Type.anyopaque;
- new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
+ new_decl.ty = ty;
+ new_decl.val = new_var.toValue();
new_decl.@"align" = 0;
new_decl.@"linksection" = null;
new_decl.has_tv = true;
new_decl.analysis = .complete;
new_decl.generation = mod.generation;
-
- try new_decl.finalizeNewArena(&new_decl_arena);
}
try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
try sema.ensureDeclAnalyzed(new_decl_index);
- const ref = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
- return sema.addConstant(ty, ref);
+ const ref = try mod.intern(.{ .ptr = .{
+ .ty = (try mod.singleConstPtrType(ty)).ip_index,
+ .addr = .{ .decl = new_decl_index },
+ } });
+ return sema.addConstant(ty, ref.toValue());
}
fn zirWorkItem(
@@ -24117,7 +24124,6 @@ fn fieldVal(
const mod = sema.mod;
const gpa = sema.gpa;
- const arena = sema.arena;
const ip = &mod.intern_pool;
const object_src = src; // TODO better source location
const object_ty = sema.typeOf(object);
@@ -24221,13 +24227,14 @@ fn fieldVal(
else => unreachable,
}
- return sema.addConstant(
- if (!child_type.isAnyError(mod))
- child_type
- else
- try mod.singleErrorSetTypeNts(name),
- try Value.Tag.@"error".create(arena, .{ .name = ip.stringToSlice(name) }),
- );
+ const error_set_type = if (!child_type.isAnyError(mod))
+ child_type
+ else
+ try mod.singleErrorSetTypeNts(name);
+ return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
+ .ty = error_set_type.ip_index,
+ .name = name,
+ } })).toValue());
},
.Union => {
if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
@@ -24368,14 +24375,13 @@ fn fieldPtr(
});
if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
- return sema.addConstant(
- result_ty,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = val,
- .container_ty = inner_ty,
- .field_index = Value.Payload.Slice.ptr_index,
- }),
- );
+ return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
+ .ty = result_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = val.ip_index,
+ .index = Value.slice_ptr_index,
+ } },
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, src, null);
@@ -24389,14 +24395,13 @@ fn fieldPtr(
});
if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
- return sema.addConstant(
- result_ty,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = val,
- .container_ty = inner_ty,
- .field_index = Value.Payload.Slice.len_index,
- }),
- );
+ return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
+ .ty = result_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = val.ip_index,
+ .index = Value.slice_len_index,
+ } },
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, src, null);
@@ -24442,14 +24447,16 @@ fn fieldPtr(
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
+ const error_set_type = if (!child_type.isAnyError(mod))
+ child_type
+ else
+ try mod.singleErrorSetTypeNts(name);
return sema.analyzeDeclRef(try anon_decl.finish(
- if (!child_type.isAnyError(mod))
- child_type
- else
- try mod.singleErrorSetTypeNts(name),
- try Value.Tag.@"error".create(anon_decl.arena(), .{
- .name = ip.stringToSlice(name),
- }),
+ error_set_type,
+ (try mod.intern(.{ .err = .{
+ .ty = error_set_type.ip_index,
+ .name = name,
+ } })).toValue(),
0, // default alignment
));
},
@@ -24714,14 +24721,13 @@ fn finishFieldCallBind(
}
if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
- const pointer = try sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(arena, .{
- .container_ptr = struct_ptr_val,
- .container_ty = container_ty,
- .field_index = field_index,
- }),
- );
+ const pointer = try sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = struct_ptr_val.ip_index,
+ .index = field_index,
+ } },
+ } })).toValue());
return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
}
@@ -24901,22 +24907,22 @@ fn structFieldPtrByIndex(
const ptr_field_ty = try Type.ptr(sema.arena, mod, ptr_ty_data);
if (field.is_comptime) {
- const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
- .field_ty = field.ty,
- .field_val = try field.default_val.copy(sema.arena),
- });
- return sema.addConstant(ptr_field_ty, val);
+ const val = try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .comptime_field = try field.default_val.intern(field.ty, mod) },
+ } });
+ return sema.addConstant(ptr_field_ty, val.toValue());
}
if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
- return sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = struct_ptr_val,
- .container_ty = struct_ptr_ty.childType(mod),
- .field_index = field_index,
- }),
- );
+ const val = try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = try struct_ptr_val.intern(struct_ptr_ty, mod),
+ .index = field_index,
+ } },
+ } });
+ return sema.addConstant(ptr_field_ty, val.toValue());
}
try sema.requireRuntimeBlock(block, src, null);
@@ -24955,7 +24961,7 @@ fn structFieldVal(
if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
return sema.addConstant(field.ty, opv);
}
- return sema.addConstant(field.ty, try struct_val.fieldValue(field.ty, mod, field_index));
+ return sema.addConstant(field.ty, try struct_val.fieldValue(mod, field_index));
}
try sema.requireRuntimeBlock(block, src, null);
@@ -24999,7 +25005,7 @@ fn tupleFieldIndex(
field_name_src: LazySrcLoc,
) CompileError!u32 {
const mod = sema.mod;
- assert(!std.mem.eql(u8, field_name, "len"));
+ assert(!mem.eql(u8, field_name, "len"));
if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
@@ -25109,14 +25115,13 @@ fn unionFieldPtr(
},
.Packed, .Extern => {},
}
- return sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(arena, .{
- .container_ptr = union_ptr_val,
- .container_ty = union_ty,
- .field_index = field_index,
- }),
- );
+ return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = union_ptr_val.ip_index,
+ .index = field_index,
+ } },
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, src, null);
@@ -25267,7 +25272,7 @@ fn elemPtrOneLayerOnly(
const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt(mod));
- const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, mod);
+ const elem_ptr = try ptr_val.elemPtr(indexable_ty, index, mod);
const result_ty = try sema.elemPtrType(indexable_ty, index);
return sema.addConstant(result_ty, elem_ptr);
};
@@ -25313,7 +25318,7 @@ fn elemVal(
const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
const index_val = maybe_index_val orelse break :rs elem_index_src;
const index = @intCast(usize, index_val.toUnsignedInt(mod));
- const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, mod);
+ const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, index, mod);
if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {
return sema.addConstant(indexable_ty.elemType2(mod), elem_val);
}
@@ -25407,22 +25412,20 @@ fn tupleFieldPtr(
});
if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
- const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
- .field_ty = field_ty,
- .field_val = default_val,
- });
- return sema.addConstant(ptr_field_ty, val);
+ return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .comptime_field = default_val.ip_index },
+ } })).toValue());
}
if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {
- return sema.addConstant(
- ptr_field_ty,
- try Value.Tag.field_ptr.create(sema.arena, .{
- .container_ptr = tuple_ptr_val,
- .container_ty = tuple_ty,
- .field_index = field_index,
- }),
- );
+ return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
+ .ty = ptr_field_ty.ip_index,
+ .addr = .{ .field = .{
+ .base = tuple_ptr_val.ip_index,
+ .index = field_index,
+ } },
+ } })).toValue());
}
if (!init) {
@@ -25463,7 +25466,7 @@ fn tupleField(
if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty);
- return sema.addConstant(field_ty, try tuple_val.fieldValue(tuple_ty, mod, field_index));
+ return sema.addConstant(field_ty, try tuple_val.fieldValue(mod, field_index));
}
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
@@ -25575,7 +25578,7 @@ fn elemPtrArray(
return sema.addConstUndef(elem_ptr_ty);
}
if (offset) |index| {
- const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, index, mod);
+ const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, index, mod);
return sema.addConstant(elem_ptr_ty, elem_ptr);
}
}
@@ -25631,7 +25634,7 @@ fn elemValSlice(
const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
}
- const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, mod);
+ const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod);
if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {
return sema.addConstant(elem_ty, elem_val);
}
@@ -25691,7 +25694,7 @@ fn elemPtrSlice(
const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
}
- const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, mod);
+ const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod);
return sema.addConstant(elem_ptr_ty, elem_ptr_val);
}
}
@@ -25851,7 +25854,7 @@ fn coerceExtra(
// Function body to function pointer.
if (inst_ty.zigTypeTag(mod) == .Fn) {
const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
- const fn_decl = fn_val.pointerDecl().?;
+ const fn_decl = fn_val.pointerDecl(mod).?;
const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
}
@@ -26080,14 +26083,14 @@ fn coerceExtra(
if (inst_child_ty.structFieldCount(mod) == 0) {
// Optional slice is represented with a null pointer so
// we use a dummy pointer value with the required alignment.
- const slice_val = try Value.Tag.slice.create(sema.arena, .{
- .ptr = if (dest_info.@"align" != 0)
+ return sema.addConstant(dest_ty, (try mod.intern(.{ .ptr = .{
+ .ty = dest_ty.ip_index,
+ .addr = .{ .int = (if (dest_info.@"align" != 0)
try mod.intValue(Type.usize, dest_info.@"align")
else
- try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena),
- .len = try mod.intValue(Type.usize, 0),
- });
- return sema.addConstant(dest_ty, slice_val);
+ try dest_info.pointee_type.lazyAbiAlignment(mod)).ip_index },
+ .len = (try mod.intValue(Type.usize, 0)).ip_index,
+ } })).toValue());
}
// pointer to tuple to slice
@@ -26255,7 +26258,8 @@ fn coerceExtra(
.EnumLiteral => {
// enum literal to enum
const val = try sema.resolveConstValue(block, .unneeded, inst, "");
- const bytes = val.castTag(.enum_literal).?.data;
+ const string = mod.intern_pool.indexToKey(val.ip_index).enum_literal;
+ const bytes = mod.intern_pool.stringToSlice(string);
const field_index = dest_ty.enumFieldIndex(bytes, mod) orelse {
const msg = msg: {
const msg = try sema.errMsg(
@@ -26292,26 +26296,30 @@ fn coerceExtra(
if (maybe_inst_val) |inst_val| {
switch (inst_val.ip_index) {
.undef => return sema.addConstUndef(dest_ty),
- .none => switch (inst_val.tag()) {
- .eu_payload => {
- const payload = try sema.addConstant(
- inst_ty.errorUnionPayload(mod),
- inst_val.castTag(.eu_payload).?.data,
- );
- return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
- error.NotCoercible => break :eu,
- else => |e| return e,
- };
+ else => switch (mod.intern_pool.indexToKey(inst_val.ip_index)) {
+ .error_union => |error_union| switch (error_union.val) {
+ .err_name => |err_name| {
+ const error_set_ty = inst_ty.errorUnionSet(mod);
+ const error_set_val = try sema.addConstant(error_set_ty, (try mod.intern(.{ .err = .{
+ .ty = error_set_ty.ip_index,
+ .name = err_name,
+ } })).toValue());
+ return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src);
+ },
+ .payload => |payload| {
+ const payload_val = try sema.addConstant(
+ inst_ty.errorUnionPayload(mod),
+ payload.toValue(),
+ );
+ return sema.wrapErrorUnionPayload(block, dest_ty, payload_val, inst_src) catch |err| switch (err) {
+ error.NotCoercible => break :eu,
+ else => |e| return e,
+ };
+ },
},
- else => {},
+ else => unreachable,
},
- else => {},
}
- const error_set = try sema.addConstant(
- inst_ty.errorUnionSet(mod),
- inst_val,
- );
- return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
}
},
.ErrorSet => {
@@ -27029,7 +27037,7 @@ fn coerceInMemoryAllowedErrorSets(
},
}
- if (dst_ies.func == sema.owner_func) {
+ if (dst_ies.func == sema.owner_func_index.unwrap()) {
// We are trying to coerce an error set to the current function's
// inferred error set.
try dst_ies.addErrorSet(src_ty, ip, gpa);
@@ -27323,7 +27331,7 @@ fn coerceVarArgParam(
),
.Fn => blk: {
const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
- const fn_decl = fn_val.pointerDecl().?;
+ const fn_decl = fn_val.pointerDecl(mod).?;
break :blk try sema.analyzeDeclRef(fn_decl);
},
.Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
@@ -27441,7 +27449,7 @@ fn storePtr2(
try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
break :rs operand_src;
};
- if (ptr_val.isComptimeMutablePtr()) {
+ if (ptr_val.isComptimeMutablePtr(mod)) {
try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
return;
} else break :rs ptr_src;
@@ -27593,7 +27601,7 @@ fn storePtrVal(
}
const ComptimePtrMutationKit = struct {
- decl_ref_mut: Value.Payload.DeclRefMut.Data,
+ decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
pointee: union(enum) {
/// The pointer type matches the actual comptime Value so a direct
/// modification is possible.
@@ -27619,12 +27627,12 @@ const ComptimePtrMutationKit = struct {
decl_arena: std.heap.ArenaAllocator = undefined,
fn beginArena(self: *ComptimePtrMutationKit, mod: *Module) Allocator {
- const decl = mod.declPtr(self.decl_ref_mut.decl_index);
+ const decl = mod.declPtr(self.decl_ref_mut.decl);
return decl.value_arena.?.acquire(mod.gpa, &self.decl_arena);
}
fn finishArena(self: *ComptimePtrMutationKit, mod: *Module) void {
- const decl = mod.declPtr(self.decl_ref_mut.decl_index);
+ const decl = mod.declPtr(self.decl_ref_mut.decl);
decl.value_arena.?.release(&self.decl_arena);
self.decl_arena = undefined;
}
@@ -27637,6 +27645,7 @@ fn beginComptimePtrMutation(
ptr_val: Value,
ptr_elem_ty: Type,
) CompileError!ComptimePtrMutationKit {
+ if (true) unreachable;
const mod = sema.mod;
switch (ptr_val.tag()) {
.decl_ref_mut => {
@@ -28169,7 +28178,7 @@ fn beginComptimePtrMutation(
},
}
},
- .decl_ref => unreachable, // isComptimeMutablePtr() has been checked already
+ .decl_ref => unreachable, // isComptimeMutablePtr has been checked already
else => unreachable,
}
}
@@ -28189,7 +28198,7 @@ fn beginComptimePtrMutationInner(
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);
+ const allocator = decl.value_arena.?.acquire(sema.gpa, &decl_arena);
defer decl.value_arena.?.release(&decl_arena);
decl_val.* = try decl_val.unintern(allocator, mod);
@@ -28273,44 +28282,83 @@ fn beginComptimePtrLoad(
const mod = sema.mod;
const target = mod.getTarget();
- var deref: ComptimePtrLoadKit = switch (ptr_val.ip_index) {
- .null_value => {
- return sema.fail(block, src, "attempt to use null value", .{});
- },
-
- .none => switch (ptr_val.tag()) {
- .decl_ref,
- .decl_ref_mut,
- => blk: {
- const decl_index = switch (ptr_val.tag()) {
- .decl_ref => ptr_val.castTag(.decl_ref).?.data,
- .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
+ var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
+ .ptr => |ptr| switch (ptr.addr) {
+ .decl, .mut_decl => blk: {
+ const decl_index = switch (ptr.addr) {
+ .decl => |decl| decl,
+ .mut_decl => |mut_decl| mut_decl.decl,
else => unreachable,
};
- const is_mutable = ptr_val.tag() == .decl_ref_mut;
const decl = mod.declPtr(decl_index);
const decl_tv = try decl.typedValue();
- if (decl_tv.val.tagIsVariable()) return error.RuntimeLoad;
+ if (decl.getVariable(mod) != null) 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 = is_mutable,
+ .is_mutable = false,
.ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
};
},
+ .int => return error.RuntimeLoad,
+ .eu_payload, .opt_payload => |container_ptr| blk: {
+ const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
+ const payload_ty = ptr.ty.toType().childType(mod);
+ var deref = try sema.beginComptimePtrLoad(block, src, container_ptr.toValue(), container_ty);
+
+ // eu_payload and opt_payload never have a well-defined layout
+ if (deref.parent != null) {
+ deref.parent = null;
+ deref.ty_without_well_defined_layout = container_ty;
+ }
- .elem_ptr => blk: {
- const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
- const elem_ty = elem_ptr.elem_ty;
- var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null);
+ if (deref.pointee) |*tv| {
+ const coerce_in_mem_ok =
+ (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
+ (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
+ if (coerce_in_mem_ok) {
+ const payload_val = switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
+ .error_union => |error_union| switch (error_union.val) {
+ .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),
+ .payload => |payload| payload,
+ },
+ .opt => |opt| switch (opt.val) {
+ .none => return sema.fail(block, src, "attempt to use null value", .{}),
+ else => opt.val,
+ },
+ else => unreachable,
+ };
+ tv.* = TypedValue{ .ty = payload_ty, .val = payload_val.toValue() };
+ break :blk deref;
+ }
+ }
+ deref.pointee = null;
+ break :blk deref;
+ },
+ .comptime_field => |comptime_field| blk: {
+ const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
+ break :blk ComptimePtrLoadKit{
+ .parent = null,
+ .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
+ .is_mutable = false,
+ .ty_without_well_defined_layout = field_ty,
+ };
+ },
+ .elem => |elem_ptr| blk: {
+ const elem_ty = ptr.ty.toType().childType(mod);
+ var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
// This code assumes that elem_ptrs have been "flattened" in order for direct dereference
// to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
// our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
- if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| {
- assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, mod)));
+ switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
+ .ptr => |base_ptr| switch (base_ptr.addr) {
+ .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
+ else => {},
+ },
+ else => {},
}
if (elem_ptr.index != 0) {
@@ -28327,7 +28375,7 @@ fn beginComptimePtrLoad(
}
}
- // If we're loading an elem_ptr that was derived from a different type
+ // If we're loading an elem that was derived from a different type
// than the true type of the underlying decl, we cannot deref directly
const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
const deref_elem_ty = deref.pointee.?.ty.childType(mod);
@@ -28373,31 +28421,25 @@ fn beginComptimePtrLoad(
};
break :blk deref;
},
+ .field => |field_ptr| blk: {
+ const field_index = @intCast(u32, field_ptr.index);
+ const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
+ var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
- .slice => blk: {
- const slice = ptr_val.castTag(.slice).?.data;
- break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null);
- },
-
- .field_ptr => blk: {
- const field_ptr = ptr_val.castTag(.field_ptr).?.data;
- const field_index = @intCast(u32, field_ptr.field_index);
- var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
-
- if (field_ptr.container_ty.hasWellDefinedLayout(mod)) {
- const struct_obj = mod.typeToStruct(field_ptr.container_ty);
+ if (container_ty.hasWellDefinedLayout(mod)) {
+ const struct_obj = mod.typeToStruct(container_ty);
if (struct_obj != null and struct_obj.?.layout == .Packed) {
// packed structs are not byte addressable
deref.parent = null;
} else if (deref.parent) |*parent| {
// Update the byte offset (in-place)
- try sema.resolveTypeLayout(field_ptr.container_ty);
- const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod);
+ try sema.resolveTypeLayout(container_ty);
+ const field_offset = container_ty.structFieldOffset(field_index, mod);
parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
}
} else {
deref.parent = null;
- deref.ty_without_well_defined_layout = field_ptr.container_ty;
+ deref.ty_without_well_defined_layout = container_ty;
}
const tv = deref.pointee orelse {
@@ -28405,294 +28447,40 @@ fn beginComptimePtrLoad(
break :blk deref;
};
const coerce_in_mem_ok =
- (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
- (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok;
+ (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
+ (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
if (!coerce_in_mem_ok) {
deref.pointee = null;
break :blk deref;
}
- if (field_ptr.container_ty.isSlice(mod)) {
- const slice_val = tv.val.castTag(.slice).?.data;
+ if (container_ty.isSlice(mod)) {
deref.pointee = switch (field_index) {
- Value.Payload.Slice.ptr_index => TypedValue{
- .ty = field_ptr.container_ty.slicePtrFieldType(mod),
- .val = slice_val.ptr,
+ Value.slice_ptr_index => TypedValue{
+ .ty = container_ty.slicePtrFieldType(mod),
+ .val = tv.val.slicePtr(mod),
},
- Value.Payload.Slice.len_index => TypedValue{
+ Value.slice_len_index => TypedValue{
.ty = Type.usize,
- .val = slice_val.len,
+ .val = mod.intern_pool.indexToKey(tv.val.ip_index).ptr.len.toValue(),
},
else => unreachable,
};
} else {
- const field_ty = field_ptr.container_ty.structFieldType(field_index, mod);
+ const field_ty = container_ty.structFieldType(field_index, mod);
deref.pointee = TypedValue{
.ty = field_ty,
- .val = try tv.val.fieldValue(tv.ty, mod, field_index),
+ .val = try tv.val.fieldValue(mod, field_index),
};
}
break :blk deref;
},
-
- .comptime_field_ptr => blk: {
- const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data;
- break :blk ComptimePtrLoadKit{
- .parent = null,
- .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val },
- .is_mutable = false,
- .ty_without_well_defined_layout = comptime_field_ptr.field_ty,
- };
- },
-
- .opt_payload_ptr,
- .eu_payload_ptr,
- => blk: {
- const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
- const payload_ty = switch (ptr_val.tag()) {
- .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(mod),
- .opt_payload_ptr => payload_ptr.container_ty.optionalChild(mod),
- else => unreachable,
- };
- var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty);
-
- // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
- if (deref.parent != null) {
- deref.parent = null;
- deref.ty_without_well_defined_layout = payload_ptr.container_ty;
- }
-
- if (deref.pointee) |*tv| {
- const coerce_in_mem_ok =
- (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
- (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok;
- if (coerce_in_mem_ok) {
- const payload_val = switch (ptr_val.tag()) {
- .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
- return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});
- },
- .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {
- if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{});
- break :opt tv.val;
- },
- else => unreachable,
- };
- tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
- break :blk deref;
- }
- }
- deref.pointee = null;
- break :blk deref;
- },
- .opt_payload => blk: {
- const opt_payload = ptr_val.castTag(.opt_payload).?.data;
- break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
- },
-
- .variable,
- .extern_fn,
- .function,
- => return error.RuntimeLoad,
-
- else => unreachable,
},
- 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,
- };
- },
- .eu_payload, .opt_payload => |container_ptr| blk: {
- const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
- const payload_ty = ptr.ty.toType().childType(mod);
- var deref = try sema.beginComptimePtrLoad(block, src, container_ptr.toValue(), container_ty);
-
- // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
- if (deref.parent != null) {
- deref.parent = null;
- deref.ty_without_well_defined_layout = container_ty;
- }
-
- if (deref.pointee) |*tv| {
- const coerce_in_mem_ok =
- (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
- (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
- if (coerce_in_mem_ok) {
- const payload_val = switch (ptr_val.tag()) {
- .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
- return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});
- },
- .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {
- if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{});
- break :opt tv.val;
- },
- else => unreachable,
- };
- tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
- break :blk deref;
- }
- }
- deref.pointee = null;
- break :blk deref;
- },
- .comptime_field => |comptime_field| blk: {
- const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
- break :blk ComptimePtrLoadKit{
- .parent = null,
- .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
- .is_mutable = false,
- .ty_without_well_defined_layout = field_ty,
- };
- },
- .elem => |elem_ptr| blk: {
- const elem_ty = ptr.ty.toType().childType(mod);
- var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
-
- // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
- // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
- // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
- switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
- .ptr => |base_ptr| switch (base_ptr.addr) {
- .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
- else => {},
- },
- else => {},
- }
-
- if (elem_ptr.index != 0) {
- if (elem_ty.hasWellDefinedLayout(mod)) {
- if (deref.parent) |*parent| {
- // Update the byte offset (in-place)
- const elem_size = try sema.typeAbiSize(elem_ty);
- const offset = parent.byte_offset + elem_size * elem_ptr.index;
- parent.byte_offset = try sema.usizeCast(block, src, offset);
- }
- } else {
- deref.parent = null;
- deref.ty_without_well_defined_layout = elem_ty;
- }
- }
-
- // If we're loading an elem that was derived from a different type
- // than the true type of the underlying decl, we cannot deref directly
- const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
- const deref_elem_ty = deref.pointee.?.ty.childType(mod);
- break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
- (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
- } else false;
- if (!ty_matches) {
- deref.pointee = null;
- break :blk deref;
- }
-
- var array_tv = deref.pointee.?;
- const check_len = array_tv.ty.arrayLenIncludingSentinel(mod);
- if (maybe_array_ty) |load_ty| {
- // It's possible that we're loading a [N]T, in which case we'd like to slice
- // the pointee array directly from our parent array.
- if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) {
- const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod));
- deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{
- .ty = try Type.array(sema.arena, N, null, elem_ty, mod),
- .val = try array_tv.val.sliceArray(mod, sema.arena, elem_ptr.index, elem_ptr.index + N),
- } else null;
- break :blk deref;
- }
- }
-
- if (elem_ptr.index >= check_len) {
- deref.pointee = null;
- break :blk deref;
- }
- if (elem_ptr.index == check_len - 1) {
- if (array_tv.ty.sentinel(mod)) |sent| {
- deref.pointee = TypedValue{
- .ty = elem_ty,
- .val = sent,
- };
- break :blk deref;
- }
- }
- deref.pointee = TypedValue{
- .ty = elem_ty,
- .val = try array_tv.val.elemValue(mod, elem_ptr.index),
- };
- break :blk deref;
- },
- .field => |field_ptr| blk: {
- const field_index = @intCast(u32, field_ptr.index);
- const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
- var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
-
- if (container_ty.hasWellDefinedLayout(mod)) {
- const struct_obj = mod.typeToStruct(container_ty);
- if (struct_obj != null and struct_obj.?.layout == .Packed) {
- // packed structs are not byte addressable
- deref.parent = null;
- } else if (deref.parent) |*parent| {
- // Update the byte offset (in-place)
- try sema.resolveTypeLayout(container_ty);
- const field_offset = container_ty.structFieldOffset(field_index, mod);
- parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
- }
- } else {
- deref.parent = null;
- deref.ty_without_well_defined_layout = container_ty;
- }
-
- const tv = deref.pointee orelse {
- deref.pointee = null;
- break :blk deref;
- };
- const coerce_in_mem_ok =
- (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
- (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
- if (!coerce_in_mem_ok) {
- deref.pointee = null;
- break :blk deref;
- }
-
- if (container_ty.isSlice(mod)) {
- const slice_val = tv.val.castTag(.slice).?.data;
- deref.pointee = switch (field_index) {
- Value.Payload.Slice.ptr_index => TypedValue{
- .ty = container_ty.slicePtrFieldType(mod),
- .val = slice_val.ptr,
- },
- Value.Payload.Slice.len_index => TypedValue{
- .ty = Type.usize,
- .val = slice_val.len,
- },
- else => unreachable,
- };
- } else {
- const field_ty = container_ty.structFieldType(field_index, mod);
- deref.pointee = TypedValue{
- .ty = field_ty,
- .val = try tv.val.fieldValue(tv.ty, mod, field_index),
- };
- }
- break :blk deref;
- },
- },
- else => unreachable,
+ .opt => |opt| switch (opt.val) {
+ .none => return sema.fail(block, src, "attempt to use null value", .{}),
+ else => try sema.beginComptimePtrLoad(block, src, opt.val.toValue(), null),
},
+ else => unreachable,
};
if (deref.pointee) |tv| {
@@ -28853,7 +28641,7 @@ fn coerceCompatiblePtrs(
}
// The comptime Value representation is compatible with both types.
return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(
- mod.gpa,
+ sema.gpa,
try val.intern(inst_ty, mod),
dest_ty.ip_index,
)).toValue());
@@ -29538,7 +29326,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
};
}
-fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
+fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
if (sema.owner_func) |owner_func| {
owner_func.state = .dependency_failure;
@@ -29550,6 +29338,7 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
}
fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
+ const mod = sema.mod;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const decl = try anon_decl.finish(
@@ -29558,15 +29347,23 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
0, // default alignment
);
try sema.maybeQueueFuncBodyAnalysis(decl);
- try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);
- return try Value.Tag.decl_ref.create(sema.arena, decl);
+ try mod.declareDeclDependency(sema.owner_decl_index, decl);
+ const result = try mod.intern(.{ .ptr = .{
+ .ty = (try mod.singleConstPtrType(ty)).ip_index,
+ .addr = .{ .decl = decl },
+ } });
+ return result.toValue();
}
fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
+ const mod = sema.mod;
const val = opt_val orelse return Value.null;
const ptr_val = try sema.refValue(block, ty, val);
- const result = try Value.Tag.opt_payload.create(sema.arena, ptr_val);
- return result;
+ const result = try mod.intern(.{ .opt = .{
+ .ty = (try mod.optionalType((try mod.singleConstPtrType(ty)).ip_index)).ip_index,
+ .val = ptr_val.ip_index,
+ } });
+ return result.toValue();
}
fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref {
@@ -29587,10 +29384,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: boo
const ptr_ty = try mod.ptrType(.{
.elem_type = decl_tv.ty.ip_index,
.alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
- .is_const = if (decl_tv.val.castTag(.variable)) |payload|
- !payload.data.is_mutable
- else
- false,
+ .is_const = if (decl.getVariable(mod)) |variable| variable.is_const else false,
.address_space = decl.@"addrspace",
});
if (analyze_fn_body) {
@@ -29608,8 +29402,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
const tv = try decl.typedValue();
if (tv.ty.zigTypeTag(mod) != .Fn) return;
if (!try sema.fnHasRuntimeBits(tv.ty)) return;
- const func = tv.val.castTag(.function) orelse return; // undef or extern_fn
- try mod.ensureFuncBodyAnalysisQueued(func.data);
+ const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
+ try mod.ensureFuncBodyAnalysisQueued(func_index);
}
fn analyzeRef(
@@ -29622,14 +29416,12 @@ fn analyzeRef(
if (try sema.resolveMaybeUndefVal(operand)) |val| {
switch (val.ip_index) {
- .none => switch (val.tag()) {
- .extern_fn, .function => {
- const decl_index = val.pointerDecl().?;
- return sema.analyzeDeclRef(decl_index);
- },
+ .none => {},
+ else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
+ .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
+ .func => |func| return sema.analyzeDeclRef(sema.mod.funcPtr(func.index).owner_decl),
else => {},
},
- else => {},
}
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
@@ -29854,7 +29646,7 @@ fn analyzeIsNonErrComptimeOnly(
if (other_ies.errors.count() != 0) break :blk;
}
- if (ies.func == sema.owner_func) {
+ if (ies.func == sema.owner_func_index.unwrap()) {
// We're checking the inferred errorset of the current function and none of
// its child inferred error sets contained any errors meaning that any value
// so far with this type can't contain errors either.
@@ -29873,7 +29665,7 @@ fn analyzeIsNonErrComptimeOnly(
if (err_union.isUndef(mod)) {
return sema.addConstUndef(Type.bool);
}
- if (err_union.getError() == null) {
+ if (err_union.getError(mod) == null) {
return Air.Inst.Ref.bool_true;
} else {
return Air.Inst.Ref.bool_false;
@@ -30137,7 +29929,7 @@ fn analyzeSlice(
const end_int = end_val.getUnsignedInt(mod).?;
const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
- const elem_ptr = try ptr_val.elemPtr(new_ptr_ty, sema.arena, sentinel_index, sema.mod);
+ const elem_ptr = try ptr_val.elemPtr(new_ptr_ty, sentinel_index, sema.mod);
const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);
const actual_sentinel = switch (res) {
.runtime_load => break :sentinel_check,
@@ -30233,7 +30025,7 @@ fn analyzeSlice(
if (!new_ptr_val.isUndef(mod)) {
return sema.addConstant(return_ty, (try mod.intern_pool.getCoerced(
- mod.gpa,
+ sema.gpa,
try new_ptr_val.intern(new_ptr_ty, mod),
return_ty.ip_index,
)).toValue());
@@ -30753,7 +30545,10 @@ fn wrapOptional(
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
if (try sema.resolveMaybeUndefVal(inst)) |val| {
- return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, val));
+ return sema.addConstant(dest_ty, (try sema.mod.intern(.{ .opt = .{
+ .ty = dest_ty.ip_index,
+ .val = val.ip_index,
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, inst_src, null);
@@ -30771,7 +30566,10 @@ fn wrapErrorUnionPayload(
const dest_payload_ty = dest_ty.errorUnionPayload(mod);
const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });
if (try sema.resolveMaybeUndefVal(coerced)) |val| {
- return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
+ return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{
+ .ty = dest_ty.ip_index,
+ .val = .{ .payload = val.ip_index },
+ } })).toValue());
}
try sema.requireRuntimeBlock(block, inst_src, null);
try sema.queueFullTypeResolution(dest_payload_ty);
@@ -30794,27 +30592,20 @@ fn wrapErrorUnionSet(
.anyerror_type => {},
else => switch (ip.indexToKey(dest_err_set_ty.ip_index)) {
.error_set_type => |error_set_type| ok: {
- const expected_name = val.castTag(.@"error").?.data.name;
- if (ip.getString(expected_name).unwrap()) |expected_name_interned| {
- if (error_set_type.nameIndex(ip, expected_name_interned) != null)
- break :ok;
- }
+ const expected_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
+ if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
},
.inferred_error_set_type => |ies_index| ok: {
const ies = mod.inferredErrorSetPtr(ies_index);
- const expected_name = val.castTag(.@"error").?.data.name;
+ const expected_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
// We carefully do this in an order that avoids unnecessarily
// resolving the destination error set type.
if (ies.is_anyerror) break :ok;
- if (ip.getString(expected_name).unwrap()) |expected_name_interned| {
- if (ies.errors.contains(expected_name_interned)) break :ok;
- }
- if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
- break :ok;
- }
+ if (ies.errors.contains(expected_name)) break :ok;
+ if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
},
@@ -31462,43 +31253,33 @@ pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileErro
/// to a type not having its layout resolved.
fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {
switch (val.ip_index) {
- .none => switch (val.tag()) {
- .lazy_align => {
- const ty = val.castTag(.lazy_align).?.data;
- return sema.resolveTypeLayout(ty);
- },
- .lazy_size => {
- const ty = val.castTag(.lazy_size).?.data;
- return sema.resolveTypeLayout(ty);
- },
- .comptime_field_ptr => {
- const field_ptr = val.castTag(.comptime_field_ptr).?.data;
- return sema.resolveLazyValue(field_ptr.field_val);
- },
- .eu_payload,
- .opt_payload,
- => {
- const sub_val = val.cast(Value.Payload.SubValue).?.data;
- return sema.resolveLazyValue(sub_val);
- },
- .@"union" => {
- const union_val = val.castTag(.@"union").?.data;
- return sema.resolveLazyValue(union_val.val);
- },
- .aggregate => {
- const aggregate = val.castTag(.aggregate).?.data;
- for (aggregate) |elem_val| {
- try sema.resolveLazyValue(elem_val);
- }
- },
- .slice => {
- const slice = val.castTag(.slice).?.data;
- try sema.resolveLazyValue(slice.ptr);
- return sema.resolveLazyValue(slice.len);
+ .none => {},
+ else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
+ .int => |int| switch (int.storage) {
+ .u64, .i64, .big_int => {},
+ .lazy_align, .lazy_size => |lazy_ty| try sema.resolveTypeLayout(lazy_ty.toType()),
+ },
+ .ptr => |ptr| {
+ switch (ptr.addr) {
+ .decl, .mut_decl => {},
+ .int => |int| try sema.resolveLazyValue(int.toValue()),
+ .eu_payload, .opt_payload => |base| try sema.resolveLazyValue(base.toValue()),
+ .comptime_field => |comptime_field| try sema.resolveLazyValue(comptime_field.toValue()),
+ .elem, .field => |base_index| try sema.resolveLazyValue(base_index.base.toValue()),
+ }
+ if (ptr.len != .none) try sema.resolveLazyValue(ptr.len.toValue());
+ },
+ .aggregate => |aggregate| switch (aggregate.storage) {
+ .bytes => {},
+ .elems => |elems| for (elems) |elem| try sema.resolveLazyValue(elem.toValue()),
+ .repeated_elem => |elem| try sema.resolveLazyValue(elem.toValue()),
+ },
+ .un => |un| {
+ try sema.resolveLazyValue(un.tag.toValue());
+ try sema.resolveLazyValue(un.val.toValue());
},
- else => return,
+ else => {},
},
- else => return,
}
}
@@ -31597,7 +31378,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
else blk: {
const decl = mod.declPtr(struct_obj.owner_decl);
var decl_arena: std.heap.ArenaAllocator = undefined;
- const decl_arena_allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena);
+ const decl_arena_allocator = decl.value_arena.?.acquire(sema.gpa, &decl_arena);
defer decl.value_arena.?.release(&decl_arena);
break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
};
@@ -31662,18 +31443,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
var analysis_arena = std.heap.ArenaAllocator.init(gpa);
defer analysis_arena.deinit();
- var sema: Sema = .{
- .mod = mod,
- .gpa = gpa,
- .arena = analysis_arena.allocator(),
- .perm_arena = decl_arena_allocator,
- .code = zir,
- .owner_decl = decl,
- .owner_decl_index = decl_index,
- .func = null,
- .fn_ret_ty = Type.void,
- .owner_func = null,
- };
+ var sema: Sema = .{ .mod = mod, .gpa = gpa, .arena = analysis_arena.allocator(), .perm_arena = decl_arena_allocator, .code = zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = null, .func_index = .none, .fn_ret_ty = Type.void, .owner_func = null, .owner_func_index = .none };
defer sema.deinit();
var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
@@ -31720,8 +31490,10 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
.owner_decl = decl,
.owner_decl_index = decl_index,
.func = null,
+ .func_index = .none,
.fn_ret_ty = Type.void,
.owner_func = null,
+ .owner_func_index = .none,
};
defer sema.deinit();
@@ -31974,16 +31746,23 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
.enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),
// values, not types
- .undef => unreachable,
- .un => unreachable,
- .simple_value => unreachable,
- .extern_func => unreachable,
- .int => unreachable,
- .float => unreachable,
- .ptr => unreachable,
- .opt => unreachable,
- .enum_tag => unreachable,
- .aggregate => unreachable,
+ .undef,
+ .runtime_value,
+ .simple_value,
+ .variable,
+ .extern_func,
+ .func,
+ .int,
+ .err,
+ .error_union,
+ .enum_literal,
+ .enum_tag,
+ .float,
+ .ptr,
+ .opt,
+ .aggregate,
+ .un,
+ => unreachable,
},
};
}
@@ -32141,8 +31920,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
.manyptr_const_u8_type,
.manyptr_const_u8_sentinel_0_type,
.single_const_pointer_to_comptime_int_type,
- .const_slice_u8_type,
- .const_slice_u8_sentinel_0_type,
+ .slice_const_u8_type,
+ .slice_const_u8_sentinel_0_type,
.anyerror_void_error_union_type,
.generic_poison_type,
.empty_struct_type,
@@ -32288,18 +32067,19 @@ fn resolveInferredErrorSet(
if (ies.is_resolved) return;
- if (ies.func.state == .in_progress) {
+ const func = mod.funcPtr(ies.func);
+ if (func.state == .in_progress) {
return sema.fail(block, src, "unable to resolve inferred error set", .{});
}
// In order to ensure that all dependencies are properly added to the set, we
// need to ensure the function body is analyzed of the inferred error set.
// However, in the case of comptime/inline function calls with inferred error sets,
- // each call gets a new InferredErrorSet object, which points to the same
- // `*Module.Fn`. Not only is the function not relevant to the inferred error set
+ // each call gets a new InferredErrorSet object, which contains the same
+ // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
// in this case, it may be a generic function which would cause an assertion failure
// if we called `ensureFuncBodyAnalyzed` on it here.
- const ies_func_owner_decl = mod.declPtr(ies.func.owner_decl);
+ const ies_func_owner_decl = mod.declPtr(func.owner_decl);
const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
// if ies declared by a inline function with generic return type, the return_type should be generic_poison,
// because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
@@ -32414,8 +32194,10 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
.owner_decl = decl,
.owner_decl_index = decl_index,
.func = null,
+ .func_index = .none,
.fn_ret_ty = Type.void,
.owner_func = null,
+ .owner_func_index = .none,
};
defer sema.deinit();
@@ -32754,8 +32536,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
.owner_decl = decl,
.owner_decl_index = decl_index,
.func = null,
+ .func_index = .none,
.fn_ret_ty = Type.void,
.owner_func = null,
+ .owner_func_index = .none,
};
defer sema.deinit();
@@ -33111,7 +32895,7 @@ fn generateUnionTagTypeNumbered(
const name = name: {
const fqn = try union_obj.getFullyQualifiedName(mod);
defer sema.gpa.free(fqn);
- break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
+ break :name try std.fmt.allocPrintZ(sema.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
};
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
.ty = Type.type,
@@ -33160,7 +32944,7 @@ fn generateUnionTagTypeSimple(
const name = name: {
const fqn = try union_obj.getFullyQualifiedName(mod);
defer sema.gpa.free(fqn);
- break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
+ break :name try std.fmt.allocPrintZ(sema.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
};
try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
.ty = Type.type,
@@ -33288,19 +33072,19 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
.inferred_error_set_type,
=> null,
- .array_type => |array_type| {
- if (array_type.len == 0)
- return Value.initTag(.empty_array);
- if ((try sema.typeHasOnePossibleValue(array_type.child.toType())) != null) {
- return Value.initTag(.the_only_possible_value);
+ inline .array_type, .vector_type => |seq_type| {
+ if (seq_type.len == 0) return (try mod.intern(.{ .aggregate = .{
+ .ty = ty.ip_index,
+ .storage = .{ .elems = &.{} },
+ } })).toValue();
+ if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {
+ return (try mod.intern(.{ .aggregate = .{
+ .ty = ty.ip_index,
+ .storage = .{ .repeated_elem = opv.ip_index },
+ } })).toValue();
}
return null;
},
- .vector_type => |vector_type| {
- if (vector_type.len == 0) return Value.initTag(.empty_array);
- if (try sema.typeHasOnePossibleValue(vector_type.child.toType())) |v| return v;
- return null;
- },
.opt_type => |child| {
if (child == .noreturn_type) {
return try mod.nullValue(ty);
@@ -33466,16 +33250,23 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
},
// values, not types
- .undef => unreachable,
- .un => unreachable,
- .simple_value => unreachable,
- .extern_func => unreachable,
- .int => unreachable,
- .float => unreachable,
- .ptr => unreachable,
- .opt => unreachable,
- .enum_tag => unreachable,
- .aggregate => unreachable,
+ .undef,
+ .runtime_value,
+ .simple_value,
+ .variable,
+ .extern_func,
+ .func,
+ .int,
+ .err,
+ .error_union,
+ .enum_literal,
+ .enum_tag,
+ .float,
+ .ptr,
+ .opt,
+ .aggregate,
+ .un,
+ => unreachable,
},
};
}
@@ -33625,10 +33416,13 @@ fn analyzeComptimeAlloc(
decl.@"align" = alignment;
try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
- return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
- .runtime_index = block.runtime_index,
- .decl_index = decl_index,
- }));
+ return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
+ .ty = ptr_type.ip_index,
+ .addr = .{ .mut_decl = .{
+ .decl = decl_index,
+ .runtime_index = block.runtime_index,
+ } },
+ } })).toValue());
}
/// The places where a user can specify an address space attribute
@@ -33969,16 +33763,23 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
.enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),
// values, not types
- .undef => unreachable,
- .un => unreachable,
- .simple_value => unreachable,
- .extern_func => unreachable,
- .int => unreachable,
- .float => unreachable,
- .ptr => unreachable,
- .opt => unreachable,
- .enum_tag => unreachable,
- .aggregate => unreachable,
+ .undef,
+ .runtime_value,
+ .simple_value,
+ .variable,
+ .extern_func,
+ .func,
+ .int,
+ .err,
+ .error_union,
+ .enum_literal,
+ .enum_tag,
+ .float,
+ .ptr,
+ .opt,
+ .aggregate,
+ .un,
+ => unreachable,
},
};
}
@@ -34337,8 +34138,9 @@ fn intFitsInType(
ty: Type,
vector_index: ?*usize,
) CompileError!bool {
- if (ty.ip_index == .comptime_int_type) return true;
const mod = sema.mod;
+ if (ty.ip_index == .comptime_int_type) return true;
+ const info = ty.intInfo(mod);
switch (val.ip_index) {
.undef,
.zero,
@@ -34346,40 +34148,8 @@ fn intFitsInType(
.zero_u8,
=> return true,
- .none => switch (val.tag()) {
- .lazy_align => {
- const info = ty.intInfo(mod);
- const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
- // If it is u16 or bigger we know the alignment fits without resolving it.
- if (info.bits >= max_needed_bits) return true;
- const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data);
- if (x == 0) return true;
- const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
- return info.bits >= actual_needed_bits;
- },
- .lazy_size => {
- const info = ty.intInfo(mod);
- const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
- // If it is u64 or bigger we know the size fits without resolving it.
- if (info.bits >= max_needed_bits) return true;
- const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data);
- if (x == 0) return true;
- const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
- return info.bits >= actual_needed_bits;
- },
-
- .the_only_possible_value => {
- assert(ty.intInfo(mod).bits == 0);
- return true;
- },
-
- .decl_ref_mut,
- .extern_fn,
- .decl_ref,
- .function,
- .variable,
- => {
- const info = ty.intInfo(mod);
+ else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
+ .variable, .extern_func, .func, .ptr => {
const target = mod.getTarget();
const ptr_bits = target.ptrBitWidth();
return switch (info.signedness) {
@@ -34387,27 +34157,51 @@ fn intFitsInType(
.unsigned => info.bits >= ptr_bits,
};
},
-
- .aggregate => {
- assert(ty.zigTypeTag(mod) == .Vector);
- for (val.castTag(.aggregate).?.data, 0..) |elem, i| {
- if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) {
- if (vector_index) |some| some.* = i;
- return false;
- }
- }
- return true;
+ .int => |int| switch (int.storage) {
+ .u64, .i64, .big_int => {
+ var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
+ const big_int = int.storage.toBigInt(&buffer);
+ return big_int.fitsInTwosComp(info.signedness, info.bits);
+ },
+ .lazy_align => |lazy_ty| {
+ const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
+ // If it is u16 or bigger we know the alignment fits without resolving it.
+ if (info.bits >= max_needed_bits) return true;
+ const x = try sema.typeAbiAlignment(lazy_ty.toType());
+ if (x == 0) return true;
+ const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
+ return info.bits >= actual_needed_bits;
+ },
+ .lazy_size => |lazy_ty| {
+ const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
+ // If it is u64 or bigger we know the size fits without resolving it.
+ if (info.bits >= max_needed_bits) return true;
+ const x = try sema.typeAbiSize(lazy_ty.toType());
+ if (x == 0) return true;
+ const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
+ return info.bits >= actual_needed_bits;
+ },
},
-
- else => unreachable,
- },
-
- else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
- .int => |int| {
- const info = ty.intInfo(mod);
- var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
- const big_int = int.storage.toBigInt(&buffer);
- return big_int.fitsInTwosComp(info.signedness, info.bits);
+ .aggregate => |aggregate| {
+ assert(ty.zigTypeTag(mod) == .Vector);
+ return switch (aggregate.storage) {
+ .bytes => |bytes| for (bytes, 0..) |byte, i| {
+ if (byte == 0) continue;
+ const actual_needed_bits = std.math.log2(byte) + 1 + @boolToInt(info.signedness == .signed);
+ if (info.bits >= actual_needed_bits) continue;
+ if (vector_index) |vi| vi.* = i;
+ break false;
+ } else true,
+ .elems, .repeated_elem => for (switch (aggregate.storage) {
+ .bytes => unreachable,
+ .elems => |elems| elems,
+ .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem),
+ }, 0..) |elem, i| {
+ if (try sema.intFitsInType(elem.toValue(), ty.scalarType(mod), null)) continue;
+ if (vector_index) |vi| vi.* = i;
+ break false;
+ } else true,
+ };
},
else => unreachable,
},