authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-22 07:58:02-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:54-07:00
log6e0de1d11694a58745da76d601ebab7562feed09
treecd6cf352788d8f47bad97a95e4390dd3f6a309c5
parent5555bdca047f8dbf8d7adfa8f248f5ce9b692b9e

InternPool: port most of value tags


34 files changed, 5236 insertions(+), 6010 deletions(-)

lib/std/array_list.zig+44
......@@ -459,6 +459,28 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
459459 return self.items[prev_len..][0..n];
460460 }
461461
462 /// Resize the array, adding `n` new elements, which have `undefined` values.
463 /// The return value is a slice pointing to the newly allocated elements.
464 /// The returned pointer becomes invalid when the list is resized.
465 /// Resizes list if `self.capacity` is not large enough.
466 pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T {
467 const prev_len = self.items.len;
468 try self.resize(self.items.len + n);
469 return self.items[prev_len..][0..n];
470 }
471
472 /// Resize the array, adding `n` new elements, which have `undefined` values.
473 /// The return value is a slice pointing to the newly allocated elements.
474 /// Asserts that there is already space for the new item without allocating more.
475 /// **Does not** invalidate element pointers.
476 /// The returned pointer becomes invalid when the list is resized.
477 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
478 assert(self.items.len + n <= self.capacity);
479 const prev_len = self.items.len;
480 self.items.len += n;
481 return self.items[prev_len..][0..n];
482 }
483
462484 /// Remove and return the last element from the list.
463485 /// Asserts the list has at least one item.
464486 /// Invalidates pointers to the removed element.
......@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
949971 return self.items[prev_len..][0..n];
950972 }
951973
974 /// Resize the array, adding `n` new elements, which have `undefined` values.
975 /// The return value is a slice pointing to the newly allocated elements.
976 /// The returned pointer becomes invalid when the list is resized.
977 /// Resizes list if `self.capacity` is not large enough.
978 pub fn addManyAsSlice(self: *Self, allocator: Allocator, n: usize) Allocator.Error![]T {
979 const prev_len = self.items.len;
980 try self.resize(allocator, self.items.len + n);
981 return self.items[prev_len..][0..n];
982 }
983
984 /// Resize the array, adding `n` new elements, which have `undefined` values.
985 /// The return value is a slice pointing to the newly allocated elements.
986 /// Asserts that there is already space for the new item without allocating more.
987 /// **Does not** invalidate element pointers.
988 /// The returned pointer becomes invalid when the list is resized.
989 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
990 assert(self.items.len + n <= self.capacity);
991 const prev_len = self.items.len;
992 self.items.len += n;
993 return self.items[prev_len..][0..n];
994 }
995
952996 /// Remove and return the last element from the list.
953997 /// Asserts the list has at least one item.
954998 /// Invalidates pointers to last element.
src/Air.zig+3-3
......@@ -901,8 +901,8 @@ pub const Inst = struct {
901901 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
902902 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
903903 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),
904 const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type),
905 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),
904 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
905 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
906906 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
907907 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
908908 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
......@@ -1382,7 +1382,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
13821382
13831383 .bool_to_int => return Type.u1,
13841384
1385 .tag_name, .error_name => return Type.const_slice_u8_sentinel_0,
1385 .tag_name, .error_name => return Type.slice_const_u8_sentinel_0,
13861386
13871387 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
13881388 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
src/AstGen.zig+15-15
......@@ -3934,7 +3934,7 @@ fn fnDecl(
39343934 var section_gz = decl_gz.makeSubBlock(params_scope);
39353935 defer section_gz.unstack();
39363936 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3937 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .const_slice_u8_type } }, fn_proto.ast.section_expr);
3937 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, fn_proto.ast.section_expr);
39383938 if (section_gz.instructionsSlice().len == 0) {
39393939 // In this case we will send a len=0 body which can be encoded more efficiently.
39403940 break :inst inst;
......@@ -4137,7 +4137,7 @@ fn globalVarDecl(
41374137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
41384138 };
41394139 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
4140 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .const_slice_u8_type } }, var_decl.ast.section_node);
4140 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .slice_const_u8_type } }, var_decl.ast.section_node);
41414141 };
41424142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
41434143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
......@@ -7878,7 +7878,7 @@ fn unionInit(
78787878 params: []const Ast.Node.Index,
78797879) InnerError!Zir.Inst.Ref {
78807880 const union_type = try typeExpr(gz, scope, params[0]);
7881 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
7881 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]);
78827882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
78837883 .container_type = union_type,
78847884 .field_name = field_name,
......@@ -8100,12 +8100,12 @@ fn builtinCall(
81008100 if (ri.rl == .ref) {
81018101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
81028102 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
8103 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
8103 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
81048104 });
81058105 }
81068106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
81078107 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
8108 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
8108 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
81098109 });
81108110 return rvalue(gz, ri, result, node);
81118111 },
......@@ -8271,11 +8271,11 @@ fn builtinCall(
82718271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
82728272
82738273 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),
8274 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .compile_error),
8274 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .compile_error),
82758275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),
82768276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
82778277 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),
8278 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file),
8278 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .embed_file),
82798279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
82808280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
82818281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
......@@ -8334,7 +8334,7 @@ fn builtinCall(
83348334 },
83358335 .panic => {
83368336 try emitDbgNode(gz, node);
8337 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .panic);
8337 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .panic);
83388338 },
83398339 .trap => {
83408340 try emitDbgNode(gz, node);
......@@ -8450,7 +8450,7 @@ fn builtinCall(
84508450 },
84518451 .c_define => {
84528452 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
8453 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]);
8453 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0]);
84548454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
84558455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
84568456 .node = gz.nodeIndexToRelative(node),
......@@ -8546,7 +8546,7 @@ fn builtinCall(
85468546 },
85478547 .field_parent_ptr => {
85488548 const parent_type = try typeExpr(gz, scope, params[0]);
8549 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
8549 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]);
85508550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
85518551 .parent_type = parent_type,
85528552 .field_name = field_name,
......@@ -8701,7 +8701,7 @@ fn hasDeclOrField(
87018701 tag: Zir.Inst.Tag,
87028702) InnerError!Zir.Inst.Ref {
87038703 const container_type = try typeExpr(gz, scope, lhs_node);
8704 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
8704 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node);
87058705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
87068706 .lhs = container_type,
87078707 .rhs = name,
......@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(
88518851) InnerError!Zir.Inst.Ref {
88528852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
88538853 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
8854 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, operand_node);
8854 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, operand_node);
88558855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
88568856 .node = gz.nodeIndexToRelative(node),
88578857 .operand = operand,
......@@ -8869,7 +8869,7 @@ fn offsetOf(
88698869 tag: Zir.Inst.Tag,
88708870) InnerError!Zir.Inst.Ref {
88718871 const type_inst = try typeExpr(gz, scope, lhs_node);
8872 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
8872 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node);
88738873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
88748874 .lhs = type_inst,
88758875 .rhs = field_name,
......@@ -10317,8 +10317,8 @@ fn rvalue(
1031710317 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_type),
1031810318 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),
1031910319 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
10320 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type),
10321 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_sentinel_0_type),
10320 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_type),
10321 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
1032210322 as_ty | @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type),
1032310323 as_ty | @enumToInt(Zir.Inst.Ref.generic_poison_type),
1032410324 as_ty | @enumToInt(Zir.Inst.Ref.empty_struct_type),
src/Compilation.zig+3-2
......@@ -226,7 +226,7 @@ const Job = union(enum) {
226226 /// Write the constant value for a Decl to the output file.
227227 codegen_decl: Module.Decl.Index,
228228 /// Write the machine code for a function to the output file.
229 codegen_func: *Module.Fn,
229 codegen_func: Module.Fn.Index,
230230 /// Render the .h file snippet for the Decl.
231231 emit_h_decl: Module.Decl.Index,
232232 /// The Decl needs to be analyzed and possibly export itself.
......@@ -3208,7 +3208,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
32083208 // Tests are always emitted in test binaries. The decl_refs are created by
32093209 // Module.populateTestFunctions, but this will not queue body analysis, so do
32103210 // that now.
3211 try module.ensureFuncBodyAnalysisQueued(decl.val.castTag(.function).?.data);
3211 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
3212 try module.ensureFuncBodyAnalysisQueued(func_index);
32123213 }
32133214 },
32143215 .update_embed_file => |embed_file| {
src/InternPool.zig+667-160
......@@ -34,6 +34,12 @@ allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
3434/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
3535unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
3636
37/// Fn objects are stored in this data structure because:
38/// * They need to be mutated after creation.
39allocated_funcs: std.SegmentedList(Module.Fn, 0) = .{},
40/// When a Fn object is freed from `allocated_funcs`, it is pushed into this stack.
41funcs_free_list: std.ArrayListUnmanaged(Module.Fn.Index) = .{},
42
3743/// InferredErrorSet objects are stored in this data structure because:
3844/// * They contain pointers such as the errors map and the set of other inferred error sets.
3945/// * They need to be mutated after creation.
......@@ -66,18 +72,18 @@ const Limb = std.math.big.Limb;
6672
6773const InternPool = @This();
6874const Module = @import("Module.zig");
75const Sema = @import("Sema.zig");
6976
7077const KeyAdapter = struct {
7178 intern_pool: *const InternPool,
7279
7380 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
7481 _ = b_void;
75 return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a);
82 return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a, ctx.intern_pool);
7683 }
7784
7885 pub fn hash(ctx: @This(), a: Key) u32 {
79 _ = ctx;
80 return a.hash32();
86 return a.hash32(ctx.intern_pool);
8187 }
8288};
8389
......@@ -111,10 +117,19 @@ pub const RuntimeIndex = enum(u32) {
111117 }
112118};
113119
120/// An index into `string_bytes`.
121pub const String = enum(u32) {
122 _,
123};
124
114125/// An index into `string_bytes`.
115126pub const NullTerminatedString = enum(u32) {
116127 _,
117128
129 pub fn toString(self: NullTerminatedString) String {
130 return @intToEnum(String, @enumToInt(self));
131 }
132
118133 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
119134 return @intToEnum(OptionalNullTerminatedString, @enumToInt(self));
120135 }
......@@ -180,23 +195,20 @@ pub const Key = union(enum) {
180195 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
181196 /// via `simple_value` and has a named `Index` tag for it.
182197 undef: Index,
198 runtime_value: TypeValue,
183199 simple_value: SimpleValue,
184 extern_func: struct {
185 ty: Index,
186 /// The Decl that corresponds to the function itself.
187 decl: Module.Decl.Index,
188 /// Library name if specified.
189 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
190 /// Index into the string table bytes.
191 lib_name: u32,
192 },
200 variable: Key.Variable,
201 extern_func: ExternFunc,
202 func: Func,
193203 int: Key.Int,
204 err: Error,
205 error_union: ErrorUnion,
206 enum_literal: NullTerminatedString,
194207 /// A specific enum tag, indicated by the integer tag value.
195208 enum_tag: Key.EnumTag,
196209 float: Key.Float,
197210 ptr: Ptr,
198211 opt: Opt,
199
200212 /// An instance of a struct, array, or vector.
201213 /// Each element/field stored as an `Index`.
202214 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
......@@ -261,7 +273,7 @@ pub const Key = union(enum) {
261273 pub const ArrayType = struct {
262274 len: u64,
263275 child: Index,
264 sentinel: Index,
276 sentinel: Index = .none,
265277 };
266278
267279 pub const VectorType = struct {
......@@ -369,6 +381,7 @@ pub const Key = union(enum) {
369381 return @intCast(u32, x);
370382 },
371383 .i64, .big_int => return null, // out of range
384 .lazy_align, .lazy_size => unreachable,
372385 }
373386 }
374387 };
......@@ -441,6 +454,32 @@ pub const Key = union(enum) {
441454 }
442455 };
443456
457 pub const Variable = struct {
458 ty: Index,
459 init: Index,
460 decl: Module.Decl.Index,
461 lib_name: OptionalNullTerminatedString = .none,
462 is_extern: bool = false,
463 is_const: bool = false,
464 is_threadlocal: bool = false,
465 is_weak_linkage: bool = false,
466 };
467
468 pub const ExternFunc = struct {
469 ty: Index,
470 /// The Decl that corresponds to the function itself.
471 decl: Module.Decl.Index,
472 /// Library name if specified.
473 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
474 /// Index into the string table bytes.
475 lib_name: OptionalNullTerminatedString,
476 };
477
478 pub const Func = struct {
479 ty: Index,
480 index: Module.Fn.Index,
481 };
482
444483 pub const Int = struct {
445484 ty: Index,
446485 storage: Storage,
......@@ -449,6 +488,8 @@ pub const Key = union(enum) {
449488 u64: u64,
450489 i64: i64,
451490 big_int: BigIntConst,
491 lazy_align: Index,
492 lazy_size: Index,
452493
453494 /// Big enough to fit any non-BigInt value
454495 pub const BigIntSpace = struct {
......@@ -460,13 +501,26 @@ pub const Key = union(enum) {
460501 pub fn toBigInt(storage: Storage, space: *BigIntSpace) BigIntConst {
461502 return switch (storage) {
462503 .big_int => |x| x,
463 .u64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
464 .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
504 inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
505 .lazy_align, .lazy_size => unreachable,
465506 };
466507 }
467508 };
468509 };
469510
511 pub const Error = struct {
512 ty: Index,
513 name: NullTerminatedString,
514 };
515
516 pub const ErrorUnion = struct {
517 ty: Index,
518 val: union(enum) {
519 err_name: NullTerminatedString,
520 payload: Index,
521 },
522 };
523
470524 pub const EnumTag = struct {
471525 /// The enum type.
472526 ty: Index,
......@@ -497,19 +551,8 @@ pub const Key = union(enum) {
497551 len: Index = .none,
498552
499553 pub const Addr = union(enum) {
500 @"var": struct {
501 init: Index,
502 owner_decl: Module.Decl.Index,
503 lib_name: OptionalNullTerminatedString,
504 is_const: bool,
505 is_threadlocal: bool,
506 is_weak_linkage: bool,
507 },
508554 decl: Module.Decl.Index,
509 mut_decl: struct {
510 decl: Module.Decl.Index,
511 runtime_index: RuntimeIndex,
512 },
555 mut_decl: MutDecl,
513556 int: Index,
514557 eu_payload: Index,
515558 opt_payload: Index,
......@@ -517,6 +560,10 @@ pub const Key = union(enum) {
517560 elem: BaseIndex,
518561 field: BaseIndex,
519562
563 pub const MutDecl = struct {
564 decl: Module.Decl.Index,
565 runtime_index: RuntimeIndex,
566 };
520567 pub const BaseIndex = struct {
521568 base: Index,
522569 index: u64,
......@@ -546,22 +593,31 @@ pub const Key = union(enum) {
546593 storage: Storage,
547594
548595 pub const Storage = union(enum) {
596 bytes: []const u8,
549597 elems: []const Index,
550598 repeated_elem: Index,
599
600 pub fn values(self: *const Storage) []const Index {
601 return switch (self.*) {
602 .bytes => &.{},
603 .elems => |elems| elems,
604 .repeated_elem => |*elem| @as(*const [1]Index, elem),
605 };
606 }
551607 };
552608 };
553609
554 pub fn hash32(key: Key) u32 {
555 return @truncate(u32, key.hash64());
610 pub fn hash32(key: Key, ip: *const InternPool) u32 {
611 return @truncate(u32, key.hash64(ip));
556612 }
557613
558 pub fn hash64(key: Key) u64 {
614 pub fn hash64(key: Key, ip: *const InternPool) u64 {
559615 var hasher = std.hash.Wyhash.init(0);
560 key.hashWithHasher(&hasher);
616 key.hashWithHasher(&hasher, ip);
561617 return hasher.final();
562618 }
563619
564 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash) void {
620 pub fn hashWithHasher(key: Key, hasher: *std.hash.Wyhash, ip: *const InternPool) void {
565621 const KeyTag = @typeInfo(Key).Union.tag_type.?;
566622 const key_tag: KeyTag = key;
567623 std.hash.autoHash(hasher, key_tag);
......@@ -575,27 +631,45 @@ pub const Key = union(enum) {
575631 .error_union_type,
576632 .simple_type,
577633 .simple_value,
578 .extern_func,
579634 .opt,
580635 .struct_type,
581636 .union_type,
582637 .un,
583638 .undef,
639 .err,
640 .error_union,
641 .enum_literal,
584642 .enum_tag,
585643 .inferred_error_set_type,
586644 => |info| std.hash.autoHash(hasher, info),
587645
646 .runtime_value => |runtime_value| std.hash.autoHash(hasher, runtime_value.val),
588647 .opaque_type => |opaque_type| std.hash.autoHash(hasher, opaque_type.decl),
589648 .enum_type => |enum_type| std.hash.autoHash(hasher, enum_type.decl),
590649
650 .variable => |variable| std.hash.autoHash(hasher, variable.decl),
651 .extern_func => |extern_func| std.hash.autoHash(hasher, extern_func.decl),
652 .func => |func| std.hash.autoHash(hasher, func.index),
653
591654 .int => |int| {
592655 // Canonicalize all integers by converting them to BigIntConst.
593 var buffer: Key.Int.Storage.BigIntSpace = undefined;
594 const big_int = int.storage.toBigInt(&buffer);
595
596 std.hash.autoHash(hasher, int.ty);
597 std.hash.autoHash(hasher, big_int.positive);
598 for (big_int.limbs) |limb| std.hash.autoHash(hasher, limb);
656 switch (int.storage) {
657 .u64, .i64, .big_int => {
658 var buffer: Key.Int.Storage.BigIntSpace = undefined;
659 const big_int = int.storage.toBigInt(&buffer);
660
661 std.hash.autoHash(hasher, int.ty);
662 std.hash.autoHash(hasher, big_int.positive);
663 for (big_int.limbs) |limb| std.hash.autoHash(hasher, limb);
664 },
665 .lazy_align, .lazy_size => |lazy_ty| {
666 std.hash.autoHash(
667 hasher,
668 @as(@typeInfo(Key.Int.Storage).Union.tag_type.?, int.storage),
669 );
670 std.hash.autoHash(hasher, lazy_ty);
671 },
672 }
599673 },
600674
601675 .float => |float| {
......@@ -615,7 +689,6 @@ pub const Key = union(enum) {
615689 // This is sound due to pointer provenance rules.
616690 std.hash.autoHash(hasher, @as(@typeInfo(Key.Ptr.Addr).Union.tag_type.?, ptr.addr));
617691 switch (ptr.addr) {
618 .@"var" => |@"var"| std.hash.autoHash(hasher, @"var".owner_decl),
619692 .decl => |decl| std.hash.autoHash(hasher, decl),
620693 .mut_decl => |mut_decl| std.hash.autoHash(hasher, mut_decl),
621694 .int => |int| std.hash.autoHash(hasher, int),
......@@ -629,13 +702,47 @@ pub const Key = union(enum) {
629702
630703 .aggregate => |aggregate| {
631704 std.hash.autoHash(hasher, aggregate.ty);
632 std.hash.autoHash(hasher, @as(
633 @typeInfo(Key.Aggregate.Storage).Union.tag_type.?,
634 aggregate.storage,
635 ));
705 switch (ip.indexToKey(aggregate.ty)) {
706 .array_type => |array_type| if (array_type.child == .u8_type) switch (aggregate.storage) {
707 .bytes => |bytes| for (bytes) |byte| std.hash.autoHash(hasher, byte),
708 .elems => |elems| {
709 var buffer: Key.Int.Storage.BigIntSpace = undefined;
710 for (elems) |elem| std.hash.autoHash(
711 hasher,
712 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
713 unreachable,
714 );
715 },
716 .repeated_elem => |elem| {
717 const len = ip.aggregateTypeLen(aggregate.ty);
718 var buffer: Key.Int.Storage.BigIntSpace = undefined;
719 const byte = ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
720 unreachable;
721 var i: u64 = 0;
722 while (i < len) : (i += 1) std.hash.autoHash(hasher, byte);
723 },
724 },
725 else => {},
726 }
727
636728 switch (aggregate.storage) {
637 .elems => |elems| for (elems) |elem| std.hash.autoHash(hasher, elem),
638 .repeated_elem => |elem| std.hash.autoHash(hasher, elem),
729 .bytes => unreachable,
730 .elems => |elems| {
731 var buffer: Key.Int.Storage.BigIntSpace = undefined;
732 for (elems) |elem| std.hash.autoHash(
733 hasher,
734 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
735 unreachable,
736 );
737 },
738 .repeated_elem => |elem| {
739 const len = ip.aggregateTypeLen(aggregate.ty);
740 var buffer: Key.Int.Storage.BigIntSpace = undefined;
741 const byte = ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch
742 unreachable;
743 var i: u64 = 0;
744 while (i < len) : (i += 1) std.hash.autoHash(hasher, byte);
745 },
639746 }
640747 },
641748
......@@ -663,7 +770,7 @@ pub const Key = union(enum) {
663770 }
664771 }
665772
666 pub fn eql(a: Key, b: Key) bool {
773 pub fn eql(a: Key, b: Key, ip: *const InternPool) bool {
667774 const KeyTag = @typeInfo(Key).Union.tag_type.?;
668775 const a_tag: KeyTag = a;
669776 const b_tag: KeyTag = b;
......@@ -709,9 +816,9 @@ pub const Key = union(enum) {
709816 const b_info = b.undef;
710817 return a_info == b_info;
711818 },
712 .extern_func => |a_info| {
713 const b_info = b.extern_func;
714 return std.meta.eql(a_info, b_info);
819 .runtime_value => |a_info| {
820 const b_info = b.runtime_value;
821 return a_info.val == b_info.val;
715822 },
716823 .opt => |a_info| {
717824 const b_info = b.opt;
......@@ -729,11 +836,36 @@ pub const Key = union(enum) {
729836 const b_info = b.un;
730837 return std.meta.eql(a_info, b_info);
731838 },
839 .err => |a_info| {
840 const b_info = b.err;
841 return std.meta.eql(a_info, b_info);
842 },
843 .error_union => |a_info| {
844 const b_info = b.error_union;
845 return std.meta.eql(a_info, b_info);
846 },
847 .enum_literal => |a_info| {
848 const b_info = b.enum_literal;
849 return a_info == b_info;
850 },
732851 .enum_tag => |a_info| {
733852 const b_info = b.enum_tag;
734853 return std.meta.eql(a_info, b_info);
735854 },
736855
856 .variable => |a_info| {
857 const b_info = b.variable;
858 return a_info.decl == b_info.decl;
859 },
860 .extern_func => |a_info| {
861 const b_info = b.extern_func;
862 return a_info.decl == b_info.decl;
863 },
864 .func => |a_info| {
865 const b_info = b.func;
866 return a_info.index == b_info.index;
867 },
868
737869 .ptr => |a_info| {
738870 const b_info = b.ptr;
739871 if (a_info.ty != b_info.ty or a_info.len != b_info.len) return false;
......@@ -742,7 +874,6 @@ pub const Key = union(enum) {
742874 if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false;
743875
744876 return switch (a_info.addr) {
745 .@"var" => |a_var| a_var.owner_decl == b_info.addr.@"var".owner_decl,
746877 .decl => |a_decl| a_decl == b_info.addr.decl,
747878 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),
748879 .int => |a_int| a_int == b_info.addr.int,
......@@ -765,16 +896,27 @@ pub const Key = union(enum) {
765896 .u64 => |bb| aa == bb,
766897 .i64 => |bb| aa == bb,
767898 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
899 .lazy_align, .lazy_size => false,
768900 },
769901 .i64 => |aa| switch (b_info.storage) {
770902 .u64 => |bb| aa == bb,
771903 .i64 => |bb| aa == bb,
772904 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
905 .lazy_align, .lazy_size => false,
773906 },
774907 .big_int => |aa| switch (b_info.storage) {
775908 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,
776909 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,
777910 .big_int => |bb| aa.eq(bb),
911 .lazy_align, .lazy_size => false,
912 },
913 .lazy_align => |aa| switch (b_info.storage) {
914 .u64, .i64, .big_int, .lazy_size => false,
915 .lazy_align => |bb| aa == bb,
916 },
917 .lazy_size => |aa| switch (b_info.storage) {
918 .u64, .i64, .big_int, .lazy_align => false,
919 .lazy_size => |bb| aa == bb,
778920 },
779921 };
780922 },
......@@ -818,12 +960,43 @@ pub const Key = union(enum) {
818960 if (a_info.ty != b_info.ty) return false;
819961
820962 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;
821 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) return false;
963 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) {
964 for (0..@intCast(usize, ip.aggregateTypeLen(a_info.ty))) |elem_index| {
965 const a_elem = switch (a_info.storage) {
966 .bytes => |bytes| ip.getIfExists(.{ .int = .{
967 .ty = .u8_type,
968 .storage = .{ .u64 = bytes[elem_index] },
969 } }) orelse return false,
970 .elems => |elems| elems[elem_index],
971 .repeated_elem => |elem| elem,
972 };
973 const b_elem = switch (b_info.storage) {
974 .bytes => |bytes| ip.getIfExists(.{ .int = .{
975 .ty = .u8_type,
976 .storage = .{ .u64 = bytes[elem_index] },
977 } }) orelse return false,
978 .elems => |elems| elems[elem_index],
979 .repeated_elem => |elem| elem,
980 };
981 if (a_elem != b_elem) return false;
982 }
983 return true;
984 }
822985
823 return switch (a_info.storage) {
824 .elems => |a_elems| std.mem.eql(Index, a_elems, b_info.storage.elems),
825 .repeated_elem => |a_elem| a_elem == b_info.storage.repeated_elem,
826 };
986 switch (a_info.storage) {
987 .bytes => |a_bytes| {
988 const b_bytes = b_info.storage.bytes;
989 return std.mem.eql(u8, a_bytes, b_bytes);
990 },
991 .elems => |a_elems| {
992 const b_elems = b_info.storage.elems;
993 return std.mem.eql(Index, a_elems, b_elems);
994 },
995 .repeated_elem => |a_elem| {
996 const b_elem = b_info.storage.repeated_elem;
997 return a_elem == b_elem;
998 },
999 }
8271000 },
8281001 .anon_struct_type => |a_info| {
8291002 const b_info = b.anon_struct_type;
......@@ -876,16 +1049,23 @@ pub const Key = union(enum) {
8761049 .func_type,
8771050 => .type_type,
8781051
879 inline .ptr,
1052 inline .runtime_value,
1053 .ptr,
8801054 .int,
8811055 .float,
8821056 .opt,
1057 .variable,
8831058 .extern_func,
1059 .func,
1060 .err,
1061 .error_union,
8841062 .enum_tag,
8851063 .aggregate,
8861064 .un,
8871065 => |x| x.ty,
8881066
1067 .enum_literal => .enum_literal_type,
1068
8891069 .undef => |x| x,
8901070
8911071 .simple_value => |s| switch (s) {
......@@ -977,8 +1157,8 @@ pub const Index = enum(u32) {
9771157 manyptr_const_u8_type,
9781158 manyptr_const_u8_sentinel_0_type,
9791159 single_const_pointer_to_comptime_int_type,
980 const_slice_u8_type,
981 const_slice_u8_sentinel_0_type,
1160 slice_const_u8_type,
1161 slice_const_u8_sentinel_0_type,
9821162 anyerror_void_error_union_type,
9831163 generic_poison_type,
9841164 inferred_alloc_const_type,
......@@ -1128,11 +1308,11 @@ pub const Index = enum(u32) {
11281308 },
11291309
11301310 undef: DataIsIndex,
1311 runtime_value: DataIsIndex,
11311312 simple_value: struct { data: SimpleValue },
1132 ptr_var: struct { data: *PtrVar },
11331313 ptr_mut_decl: struct { data: *PtrMutDecl },
11341314 ptr_decl: struct { data: *PtrDecl },
1135 ptr_int: struct { data: *PtrInt },
1315 ptr_int: struct { data: *PtrAddr },
11361316 ptr_eu_payload: DataIsIndex,
11371317 ptr_opt_payload: DataIsIndex,
11381318 ptr_comptime_field: struct { data: *PtrComptimeField },
......@@ -1151,6 +1331,12 @@ pub const Index = enum(u32) {
11511331 int_small: struct { data: *IntSmall },
11521332 int_positive: struct { data: u32 },
11531333 int_negative: struct { data: u32 },
1334 int_lazy_align: struct { data: *IntLazy },
1335 int_lazy_size: struct { data: *IntLazy },
1336 error_set_error: struct { data: *Key.Error },
1337 error_union_error: struct { data: *Key.Error },
1338 error_union_payload: struct { data: *TypeValue },
1339 enum_literal: struct { data: NullTerminatedString },
11541340 enum_tag: struct { data: *Key.EnumTag },
11551341 float_f16: struct { data: f16 },
11561342 float_f32: struct { data: f32 },
......@@ -1160,18 +1346,21 @@ pub const Index = enum(u32) {
11601346 float_c_longdouble_f80: struct { data: *Float80 },
11611347 float_c_longdouble_f128: struct { data: *Float128 },
11621348 float_comptime_float: struct { data: *Float128 },
1349 variable: struct { data: *Variable },
11631350 extern_func: struct { data: void },
11641351 func: struct { data: void },
11651352 only_possible_value: DataIsIndex,
11661353 union_value: struct { data: *Key.Union },
1354 bytes: struct { data: *Bytes },
11671355 aggregate: struct { data: *Aggregate },
11681356 repeated: struct { data: *Repeated },
11691357 }) void {
11701358 _ = self;
1171 @setEvalBranchQuota(10_000);
1172 inline for (@typeInfo(Tag).Enum.fields) |tag| {
1173 inline for (@typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields) |entry| {
1174 if (comptime std.mem.eql(u8, tag.name, entry.name)) break;
1359 const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields;
1360 @setEvalBranchQuota(2_000);
1361 inline for (@typeInfo(Tag).Enum.fields, 0..) |tag, start| {
1362 inline for (0..map_fields.len) |offset| {
1363 if (comptime std.mem.eql(u8, tag.name, map_fields[(start + offset) % map_fields.len].name)) break;
11751364 } else {
11761365 @compileError(@typeName(Tag) ++ "." ++ tag.name ++ " missing dbHelper tag_to_encoding_map entry");
11771366 }
......@@ -1318,14 +1507,14 @@ pub const static_keys = [_]Key{
13181507 .is_const = true,
13191508 } },
13201509
1321 // const_slice_u8_type
1510 // slice_const_u8_type
13221511 .{ .ptr_type = .{
13231512 .elem_type = .u8_type,
13241513 .size = .Slice,
13251514 .is_const = true,
13261515 } },
13271516
1328 // const_slice_u8_sentinel_0_type
1517 // slice_const_u8_sentinel_0_type
13291518 .{ .ptr_type = .{
13301519 .elem_type = .u8_type,
13311520 .sentinel = .zero_u8,
......@@ -1505,12 +1694,13 @@ pub const Tag = enum(u8) {
15051694 /// `data` is `Index` of the type.
15061695 /// Untyped `undefined` is stored instead via `simple_value`.
15071696 undef,
1697 /// A wrapper for values which are comptime-known but should
1698 /// semantically be runtime-known.
1699 /// `data` is `Index` of the value.
1700 runtime_value,
15081701 /// A value that can be represented with only an enum tag.
15091702 /// data is SimpleValue enum value.
15101703 simple_value,
1511 /// A pointer to a var.
1512 /// data is extra index of PtrVal, which contains the type and address.
1513 ptr_var,
15141704 /// A pointer to a decl that can be mutated at comptime.
15151705 /// data is extra index of PtrMutDecl, which contains the type and address.
15161706 ptr_mut_decl,
......@@ -1518,7 +1708,7 @@ pub const Tag = enum(u8) {
15181708 /// data is extra index of PtrDecl, which contains the type and address.
15191709 ptr_decl,
15201710 /// A pointer with an integer value.
1521 /// data is extra index of PtrInt, which contains the type and address.
1711 /// data is extra index of PtrAddr, which contains the type and address.
15221712 /// Only pointer types are allowed to have this encoding. Optional types must use
15231713 /// `opt_payload` or `opt_null`.
15241714 ptr_int,
......@@ -1585,6 +1775,24 @@ pub const Tag = enum(u8) {
15851775 /// A negative integer value.
15861776 /// data is a limbs index to `Int`.
15871777 int_negative,
1778 /// The ABI alignment of a lazy type.
1779 /// data is extra index of `IntLazy`.
1780 int_lazy_align,
1781 /// The ABI size of a lazy type.
1782 /// data is extra index of `IntLazy`.
1783 int_lazy_size,
1784 /// An error value.
1785 /// data is extra index of `Key.Error`.
1786 error_set_error,
1787 /// An error union error.
1788 /// data is extra index of `Key.Error`.
1789 error_union_error,
1790 /// An error union payload.
1791 /// data is extra index of `TypeValue`.
1792 error_union_payload,
1793 /// An enum literal value.
1794 /// data is `NullTerminatedString` of the error name.
1795 enum_literal,
15881796 /// An enum tag value.
15891797 /// data is extra index of `Key.EnumTag`.
15901798 enum_tag,
......@@ -1617,9 +1825,14 @@ pub const Tag = enum(u8) {
16171825 /// A comptime_float value.
16181826 /// data is extra index to Float128.
16191827 float_comptime_float,
1828 /// A global variable.
1829 /// data is extra index to Variable.
1830 variable,
16201831 /// An extern function.
1832 /// data is extra index to Key.ExternFunc.
16211833 extern_func,
16221834 /// A regular function.
1835 /// data is extra index to Key.Func.
16231836 func,
16241837 /// This represents the only possible value for *some* types which have
16251838 /// only one possible value. Not all only-possible-values are encoded this way;
......@@ -1631,6 +1844,9 @@ pub const Tag = enum(u8) {
16311844 only_possible_value,
16321845 /// data is extra index to Key.Union.
16331846 union_value,
1847 /// An array of bytes.
1848 /// data is extra index to `Bytes`.
1849 bytes,
16341850 /// An instance of a struct, array, or vector.
16351851 /// data is extra index to `Aggregate`.
16361852 aggregate,
......@@ -1670,6 +1886,13 @@ pub const TypeFunction = struct {
16701886 };
16711887};
16721888
1889pub const Bytes = struct {
1890 /// The type of the aggregate
1891 ty: Index,
1892 /// Index into string_bytes, of len ip.aggregateTypeLen(ty)
1893 bytes: String,
1894};
1895
16731896/// Trailing:
16741897/// 0. element: Index for each len
16751898/// len is determined by the aggregate type.
......@@ -1843,6 +2066,11 @@ pub const Array = struct {
18432066 }
18442067};
18452068
2069pub const TypeValue = struct {
2070 ty: Index,
2071 val: Index,
2072};
2073
18462074/// Trailing:
18472075/// 0. field name: NullTerminatedString for each fields_len; declaration order
18482076/// 1. tag value: Index for each fields_len; declaration order
......@@ -1888,21 +2116,22 @@ pub const PackedU64 = packed struct(u64) {
18882116 }
18892117};
18902118
1891pub const PtrVar = struct {
1892 ty: Index,
1893 /// If flags.is_extern == true this is `none`.
2119pub const Variable = struct {
2120 /// This is a value if has_init is true, otherwise a type.
18942121 init: Index,
1895 owner_decl: Module.Decl.Index,
2122 decl: Module.Decl.Index,
18962123 /// Library name if specified.
18972124 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
18982125 lib_name: OptionalNullTerminatedString,
18992126 flags: Flags,
19002127
19012128 pub const Flags = packed struct(u32) {
2129 has_init: bool,
2130 is_extern: bool,
19022131 is_const: bool,
19032132 is_threadlocal: bool,
19042133 is_weak_linkage: bool,
1905 _: u29 = 0,
2134 _: u27 = 0,
19062135 };
19072136};
19082137
......@@ -1917,7 +2146,7 @@ pub const PtrMutDecl = struct {
19172146 runtime_index: RuntimeIndex,
19182147};
19192148
1920pub const PtrInt = struct {
2149pub const PtrAddr = struct {
19212150 ty: Index,
19222151 addr: Index,
19232152};
......@@ -1949,6 +2178,11 @@ pub const IntSmall = struct {
19492178 value: u32,
19502179};
19512180
2181pub const IntLazy = struct {
2182 ty: Index,
2183 lazy_ty: Index,
2184};
2185
19522186/// A f64 value, broken up into 2 u32 parts.
19532187pub const Float64 = struct {
19542188 piece0: u32,
......@@ -2063,6 +2297,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void {
20632297 ip.unions_free_list.deinit(gpa);
20642298 ip.allocated_unions.deinit(gpa);
20652299
2300 ip.funcs_free_list.deinit(gpa);
2301 ip.allocated_funcs.deinit(gpa);
2302
20662303 ip.inferred_error_sets_free_list.deinit(gpa);
20672304 ip.allocated_inferred_error_sets.deinit(gpa);
20682305
......@@ -2235,6 +2472,13 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
22352472 .type_function => .{ .func_type = indexToKeyFuncType(ip, data) },
22362473
22372474 .undef => .{ .undef = @intToEnum(Index, data) },
2475 .runtime_value => {
2476 const val = @intToEnum(Index, data);
2477 return .{ .runtime_value = .{
2478 .ty = ip.typeOf(val),
2479 .val = val,
2480 } };
2481 },
22382482 .opt_null => .{ .opt = .{
22392483 .ty = @intToEnum(Index, data),
22402484 .val = .none,
......@@ -2251,18 +2495,11 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
22512495 .val = payload_val,
22522496 } };
22532497 },
2254 .ptr_var => {
2255 const info = ip.extraData(PtrVar, data);
2498 .ptr_decl => {
2499 const info = ip.extraData(PtrDecl, data);
22562500 return .{ .ptr = .{
22572501 .ty = info.ty,
2258 .addr = .{ .@"var" = .{
2259 .init = info.init,
2260 .owner_decl = info.owner_decl,
2261 .lib_name = info.lib_name,
2262 .is_const = info.flags.is_const,
2263 .is_threadlocal = info.flags.is_threadlocal,
2264 .is_weak_linkage = info.flags.is_weak_linkage,
2265 } },
2502 .addr = .{ .decl = info.decl },
22662503 } };
22672504 },
22682505 .ptr_mut_decl => {
......@@ -2275,15 +2512,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
22752512 } },
22762513 } };
22772514 },
2278 .ptr_decl => {
2279 const info = ip.extraData(PtrDecl, data);
2280 return .{ .ptr = .{
2281 .ty = info.ty,
2282 .addr = .{ .decl = info.decl },
2283 } };
2284 },
22852515 .ptr_int => {
2286 const info = ip.extraData(PtrInt, data);
2516 const info = ip.extraData(PtrAddr, data);
22872517 return .{ .ptr = .{
22882518 .ty = info.ty,
22892519 .addr = .{ .int = info.addr },
......@@ -2383,6 +2613,17 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
23832613 .storage = .{ .u64 = info.value },
23842614 } };
23852615 },
2616 .int_lazy_align, .int_lazy_size => |tag| {
2617 const info = ip.extraData(IntLazy, data);
2618 return .{ .int = .{
2619 .ty = info.ty,
2620 .storage = switch (tag) {
2621 .int_lazy_align => .{ .lazy_align = info.lazy_ty },
2622 .int_lazy_size => .{ .lazy_size = info.lazy_ty },
2623 else => unreachable,
2624 },
2625 } };
2626 },
23862627 .float_f16 => .{ .float = .{
23872628 .ty = .f16_type,
23882629 .storage = .{ .f16 = @bitCast(f16, @intCast(u16, data)) },
......@@ -2415,8 +2656,21 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
24152656 .ty = .comptime_float_type,
24162657 .storage = .{ .f128 = ip.extraData(Float128, data).get() },
24172658 } },
2418 .extern_func => @panic("TODO"),
2419 .func => @panic("TODO"),
2659 .variable => {
2660 const extra = ip.extraData(Variable, data);
2661 return .{ .variable = .{
2662 .ty = if (extra.flags.has_init) ip.typeOf(extra.init) else extra.init,
2663 .init = if (extra.flags.has_init) extra.init else .none,
2664 .decl = extra.decl,
2665 .lib_name = extra.lib_name,
2666 .is_extern = extra.flags.is_extern,
2667 .is_const = extra.flags.is_const,
2668 .is_threadlocal = extra.flags.is_threadlocal,
2669 .is_weak_linkage = extra.flags.is_weak_linkage,
2670 } };
2671 },
2672 .extern_func => .{ .extern_func = ip.extraData(Key.ExternFunc, data) },
2673 .func => .{ .func = ip.extraData(Key.Func, data) },
24202674 .only_possible_value => {
24212675 const ty = @intToEnum(Index, data);
24222676 return switch (ip.indexToKey(ty)) {
......@@ -2438,6 +2692,14 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
24382692 else => unreachable,
24392693 };
24402694 },
2695 .bytes => {
2696 const extra = ip.extraData(Bytes, data);
2697 const len = @intCast(u32, ip.aggregateTypeLen(extra.ty));
2698 return .{ .aggregate = .{
2699 .ty = extra.ty,
2700 .storage = .{ .bytes = ip.string_bytes.items[@enumToInt(extra.bytes)..][0..len] },
2701 } };
2702 },
24412703 .aggregate => {
24422704 const extra = ip.extraDataTrail(Aggregate, data);
24432705 const len = @intCast(u32, ip.aggregateTypeLen(extra.data.ty));
......@@ -2455,6 +2717,22 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
24552717 } };
24562718 },
24572719 .union_value => .{ .un = ip.extraData(Key.Union, data) },
2720 .error_set_error => .{ .err = ip.extraData(Key.Error, data) },
2721 .error_union_error => {
2722 const extra = ip.extraData(Key.Error, data);
2723 return .{ .error_union = .{
2724 .ty = extra.ty,
2725 .val = .{ .err_name = extra.name },
2726 } };
2727 },
2728 .error_union_payload => {
2729 const extra = ip.extraData(TypeValue, data);
2730 return .{ .error_union = .{
2731 .ty = extra.ty,
2732 .val = .{ .payload = extra.val },
2733 } };
2734 },
2735 .enum_literal => .{ .enum_literal = @intToEnum(NullTerminatedString, data) },
24582736 .enum_tag => .{ .enum_tag = ip.extraData(Key.EnumTag, data) },
24592737 };
24602738}
......@@ -2547,7 +2825,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
25472825 _ = ip.map.pop();
25482826 var new_key = key;
25492827 new_key.ptr_type.size = .Many;
2550 const ptr_type_index = try get(ip, gpa, new_key);
2828 const ptr_type_index = try ip.get(gpa, new_key);
25512829 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
25522830 try ip.items.ensureUnusedCapacity(gpa, 1);
25532831 ip.items.appendAssumeCapacity(.{
......@@ -2677,6 +2955,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
26772955 .data = @enumToInt(ty),
26782956 });
26792957 },
2958 .runtime_value => |runtime_value| {
2959 assert(runtime_value.ty == ip.typeOf(runtime_value.val));
2960 ip.items.appendAssumeCapacity(.{
2961 .tag = .runtime_value,
2962 .data = @enumToInt(runtime_value.val),
2963 });
2964 },
26802965
26812966 .struct_type => |struct_type| {
26822967 ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{
......@@ -2809,7 +3094,35 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
28093094 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, func_type.param_types));
28103095 },
28113096
2812 .extern_func => @panic("TODO"),
3097 .variable => |variable| {
3098 const has_init = variable.init != .none;
3099 if (has_init) assert(variable.ty == ip.typeOf(variable.init));
3100 ip.items.appendAssumeCapacity(.{
3101 .tag = .variable,
3102 .data = try ip.addExtra(gpa, Variable{
3103 .init = if (has_init) variable.init else variable.ty,
3104 .decl = variable.decl,
3105 .lib_name = variable.lib_name,
3106 .flags = .{
3107 .has_init = has_init,
3108 .is_extern = variable.is_extern,
3109 .is_const = variable.is_const,
3110 .is_threadlocal = variable.is_threadlocal,
3111 .is_weak_linkage = variable.is_weak_linkage,
3112 },
3113 }),
3114 });
3115 },
3116
3117 .extern_func => |extern_func| ip.items.appendAssumeCapacity(.{
3118 .tag = .extern_func,
3119 .data = try ip.addExtra(gpa, extern_func),
3120 }),
3121
3122 .func => |func| ip.items.appendAssumeCapacity(.{
3123 .tag = .func,
3124 .data = try ip.addExtra(gpa, func),
3125 }),
28133126
28143127 .ptr => |ptr| {
28153128 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
......@@ -2817,20 +3130,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
28173130 .none => {
28183131 assert(ptr_type.size != .Slice);
28193132 switch (ptr.addr) {
2820 .@"var" => |@"var"| ip.items.appendAssumeCapacity(.{
2821 .tag = .ptr_var,
2822 .data = try ip.addExtra(gpa, PtrVar{
2823 .ty = ptr.ty,
2824 .init = @"var".init,
2825 .owner_decl = @"var".owner_decl,
2826 .lib_name = @"var".lib_name,
2827 .flags = .{
2828 .is_const = @"var".is_const,
2829 .is_threadlocal = @"var".is_threadlocal,
2830 .is_weak_linkage = @"var".is_weak_linkage,
2831 },
2832 }),
2833 }),
28343133 .decl => |decl| ip.items.appendAssumeCapacity(.{
28353134 .tag = .ptr_decl,
28363135 .data = try ip.addExtra(gpa, PtrDecl{
......@@ -2846,31 +3145,41 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
28463145 .runtime_index = mut_decl.runtime_index,
28473146 }),
28483147 }),
2849 .int => |int| ip.items.appendAssumeCapacity(.{
2850 .tag = .ptr_int,
2851 .data = try ip.addExtra(gpa, PtrInt{
2852 .ty = ptr.ty,
2853 .addr = int,
2854 }),
2855 }),
2856 .eu_payload, .opt_payload => |data| ip.items.appendAssumeCapacity(.{
2857 .tag = switch (ptr.addr) {
2858 .eu_payload => .ptr_eu_payload,
2859 .opt_payload => .ptr_opt_payload,
2860 else => unreachable,
2861 },
2862 .data = @enumToInt(data),
2863 }),
2864 .comptime_field => |field_val| ip.items.appendAssumeCapacity(.{
2865 .tag = .ptr_comptime_field,
2866 .data = try ip.addExtra(gpa, PtrComptimeField{
2867 .ty = ptr.ty,
2868 .field_val = field_val,
2869 }),
2870 }),
3148 .int => |int| {
3149 assert(int != .none);
3150 ip.items.appendAssumeCapacity(.{
3151 .tag = .ptr_int,
3152 .data = try ip.addExtra(gpa, PtrAddr{
3153 .ty = ptr.ty,
3154 .addr = int,
3155 }),
3156 });
3157 },
3158 .eu_payload, .opt_payload => |data| {
3159 assert(data != .none);
3160 ip.items.appendAssumeCapacity(.{
3161 .tag = switch (ptr.addr) {
3162 .eu_payload => .ptr_eu_payload,
3163 .opt_payload => .ptr_opt_payload,
3164 else => unreachable,
3165 },
3166 .data = @enumToInt(data),
3167 });
3168 },
3169 .comptime_field => |field_val| {
3170 assert(field_val != .none);
3171 ip.items.appendAssumeCapacity(.{
3172 .tag = .ptr_comptime_field,
3173 .data = try ip.addExtra(gpa, PtrComptimeField{
3174 .ty = ptr.ty,
3175 .field_val = field_val,
3176 }),
3177 });
3178 },
28713179 .elem, .field => |base_index| {
3180 assert(base_index.base != .none);
28723181 _ = ip.map.pop();
2873 const index_index = try get(ip, gpa, .{ .int = .{
3182 const index_index = try ip.get(gpa, .{ .int = .{
28743183 .ty = .usize_type,
28753184 .storage = .{ .u64 = base_index.index },
28763185 } });
......@@ -2894,7 +3203,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
28943203 new_key.ptr.ty = ip.slicePtrType(ptr.ty);
28953204 new_key.ptr.len = .none;
28963205 assert(ip.indexToKey(new_key.ptr.ty).ptr_type.size == .Many);
2897 const ptr_index = try get(ip, gpa, new_key);
3206 const ptr_index = try ip.get(gpa, new_key);
28983207 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
28993208 try ip.items.ensureUnusedCapacity(gpa, 1);
29003209 ip.items.appendAssumeCapacity(.{
......@@ -2921,8 +3230,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
29213230 },
29223231
29233232 .int => |int| b: {
3233 assert(int.ty == .comptime_int_type or ip.indexToKey(int.ty) == .int_type);
3234 switch (int.storage) {
3235 .u64, .i64, .big_int => {},
3236 .lazy_align, .lazy_size => |lazy_ty| {
3237 ip.items.appendAssumeCapacity(.{
3238 .tag = switch (int.storage) {
3239 else => unreachable,
3240 .lazy_align => .int_lazy_align,
3241 .lazy_size => .int_lazy_size,
3242 },
3243 .data = try ip.addExtra(gpa, IntLazy{
3244 .ty = int.ty,
3245 .lazy_ty = lazy_ty,
3246 }),
3247 });
3248 return @intToEnum(Index, ip.items.len - 1);
3249 },
3250 }
29243251 switch (int.ty) {
2925 .none => unreachable,
29263252 .u8_type => switch (int.storage) {
29273253 .big_int => |big_int| {
29283254 ip.items.appendAssumeCapacity(.{
......@@ -2938,6 +3264,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
29383264 });
29393265 break :b;
29403266 },
3267 .lazy_align, .lazy_size => unreachable,
29413268 },
29423269 .u16_type => switch (int.storage) {
29433270 .big_int => |big_int| {
......@@ -2954,6 +3281,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
29543281 });
29553282 break :b;
29563283 },
3284 .lazy_align, .lazy_size => unreachable,
29573285 },
29583286 .u32_type => switch (int.storage) {
29593287 .big_int => |big_int| {
......@@ -2970,6 +3298,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
29703298 });
29713299 break :b;
29723300 },
3301 .lazy_align, .lazy_size => unreachable,
29733302 },
29743303 .i32_type => switch (int.storage) {
29753304 .big_int => |big_int| {
......@@ -2987,6 +3316,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
29873316 });
29883317 break :b;
29893318 },
3319 .lazy_align, .lazy_size => unreachable,
29903320 },
29913321 .usize_type => switch (int.storage) {
29923322 .big_int => |big_int| {
......@@ -3007,6 +3337,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
30073337 break :b;
30083338 }
30093339 },
3340 .lazy_align, .lazy_size => unreachable,
30103341 },
30113342 .comptime_int_type => switch (int.storage) {
30123343 .big_int => |big_int| {
......@@ -3041,6 +3372,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
30413372 break :b;
30423373 }
30433374 },
3375 .lazy_align, .lazy_size => unreachable,
30443376 },
30453377 else => {},
30463378 }
......@@ -3077,9 +3409,37 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
30773409 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
30783410 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
30793411 },
3412 .lazy_align, .lazy_size => unreachable,
30803413 }
30813414 },
30823415
3416 .err => |err| ip.items.appendAssumeCapacity(.{
3417 .tag = .error_set_error,
3418 .data = try ip.addExtra(gpa, err),
3419 }),
3420
3421 .error_union => |error_union| ip.items.appendAssumeCapacity(switch (error_union.val) {
3422 .err_name => |err_name| .{
3423 .tag = .error_union_error,
3424 .data = try ip.addExtra(gpa, Key.Error{
3425 .ty = error_union.ty,
3426 .name = err_name,
3427 }),
3428 },
3429 .payload => |payload| .{
3430 .tag = .error_union_payload,
3431 .data = try ip.addExtra(gpa, TypeValue{
3432 .ty = error_union.ty,
3433 .val = payload,
3434 }),
3435 },
3436 }),
3437
3438 .enum_literal => |enum_literal| ip.items.appendAssumeCapacity(.{
3439 .tag = .enum_literal,
3440 .data = @enumToInt(enum_literal),
3441 }),
3442
30833443 .enum_tag => |enum_tag| {
30843444 assert(enum_tag.ty != .none);
30853445 assert(enum_tag.int != .none);
......@@ -3131,9 +3491,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
31313491 },
31323492
31333493 .aggregate => |aggregate| {
3134 assert(aggregate.ty != .none);
3494 const ty_key = ip.indexToKey(aggregate.ty);
31353495 const aggregate_len = ip.aggregateTypeLen(aggregate.ty);
31363496 switch (aggregate.storage) {
3497 .bytes => {
3498 assert(ty_key.array_type.child == .u8_type);
3499 },
31373500 .elems => |elems| {
31383501 assert(elems.len == aggregate_len);
31393502 for (elems) |elem| assert(elem != .none);
......@@ -3151,9 +3514,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
31513514 return @intToEnum(Index, ip.items.len - 1);
31523515 }
31533516
3154 switch (ip.indexToKey(aggregate.ty)) {
3517 switch (ty_key) {
31553518 .anon_struct_type => |anon_struct_type| {
31563519 if (switch (aggregate.storage) {
3520 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {
3521 if (value != ip.getIfExists(.{ .int = .{
3522 .ty = .u8_type,
3523 .storage = .{ .u64 = byte },
3524 } })) break false;
3525 } else true,
31573526 .elems => |elems| std.mem.eql(Index, anon_struct_type.values, elems),
31583527 .repeated_elem => |elem| for (anon_struct_type.values) |value| {
31593528 if (value != elem) break false;
......@@ -3173,34 +3542,80 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
31733542 }
31743543
31753544 if (switch (aggregate.storage) {
3545 .bytes => |bytes| for (bytes[1..]) |byte| {
3546 if (byte != bytes[0]) break false;
3547 } else true,
31763548 .elems => |elems| for (elems[1..]) |elem| {
31773549 if (elem != elems[0]) break false;
31783550 } else true,
31793551 .repeated_elem => true,
31803552 }) {
3553 const elem = switch (aggregate.storage) {
3554 .bytes => |bytes| elem: {
3555 _ = ip.map.pop();
3556 const elem = try ip.get(gpa, .{ .int = .{
3557 .ty = .u8_type,
3558 .storage = .{ .u64 = bytes[0] },
3559 } });
3560 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3561 try ip.items.ensureUnusedCapacity(gpa, 1);
3562 break :elem elem;
3563 },
3564 .elems => |elems| elems[0],
3565 .repeated_elem => |elem| elem,
3566 };
3567
31813568 try ip.extra.ensureUnusedCapacity(
31823569 gpa,
31833570 @typeInfo(Repeated).Struct.fields.len,
31843571 );
3185
31863572 ip.items.appendAssumeCapacity(.{
31873573 .tag = .repeated,
31883574 .data = ip.addExtraAssumeCapacity(Repeated{
31893575 .ty = aggregate.ty,
3190 .elem_val = switch (aggregate.storage) {
3191 .elems => |elems| elems[0],
3192 .repeated_elem => |elem| elem,
3193 },
3576 .elem_val = elem,
31943577 }),
31953578 });
31963579 return @intToEnum(Index, ip.items.len - 1);
31973580 }
31983581
3582 switch (ty_key) {
3583 .array_type => |array_type| if (array_type.child == .u8_type) {
3584 const len_including_sentinel = aggregate_len + @boolToInt(array_type.sentinel != .none);
3585 try ip.string_bytes.ensureUnusedCapacity(gpa, len_including_sentinel + 1);
3586 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
3587 var buffer: Key.Int.Storage.BigIntSpace = undefined;
3588 switch (aggregate.storage) {
3589 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
3590 .elems => |elems| for (elems) |elem| ip.string_bytes.appendAssumeCapacity(
3591 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,
3592 ),
3593 .repeated_elem => |elem| @memset(
3594 ip.string_bytes.addManyAsSliceAssumeCapacity(aggregate_len),
3595 ip.indexToKey(elem).int.storage.toBigInt(&buffer).to(u8) catch unreachable,
3596 ),
3597 }
3598 if (array_type.sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3599 ip.indexToKey(array_type.sentinel).int.storage.toBigInt(&buffer).to(u8) catch
3600 unreachable,
3601 );
3602 const bytes = try ip.getOrPutTrailingString(gpa, len_including_sentinel);
3603 ip.items.appendAssumeCapacity(.{
3604 .tag = .bytes,
3605 .data = ip.addExtraAssumeCapacity(Bytes{
3606 .ty = aggregate.ty,
3607 .bytes = bytes.toString(),
3608 }),
3609 });
3610 return @intToEnum(Index, ip.items.len - 1);
3611 },
3612 else => {},
3613 }
3614
31993615 try ip.extra.ensureUnusedCapacity(
32003616 gpa,
32013617 @typeInfo(Aggregate).Struct.fields.len + aggregate_len,
32023618 );
3203
32043619 ip.items.appendAssumeCapacity(.{
32053620 .tag = .aggregate,
32063621 .data = ip.addExtraAssumeCapacity(Aggregate{
......@@ -3423,12 +3838,16 @@ pub fn finishGetEnum(
34233838 return @intToEnum(Index, ip.items.len - 1);
34243839}
34253840
3426pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
3841pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
34273842 const adapter: KeyAdapter = .{ .intern_pool = ip };
3428 const index = ip.map.getIndexAdapted(key, adapter).?;
3843 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;
34293844 return @intToEnum(Index, index);
34303845}
34313846
3847pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
3848 return ip.getIfExists(key).?;
3849}
3850
34323851fn addStringsToMap(
34333852 ip: *InternPool,
34343853 gpa: Allocator,
......@@ -3500,9 +3919,11 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
35003919 Module.Decl.Index => @enumToInt(@field(extra, field.name)),
35013920 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),
35023921 Module.Namespace.OptionalIndex => @enumToInt(@field(extra, field.name)),
3922 Module.Fn.Index => @enumToInt(@field(extra, field.name)),
35033923 MapIndex => @enumToInt(@field(extra, field.name)),
35043924 OptionalMapIndex => @enumToInt(@field(extra, field.name)),
35053925 RuntimeIndex => @enumToInt(@field(extra, field.name)),
3926 String => @enumToInt(@field(extra, field.name)),
35063927 NullTerminatedString => @enumToInt(@field(extra, field.name)),
35073928 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),
35083929 i32 => @bitCast(u32, @field(extra, field.name)),
......@@ -3510,7 +3931,7 @@ fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
35103931 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
35113932 Pointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
35123933 Pointer.VectorIndex => @enumToInt(@field(extra, field.name)),
3513 PtrVar.Flags => @bitCast(u32, @field(extra, field.name)),
3934 Variable.Flags => @bitCast(u32, @field(extra, field.name)),
35143935 else => @compileError("bad field type: " ++ @typeName(field.type)),
35153936 });
35163937 }
......@@ -3566,9 +3987,11 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
35663987 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),
35673988 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),
35683989 Module.Namespace.OptionalIndex => @intToEnum(Module.Namespace.OptionalIndex, int32),
3990 Module.Fn.Index => @intToEnum(Module.Fn.Index, int32),
35693991 MapIndex => @intToEnum(MapIndex, int32),
35703992 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),
35713993 RuntimeIndex => @intToEnum(RuntimeIndex, int32),
3994 String => @intToEnum(String, int32),
35723995 NullTerminatedString => @intToEnum(NullTerminatedString, int32),
35733996 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),
35743997 i32 => @bitCast(i32, int32),
......@@ -3576,7 +3999,7 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
35763999 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
35774000 Pointer.PackedOffset => @bitCast(Pointer.PackedOffset, int32),
35784001 Pointer.VectorIndex => @intToEnum(Pointer.VectorIndex, int32),
3579 PtrVar.Flags => @bitCast(PtrVar.Flags, int32),
4002 Variable.Flags => @bitCast(Variable.Flags, int32),
35804003 else => @compileError("bad field type: " ++ @typeName(field.type)),
35814004 };
35824005 }
......@@ -3700,8 +4123,8 @@ pub fn childType(ip: InternPool, i: Index) Index {
37004123/// Given a slice type, returns the type of the ptr field.
37014124pub fn slicePtrType(ip: InternPool, i: Index) Index {
37024125 switch (i) {
3703 .const_slice_u8_type => return .manyptr_const_u8_type,
3704 .const_slice_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
4126 .slice_const_u8_type => return .manyptr_const_u8_type,
4127 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
37054128 else => {},
37064129 }
37074130 const item = ip.items.get(@enumToInt(i));
......@@ -3830,6 +4253,8 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind
38304253 } },
38314254 } });
38324255 },
4256
4257 .lazy_align, .lazy_size => unreachable,
38334258 }
38344259}
38354260
......@@ -3862,6 +4287,14 @@ pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
38624287 }
38634288}
38644289
4290pub fn indexToFunc(ip: InternPool, val: Index) Module.Fn.OptionalIndex {
4291 assert(val != .none);
4292 const tags = ip.items.items(.tag);
4293 if (tags[@enumToInt(val)] != .func) return .none;
4294 const datas = ip.items.items(.data);
4295 return ip.extraData(Key.Func, datas[@enumToInt(val)]).index.toOptional();
4296}
4297
38654298pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
38664299 assert(val != .none);
38674300 const tags = ip.items.items(.tag);
......@@ -3891,6 +4324,15 @@ pub fn isInferredErrorSetType(ip: InternPool, ty: Index) bool {
38914324 return tags[@enumToInt(ty)] == .type_inferred_error_set;
38924325}
38934326
4327/// The is only legal because the initializer is not part of the hash.
4328pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {
4329 assert(ip.items.items(.tag)[@enumToInt(index)] == .variable);
4330 const field_index = inline for (@typeInfo(Variable).Struct.fields, 0..) |field, field_index| {
4331 if (comptime std.mem.eql(u8, field.name, "init")) break field_index;
4332 } else unreachable;
4333 ip.extra.items[ip.items.items(.data)[@enumToInt(index)] + field_index] = @enumToInt(init_index);
4334}
4335
38944336pub fn dump(ip: InternPool) void {
38954337 dumpFallible(ip, std.heap.page_allocator) catch return;
38964338}
......@@ -3903,10 +4345,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
39034345 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
39044346 const unions_size = ip.allocated_unions.len *
39054347 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4348 const funcs_size = ip.allocated_funcs.len *
4349 (@sizeOf(Module.Fn) + @sizeOf(Module.Decl));
39064350
39074351 // TODO: map overhead size is not taken into account
39084352 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
3909 structs_size + unions_size;
4353 structs_size + unions_size + funcs_size;
39104354
39114355 std.debug.print(
39124356 \\InternPool size: {d} bytes
......@@ -3915,6 +4359,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
39154359 \\ {d} limbs: {d} bytes
39164360 \\ {d} structs: {d} bytes
39174361 \\ {d} unions: {d} bytes
4362 \\ {d} funcs: {d} bytes
39184363 \\
39194364 , .{
39204365 total_size,
......@@ -3928,6 +4373,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
39284373 structs_size,
39294374 ip.allocated_unions.len,
39304375 unions_size,
4376 ip.allocated_funcs.len,
4377 funcs_size,
39314378 });
39324379
39334380 const tags = ip.items.items(.tag);
......@@ -3982,12 +4429,12 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
39824429 },
39834430
39844431 .undef => 0,
4432 .runtime_value => 0,
39854433 .simple_type => 0,
39864434 .simple_value => 0,
3987 .ptr_var => @sizeOf(PtrVar),
39884435 .ptr_decl => @sizeOf(PtrDecl),
39894436 .ptr_mut_decl => @sizeOf(PtrMutDecl),
3990 .ptr_int => @sizeOf(PtrInt),
4437 .ptr_int => @sizeOf(PtrAddr),
39914438 .ptr_eu_payload => 0,
39924439 .ptr_opt_payload => 0,
39934440 .ptr_comptime_field => @sizeOf(PtrComptimeField),
......@@ -4011,8 +4458,20 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
40114458 const int = ip.limbData(Int, data);
40124459 break :b @sizeOf(Int) + int.limbs_len * 8;
40134460 },
4461
4462 .int_lazy_align, .int_lazy_size => @sizeOf(IntLazy),
4463
4464 .error_set_error, .error_union_error => @sizeOf(Key.Error),
4465 .error_union_payload => @sizeOf(TypeValue),
4466 .enum_literal => 0,
40144467 .enum_tag => @sizeOf(Key.EnumTag),
40154468
4469 .bytes => b: {
4470 const info = ip.extraData(Bytes, data);
4471 const len = @intCast(u32, ip.aggregateTypeLen(info.ty));
4472 break :b @sizeOf(Bytes) + len +
4473 @boolToInt(ip.string_bytes.items[@enumToInt(info.bytes) + len - 1] != 0);
4474 },
40164475 .aggregate => b: {
40174476 const info = ip.extraData(Aggregate, data);
40184477 const fields_len = @intCast(u32, ip.aggregateTypeLen(info.ty));
......@@ -4028,8 +4487,9 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
40284487 .float_c_longdouble_f80 => @sizeOf(Float80),
40294488 .float_c_longdouble_f128 => @sizeOf(Float128),
40304489 .float_comptime_float => @sizeOf(Float128),
4031 .extern_func => @panic("TODO"),
4032 .func => @panic("TODO"),
4490 .variable => @sizeOf(Variable) + @sizeOf(Module.Decl),
4491 .extern_func => @sizeOf(Key.ExternFunc) + @sizeOf(Module.Decl),
4492 .func => @sizeOf(Key.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
40334493 .only_possible_value => 0,
40344494 .union_value => @sizeOf(Key.Union),
40354495 });
......@@ -4071,6 +4531,14 @@ pub fn unionPtrConst(ip: InternPool, index: Module.Union.Index) *const Module.Un
40714531 return ip.allocated_unions.at(@enumToInt(index));
40724532}
40734533
4534pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {
4535 return ip.allocated_funcs.at(@enumToInt(index));
4536}
4537
4538pub fn funcPtrConst(ip: InternPool, index: Module.Fn.Index) *const Module.Fn {
4539 return ip.allocated_funcs.at(@enumToInt(index));
4540}
4541
40744542pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
40754543 return ip.allocated_inferred_error_sets.at(@enumToInt(index));
40764544}
......@@ -4117,6 +4585,25 @@ pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index)
41174585 };
41184586}
41194587
4588pub fn createFunc(
4589 ip: *InternPool,
4590 gpa: Allocator,
4591 initialization: Module.Fn,
4592) Allocator.Error!Module.Fn.Index {
4593 if (ip.funcs_free_list.popOrNull()) |index| return index;
4594 const ptr = try ip.allocated_funcs.addOne(gpa);
4595 ptr.* = initialization;
4596 return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1);
4597}
4598
4599pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void {
4600 ip.funcPtr(index).* = undefined;
4601 ip.funcs_free_list.append(gpa, index) catch {
4602 // In order to keep `destroyFunc` a non-fallible function, we ignore memory
4603 // allocation failures here, instead leaking the Union until garbage collection.
4604 };
4605}
4606
41204607pub fn createInferredErrorSet(
41214608 ip: *InternPool,
41224609 gpa: Allocator,
......@@ -4142,9 +4629,25 @@ pub fn getOrPutString(
41424629 s: []const u8,
41434630) Allocator.Error!NullTerminatedString {
41444631 const string_bytes = &ip.string_bytes;
4145 const str_index = @intCast(u32, string_bytes.items.len);
41464632 try string_bytes.ensureUnusedCapacity(gpa, s.len + 1);
41474633 string_bytes.appendSliceAssumeCapacity(s);
4634 string_bytes.appendAssumeCapacity(0);
4635 return ip.getOrPutTrailingString(gpa, s.len + 1);
4636}
4637
4638/// Uses the last len bytes of ip.string_bytes as the key.
4639pub fn getOrPutTrailingString(
4640 ip: *InternPool,
4641 gpa: Allocator,
4642 len: usize,
4643) Allocator.Error!NullTerminatedString {
4644 const string_bytes = &ip.string_bytes;
4645 const str_index = @intCast(u32, string_bytes.items.len - len);
4646 if (len > 0 and string_bytes.getLast() == 0) {
4647 _ = string_bytes.pop();
4648 } else {
4649 try string_bytes.ensureUnusedCapacity(gpa, 1);
4650 }
41484651 const key: []const u8 = string_bytes.items[str_index..];
41494652 const gop = try ip.string_table.getOrPutContextAdapted(gpa, key, std.hash_map.StringIndexAdapter{
41504653 .bytes = string_bytes,
......@@ -4179,6 +4682,10 @@ pub fn stringToSlice(ip: InternPool, s: NullTerminatedString) [:0]const u8 {
41794682 return string_bytes[start..end :0];
41804683}
41814684
4685pub fn stringToSliceUnwrap(ip: InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 {
4686 return ip.stringToSlice(s.unwrap() orelse return null);
4687}
4688
41824689pub fn typeOf(ip: InternPool, index: Index) Index {
41834690 return ip.indexToKey(index).typeOf();
41844691}
......@@ -4199,7 +4706,7 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
41994706 };
42004707}
42014708
4202pub fn isNoReturn(ip: InternPool, ty: InternPool.Index) bool {
4709pub fn isNoReturn(ip: InternPool, ty: Index) bool {
42034710 return switch (ty) {
42044711 .noreturn_type => true,
42054712 else => switch (ip.indexToKey(ty)) {
src/Module.zig+201-208
......@@ -109,7 +109,7 @@ memoized_calls: MemoizedCallSet = .{},
109109/// Contains the values from `@setAlignStack`. A sparse table is used here
110110/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
111111/// functions are many.
112align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{},
112align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
113113
114114/// We optimize memory usage for a compilation with no compile errors by storing the
115115/// error messages and mapping outside of `Decl`.
......@@ -242,22 +242,23 @@ pub const StringLiteralAdapter = struct {
242242};
243243
244244const MonomorphedFuncsSet = std.HashMapUnmanaged(
245 *Fn,
245 Fn.Index,
246246 void,
247247 MonomorphedFuncsContext,
248248 std.hash_map.default_max_load_percentage,
249249);
250250
251251const MonomorphedFuncsContext = struct {
252 pub fn eql(ctx: @This(), a: *Fn, b: *Fn) bool {
252 mod: *Module,
253
254 pub fn eql(ctx: @This(), a: Fn.Index, b: Fn.Index) bool {
253255 _ = ctx;
254256 return a == b;
255257 }
256258
257259 /// Must match `Sema.GenericCallAdapter.hash`.
258 pub fn hash(ctx: @This(), key: *Fn) u64 {
259 _ = ctx;
260 return key.hash;
260 pub fn hash(ctx: @This(), key: Fn.Index) u64 {
261 return ctx.mod.funcPtr(key).hash;
261262 }
262263};
263264
......@@ -272,7 +273,7 @@ pub const MemoizedCall = struct {
272273 module: *Module,
273274
274275 pub const Key = struct {
275 func: *Fn,
276 func: Fn.Index,
276277 args: []TypedValue,
277278 };
278279
......@@ -652,21 +653,12 @@ pub const Decl = struct {
652653
653654 pub fn clearValues(decl: *Decl, mod: *Module) void {
654655 const gpa = mod.gpa;
655 if (decl.getExternFn()) |extern_fn| {
656 extern_fn.deinit(gpa);
657 gpa.destroy(extern_fn);
658 }
659 if (decl.getFunction()) |func| {
656 if (decl.getFunctionIndex(mod).unwrap()) |func| {
660657 _ = mod.align_stack_fns.remove(func);
661 if (func.comptime_args != null) {
662 _ = mod.monomorphed_funcs.remove(func);
658 if (mod.funcPtr(func).comptime_args != null) {
659 _ = mod.monomorphed_funcs.removeContext(func, .{ .mod = mod });
663660 }
664 func.deinit(gpa);
665 gpa.destroy(func);
666 }
667 if (decl.getVariable()) |variable| {
668 variable.deinit(gpa);
669 gpa.destroy(variable);
661 mod.destroyFunc(func);
670662 }
671663 if (decl.value_arena) |value_arena| {
672664 if (decl.owns_tv) {
......@@ -835,11 +827,11 @@ pub const Decl = struct {
835827
836828 /// If the Decl has a value and it is a struct, return it,
837829 /// otherwise null.
838 pub fn getStruct(decl: *Decl, mod: *Module) ?*Struct {
839 return mod.structPtrUnwrap(getStructIndex(decl, mod));
830 pub fn getStruct(decl: Decl, mod: *Module) ?*Struct {
831 return mod.structPtrUnwrap(decl.getStructIndex(mod));
840832 }
841833
842 pub fn getStructIndex(decl: *Decl, mod: *Module) Struct.OptionalIndex {
834 pub fn getStructIndex(decl: Decl, mod: *Module) Struct.OptionalIndex {
843835 if (!decl.owns_tv) return .none;
844836 if (decl.val.ip_index == .none) return .none;
845837 return mod.intern_pool.indexToStructType(decl.val.ip_index);
......@@ -847,7 +839,7 @@ pub const Decl = struct {
847839
848840 /// If the Decl has a value and it is a union, return it,
849841 /// otherwise null.
850 pub fn getUnion(decl: *Decl, mod: *Module) ?*Union {
842 pub fn getUnion(decl: Decl, mod: *Module) ?*Union {
851843 if (!decl.owns_tv) return null;
852844 if (decl.val.ip_index == .none) return null;
853845 return mod.typeToUnion(decl.val.toType());
......@@ -855,32 +847,30 @@ pub const Decl = struct {
855847
856848 /// If the Decl has a value and it is a function, return it,
857849 /// otherwise null.
858 pub fn getFunction(decl: *const Decl) ?*Fn {
859 if (!decl.owns_tv) return null;
860 const func = (decl.val.castTag(.function) orelse return null).data;
861 return func;
850 pub fn getFunction(decl: Decl, mod: *Module) ?*Fn {
851 return mod.funcPtrUnwrap(decl.getFunctionIndex(mod));
852 }
853
854 pub fn getFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
855 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
862856 }
863857
864858 /// If the Decl has a value and it is an extern function, returns it,
865859 /// otherwise null.
866 pub fn getExternFn(decl: *const Decl) ?*ExternFn {
867 if (!decl.owns_tv) return null;
868 const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
869 return extern_fn;
860 pub fn getExternFunc(decl: Decl, mod: *Module) ?InternPool.Key.ExternFunc {
861 return if (decl.owns_tv) decl.val.getExternFunc(mod) else null;
870862 }
871863
872864 /// If the Decl has a value and it is a variable, returns it,
873865 /// otherwise null.
874 pub fn getVariable(decl: *const Decl) ?*Var {
875 if (!decl.owns_tv) return null;
876 const variable = (decl.val.castTag(.variable) orelse return null).data;
877 return variable;
866 pub fn getVariable(decl: Decl, mod: *Module) ?InternPool.Key.Variable {
867 return if (decl.owns_tv) decl.val.getVariable(mod) else null;
878868 }
879869
880870 /// Gets the namespace that this Decl creates by being a struct, union,
881871 /// enum, or opaque.
882872 /// Only returns it if the Decl is the owner.
883 pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex {
873 pub fn getInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
884874 if (!decl.owns_tv) return .none;
885875 return switch (decl.val.ip_index) {
886876 .empty_struct_type => .none,
......@@ -896,8 +886,8 @@ pub const Decl = struct {
896886 }
897887
898888 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
899 pub fn getInnerNamespace(decl: *Decl, mod: *Module) ?*Namespace {
900 return if (getInnerNamespaceIndex(decl, mod).unwrap()) |i| mod.namespacePtr(i) else null;
889 pub fn getInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
890 return if (decl.getInnerNamespaceIndex(mod).unwrap()) |i| mod.namespacePtr(i) else null;
901891 }
902892
903893 pub fn dump(decl: *Decl) void {
......@@ -927,14 +917,11 @@ pub const Decl = struct {
927917 assert(decl.dependencies.swapRemove(other));
928918 }
929919
930 pub fn isExtern(decl: Decl) bool {
920 pub fn isExtern(decl: Decl, mod: *Module) bool {
931921 assert(decl.has_tv);
932 return switch (decl.val.ip_index) {
933 .none => switch (decl.val.tag()) {
934 .extern_fn => true,
935 .variable => decl.val.castTag(.variable).?.data.init.ip_index == .unreachable_value,
936 else => false,
937 },
922 return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
923 .variable => |variable| variable.is_extern,
924 .extern_func => true,
938925 else => false,
939926 };
940927 }
......@@ -1494,6 +1481,28 @@ pub const Fn = struct {
14941481 is_noinline: bool,
14951482 calls_or_awaits_errorable_fn: bool = false,
14961483
1484 pub const Index = enum(u32) {
1485 _,
1486
1487 pub fn toOptional(i: Index) OptionalIndex {
1488 return @intToEnum(OptionalIndex, @enumToInt(i));
1489 }
1490 };
1491
1492 pub const OptionalIndex = enum(u32) {
1493 none = std.math.maxInt(u32),
1494 _,
1495
1496 pub fn init(oi: ?Index) OptionalIndex {
1497 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1498 }
1499
1500 pub fn unwrap(oi: OptionalIndex) ?Index {
1501 if (oi == .none) return null;
1502 return @intToEnum(Index, @enumToInt(oi));
1503 }
1504 };
1505
14971506 pub const Analysis = enum {
14981507 /// This function has not yet undergone analysis, because we have not
14991508 /// seen a potential runtime call. It may be analyzed in future.
......@@ -1519,7 +1528,7 @@ pub const Fn = struct {
15191528 /// or comptime functions.
15201529 pub const InferredErrorSet = struct {
15211530 /// The function from which this error set originates.
1522 func: *Fn,
1531 func: Fn.Index,
15231532
15241533 /// All currently known errors that this error set contains. This includes
15251534 /// direct additions via `return error.Foo;`, and possibly also errors that
......@@ -1543,8 +1552,8 @@ pub const Fn = struct {
15431552 pub const Index = enum(u32) {
15441553 _,
15451554
1546 pub fn toOptional(i: Index) OptionalIndex {
1547 return @intToEnum(OptionalIndex, @enumToInt(i));
1555 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1556 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(i));
15481557 }
15491558 };
15501559
......@@ -1552,13 +1561,13 @@ pub const Fn = struct {
15521561 none = std.math.maxInt(u32),
15531562 _,
15541563
1555 pub fn init(oi: ?Index) OptionalIndex {
1556 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1564 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1565 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(oi orelse return .none));
15571566 }
15581567
1559 pub fn unwrap(oi: OptionalIndex) ?Index {
1568 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
15601569 if (oi == .none) return null;
1561 return @intToEnum(Index, @enumToInt(oi));
1570 return @intToEnum(InferredErrorSet.Index, @enumToInt(oi));
15621571 }
15631572 };
15641573
......@@ -1587,12 +1596,6 @@ pub const Fn = struct {
15871596 }
15881597 };
15891598
1590 /// TODO: remove this function
1591 pub fn deinit(func: *Fn, gpa: Allocator) void {
1592 _ = func;
1593 _ = gpa;
1594 }
1595
15961599 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
15971600 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
15981601
......@@ -1647,28 +1650,6 @@ pub const Fn = struct {
16471650 }
16481651};
16491652
1650pub const Var = struct {
1651 /// if is_extern == true this is undefined
1652 init: Value,
1653 owner_decl: Decl.Index,
1654
1655 /// Library name if specified.
1656 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
1657 /// Allocated with Module's allocator; outlives the ZIR code.
1658 lib_name: ?[*:0]const u8,
1659
1660 is_extern: bool,
1661 is_mutable: bool,
1662 is_threadlocal: bool,
1663 is_weak_linkage: bool,
1664
1665 pub fn deinit(variable: *Var, gpa: Allocator) void {
1666 if (variable.lib_name) |lib_name| {
1667 gpa.free(mem.sliceTo(lib_name, 0));
1668 }
1669 }
1670};
1671
16721653pub const DeclAdapter = struct {
16731654 mod: *Module,
16741655
......@@ -3472,6 +3453,10 @@ pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
34723453 return mod.intern_pool.structPtr(index);
34733454}
34743455
3456pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {
3457 return mod.intern_pool.funcPtr(index);
3458}
3459
34753460pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
34763461 return mod.intern_pool.inferredErrorSetPtr(index);
34773462}
......@@ -3479,7 +3464,11 @@ pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.I
34793464/// This one accepts an index from the InternPool and asserts that it is not
34803465/// the anonymous empty struct type.
34813466pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
3482 return structPtr(mod, index.unwrap() orelse return null);
3467 return mod.structPtr(index.unwrap() orelse return null);
3468}
3469
3470pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3471 return mod.funcPtr(index.unwrap() orelse return null);
34833472}
34843473
34853474/// Returns true if and only if the Decl is the top level struct associated with a File.
......@@ -3952,7 +3941,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
39523941 };
39533942 }
39543943
3955 if (decl.getFunction()) |func| {
3944 if (decl.getFunction(mod)) |func| {
39563945 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
39573946 try file.deleted_decls.append(gpa, decl_index);
39583947 continue;
......@@ -4139,7 +4128,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
41394128 try mod.deleteDeclExports(decl_index);
41404129
41414130 // Similarly, `@setAlignStack` invocations will be re-discovered.
4142 if (decl.getFunction()) |func| {
4131 if (decl.getFunctionIndex(mod).unwrap()) |func| {
41434132 _ = mod.align_stack_fns.remove(func);
41444133 }
41454134
......@@ -4229,10 +4218,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42294218 }
42304219}
42314220
4232pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4221pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
42334222 const tracy = trace(@src());
42344223 defer tracy.end();
42354224
4225 const func = mod.funcPtr(func_index);
42364226 const decl_index = func.owner_decl;
42374227 const decl = mod.declPtr(decl_index);
42384228
......@@ -4264,7 +4254,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
42644254 defer tmp_arena.deinit();
42654255 const sema_arena = tmp_arena.allocator();
42664256
4267 var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
4257 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
42684258 error.AnalysisFail => {
42694259 if (func.state == .in_progress) {
42704260 // If this decl caused the compile error, the analysis field would
......@@ -4333,7 +4323,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43334323
43344324 if (no_bin_file and !dump_llvm_ir) return;
43354325
4336 comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
4326 comp.bin_file.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) {
43374327 error.OutOfMemory => return error.OutOfMemory,
43384328 error.AnalysisFail => {
43394329 decl.analysis = .codegen_failure;
......@@ -4363,7 +4353,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43634353/// analyzed, and for ensuring it can exist at runtime (see
43644354/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
43654355/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4366pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
4356pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4357 const func = mod.funcPtr(func_index);
43674358 const decl_index = func.owner_decl;
43684359 const decl = mod.declPtr(decl_index);
43694360
......@@ -4401,7 +4392,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
44014392
44024393 // Decl itself is safely analyzed, and body analysis is not yet queued
44034394
4404 try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
4395 try mod.comp.work_queue.writeItem(.{ .codegen_func = func_index });
44054396 if (mod.emit_h != null) {
44064397 // TODO: we ideally only want to do this if the function's type changed
44074398 // since the last update
......@@ -4532,8 +4523,10 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
45324523 .owner_decl = new_decl,
45334524 .owner_decl_index = new_decl_index,
45344525 .func = null,
4526 .func_index = .none,
45354527 .fn_ret_ty = Type.void,
45364528 .owner_func = null,
4529 .owner_func_index = .none,
45374530 };
45384531 defer sema.deinit();
45394532
......@@ -4628,8 +4621,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46284621 .owner_decl = decl,
46294622 .owner_decl_index = decl_index,
46304623 .func = null,
4624 .func_index = .none,
46314625 .fn_ret_ty = Type.void,
46324626 .owner_func = null,
4627 .owner_func_index = .none,
46334628 };
46344629 defer sema.deinit();
46354630
......@@ -4707,8 +4702,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47074702 return true;
47084703 }
47094704
4710 if (decl_tv.val.castTag(.function)) |fn_payload| {
4711 const func = fn_payload.data;
4705 if (mod.intern_pool.indexToFunc(decl_tv.val.ip_index).unwrap()) |func_index| {
4706 const func = mod.funcPtr(func_index);
47124707 const owns_tv = func.owner_decl == decl_index;
47134708 if (owns_tv) {
47144709 var prev_type_has_bits = false;
......@@ -4718,7 +4713,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47184713 if (decl.has_tv) {
47194714 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
47204715 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4721 if (decl.getFunction()) |prev_func| {
4716 if (decl.getFunction(mod)) |prev_func| {
47224717 prev_is_inline = prev_func.state == .inline_only;
47234718 }
47244719 }
......@@ -4757,38 +4752,25 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47574752 switch (decl_tv.val.ip_index) {
47584753 .generic_poison => unreachable,
47594754 .unreachable_value => unreachable,
4760
4761 .none => switch (decl_tv.val.tag()) {
4762 .variable => {
4763 const variable = decl_tv.val.castTag(.variable).?.data;
4764 if (variable.owner_decl == decl_index) {
4765 decl.owns_tv = true;
4766 queue_linker_work = true;
4767
4768 const copied_init = try variable.init.copy(decl_arena_allocator);
4769 variable.init = copied_init;
4770 }
4755 else => switch (mod.intern_pool.indexToKey(decl_tv.val.ip_index)) {
4756 .variable => |variable| if (variable.decl == decl_index) {
4757 decl.owns_tv = true;
4758 queue_linker_work = true;
47714759 },
4772 .extern_fn => {
4773 const extern_fn = decl_tv.val.castTag(.extern_fn).?.data;
4774 if (extern_fn.owner_decl == decl_index) {
4775 decl.owns_tv = true;
4776 queue_linker_work = true;
4777 is_extern = true;
4778 }
4760
4761 .extern_func => |extern_fn| if (extern_fn.decl == decl_index) {
4762 decl.owns_tv = true;
4763 queue_linker_work = true;
4764 is_extern = true;
47794765 },
47804766
4781 .function => {},
4767 .func => {},
47824768
47834769 else => {
47844770 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
47854771 queue_linker_work = true;
47864772 },
47874773 },
4788 else => {
4789 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
4790 queue_linker_work = true;
4791 },
47924774 }
47934775
47944776 decl.ty = decl_tv.ty;
......@@ -4810,12 +4792,9 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48104792 break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
48114793 };
48124794 decl.@"addrspace" = blk: {
4813 const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.ip_index) {
4814 .none => switch (decl_tv.val.tag()) {
4815 .function, .extern_fn => .function,
4816 .variable => .variable,
4817 else => .constant,
4818 },
4795 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.ip_index)) {
4796 .variable => .variable,
4797 .extern_func, .func => .function,
48194798 else => .constant,
48204799 };
48214800
......@@ -5388,7 +5367,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53885367 decl.has_align = has_align;
53895368 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
53905369 decl.zir_decl_index = @intCast(u32, decl_sub_index);
5391 if (decl.getFunction()) |_| {
5370 if (decl.getFunctionIndex(mod) != .none) {
53925371 switch (comp.bin_file.tag) {
53935372 .coff, .elf, .macho, .plan9 => {
53945373 // TODO Look into detecting when this would be unnecessary by storing enough state
......@@ -5572,11 +5551,12 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
55725551 export_owners.deinit(mod.gpa);
55735552}
55745553
5575pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5554pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air {
55765555 const tracy = trace(@src());
55775556 defer tracy.end();
55785557
55795558 const gpa = mod.gpa;
5559 const func = mod.funcPtr(func_index);
55805560 const decl_index = func.owner_decl;
55815561 const decl = mod.declPtr(decl_index);
55825562
......@@ -5597,8 +5577,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
55975577 .owner_decl = decl,
55985578 .owner_decl_index = decl_index,
55995579 .func = func,
5580 .func_index = func_index.toOptional(),
56005581 .fn_ret_ty = fn_ty_info.return_type.toType(),
56015582 .owner_func = func,
5583 .owner_func_index = func_index.toOptional(),
56025584 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
56035585 };
56045586 defer sema.deinit();
......@@ -5807,8 +5789,7 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
58075789 for (kv.value) |err| err.deinit(mod.gpa);
58085790 }
58095791 if (decl.has_tv and decl.owns_tv) {
5810 if (decl.val.castTag(.function)) |payload| {
5811 const func = payload.data;
5792 if (decl.getFunctionIndex(mod).unwrap()) |func| {
58125793 _ = mod.align_stack_fns.remove(func);
58135794 }
58145795 }
......@@ -5852,6 +5833,14 @@ pub fn destroyUnion(mod: *Module, index: Union.Index) void {
58525833 return mod.intern_pool.destroyUnion(mod.gpa, index);
58535834}
58545835
5836pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index {
5837 return mod.intern_pool.createFunc(mod.gpa, initialization);
5838}
5839
5840pub fn destroyFunc(mod: *Module, index: Fn.Index) void {
5841 return mod.intern_pool.destroyFunc(mod.gpa, index);
5842}
5843
58555844pub fn allocateNewDecl(
58565845 mod: *Module,
58575846 namespace: Namespace.Index,
......@@ -6499,7 +6488,11 @@ pub fn populateTestFunctions(
64996488 try mod.ensureDeclAnalyzed(decl_index);
65006489 }
65016490 const decl = mod.declPtr(decl_index);
6502 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);
6491 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);
6492 const null_usize = try mod.intern(.{ .opt = .{
6493 .ty = try mod.intern(.{ .opt_type = .usize_type }),
6494 .val = .none,
6495 } });
65036496
65046497 const array_decl_index = d: {
65056498 // Add mod.test_functions to an array decl then make the test_functions
......@@ -6512,7 +6505,7 @@ pub fn populateTestFunctions(
65126505 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
65136506 .ty = try mod.arrayType(.{
65146507 .len = test_fn_vals.len,
6515 .child = tmp_test_fn_ty.ip_index,
6508 .child = test_fn_ty.ip_index,
65166509 .sentinel = .none,
65176510 }),
65186511 .val = try Value.Tag.aggregate.create(arena, test_fn_vals),
......@@ -6530,7 +6523,7 @@ pub fn populateTestFunctions(
65306523 errdefer name_decl_arena.deinit();
65316524 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);
65326525 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{
6533 .ty = try Type.array(name_decl_arena.allocator(), bytes.len, null, Type.u8, mod),
6526 .ty = try mod.arrayType(.{ .len = bytes.len, .child = .u8_type }),
65346527 .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),
65356528 });
65366529 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
......@@ -6540,16 +6533,24 @@ pub fn populateTestFunctions(
65406533 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);
65416534 try mod.linkerUpdateDecl(test_name_decl_index);
65426535
6543 const field_vals = try arena.create([3]Value);
6544 field_vals.* = .{
6545 try Value.Tag.slice.create(arena, .{
6546 .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index),
6547 .len = try mod.intValue(Type.usize, test_name_slice.len),
6548 }), // name
6549 try Value.Tag.decl_ref.create(arena, test_decl_index), // func
6550 Value.null, // async_frame_size
6536 const test_fn_fields = .{
6537 // name
6538 try mod.intern(.{ .ptr = .{
6539 .ty = .slice_const_u8_type,
6540 .addr = .{ .decl = test_name_decl_index },
6541 } }),
6542 // func
6543 try mod.intern(.{ .ptr = .{
6544 .ty = test_decl.ty.ip_index,
6545 .addr = .{ .decl = test_decl_index },
6546 } }),
6547 // async_frame_size
6548 null_usize,
65516549 };
6552 test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals);
6550 test_fn_vals[i] = (try mod.intern(.{ .aggregate = .{
6551 .ty = test_fn_ty.ip_index,
6552 .storage = .{ .elems = &test_fn_fields },
6553 } })).toValue();
65536554 }
65546555
65556556 try array_decl.finalizeNewArena(&new_decl_arena);
......@@ -6558,36 +6559,25 @@ pub fn populateTestFunctions(
65586559 try mod.linkerUpdateDecl(array_decl_index);
65596560
65606561 {
6561 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
6562 errdefer new_decl_arena.deinit();
6563 const arena = new_decl_arena.allocator();
6564
6565 {
6566 // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.
6567 const new_ty = try Type.ptr(arena, mod, .{
6568 .size = .Slice,
6569 .pointee_type = tmp_test_fn_ty,
6570 .mutable = false,
6571 .@"addrspace" = .generic,
6572 });
6573 const new_var = try gpa.create(Var);
6574 errdefer gpa.destroy(new_var);
6575 new_var.* = decl.val.castTag(.variable).?.data.*;
6576 new_var.init = try Value.Tag.slice.create(arena, .{
6577 .ptr = try Value.Tag.decl_ref.create(arena, array_decl_index),
6578 .len = try mod.intValue(Type.usize, mod.test_functions.count()),
6579 });
6580 const new_val = try Value.Tag.variable.create(arena, new_var);
6581
6582 // Since we are replacing the Decl's value we must perform cleanup on the
6583 // previous value.
6584 decl.clearValues(mod);
6585 decl.ty = new_ty;
6586 decl.val = new_val;
6587 decl.has_tv = true;
6588 }
6562 const new_ty = try mod.ptrType(.{
6563 .elem_type = test_fn_ty.ip_index,
6564 .is_const = true,
6565 .size = .Slice,
6566 });
6567 const new_val = decl.val;
6568 const new_init = try mod.intern(.{ .ptr = .{
6569 .ty = new_ty.ip_index,
6570 .addr = .{ .decl = array_decl_index },
6571 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).ip_index,
6572 } });
6573 mod.intern_pool.mutateVarInit(decl.val.ip_index, new_init);
65896574
6590 try decl.finalizeNewArena(&new_decl_arena);
6575 // Since we are replacing the Decl's value we must perform cleanup on the
6576 // previous value.
6577 decl.clearValues(mod);
6578 decl.ty = new_ty;
6579 decl.val = new_val;
6580 decl.has_tv = true;
65916581 }
65926582 try mod.linkerUpdateDecl(decl_index);
65936583}
......@@ -6660,50 +6650,47 @@ fn reportRetryableFileError(
66606650}
66616651
66626652pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {
6663 if (val.ip_index != .none) return;
6664 switch (val.tag()) {
6665 .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index),
6666 .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl),
6667 .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl),
6668 .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl),
6669 .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data),
6670
6671 .repeated,
6672 .eu_payload,
6673 .opt_payload,
6674 .empty_array_sentinel,
6675 => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.SubValue).?.data),
6676
6677 .eu_payload_ptr,
6678 .opt_payload_ptr,
6679 => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.PayloadPtr).?.data.container_ptr),
6680
6681 .slice => {
6682 const slice = val.cast(Value.Payload.Slice).?.data;
6683 mod.markReferencedDeclsAlive(slice.ptr);
6684 mod.markReferencedDeclsAlive(slice.len);
6685 },
6686
6687 .elem_ptr => {
6688 const elem_ptr = val.cast(Value.Payload.ElemPtr).?.data;
6689 return mod.markReferencedDeclsAlive(elem_ptr.array_ptr);
6690 },
6691 .field_ptr => {
6692 const field_ptr = val.cast(Value.Payload.FieldPtr).?.data;
6693 return mod.markReferencedDeclsAlive(field_ptr.container_ptr);
6694 },
6695 .aggregate => {
6696 for (val.castTag(.aggregate).?.data) |field_val| {
6697 mod.markReferencedDeclsAlive(field_val);
6698 }
6653 switch (val.ip_index) {
6654 .none => switch (val.tag()) {
6655 .aggregate => {
6656 for (val.castTag(.aggregate).?.data) |field_val| {
6657 mod.markReferencedDeclsAlive(field_val);
6658 }
6659 },
6660 .@"union" => {
6661 const data = val.castTag(.@"union").?.data;
6662 mod.markReferencedDeclsAlive(data.tag);
6663 mod.markReferencedDeclsAlive(data.val);
6664 },
6665 else => {},
66996666 },
6700 .@"union" => {
6701 const data = val.cast(Value.Payload.Union).?.data;
6702 mod.markReferencedDeclsAlive(data.tag);
6703 mod.markReferencedDeclsAlive(data.val);
6667 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
6668 .variable => |variable| mod.markDeclIndexAlive(variable.decl),
6669 .extern_func => |extern_func| mod.markDeclIndexAlive(extern_func.decl),
6670 .func => |func| mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
6671 .error_union => |error_union| switch (error_union.val) {
6672 .err_name => {},
6673 .payload => |payload| mod.markReferencedDeclsAlive(payload.toValue()),
6674 },
6675 .ptr => |ptr| {
6676 switch (ptr.addr) {
6677 .decl => |decl| mod.markDeclIndexAlive(decl),
6678 .mut_decl => |mut_decl| mod.markDeclIndexAlive(mut_decl.decl),
6679 .int, .comptime_field => {},
6680 .eu_payload, .opt_payload => |parent| mod.markReferencedDeclsAlive(parent.toValue()),
6681 .elem, .field => |base_index| mod.markReferencedDeclsAlive(base_index.base.toValue()),
6682 }
6683 if (ptr.len != .none) mod.markReferencedDeclsAlive(ptr.len.toValue());
6684 },
6685 .opt => |opt| if (opt.val != .none) mod.markReferencedDeclsAlive(opt.val.toValue()),
6686 .aggregate => |aggregate| for (aggregate.storage.values()) |elem|
6687 mod.markReferencedDeclsAlive(elem.toValue()),
6688 .un => |un| {
6689 mod.markReferencedDeclsAlive(un.tag.toValue());
6690 mod.markReferencedDeclsAlive(un.val.toValue());
6691 },
6692 else => {},
67046693 },
6705
6706 else => {},
67076694 }
67086695}
67096696
......@@ -7075,6 +7062,12 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
70757062
70767063 return @intCast(u16, big.bitCountTwosComp());
70777064 },
7065 .lazy_align => |lazy_ty| {
7066 return Type.smallestUnsignedBits(lazy_ty.toType().abiAlignment(mod)) + @boolToInt(sign);
7067 },
7068 .lazy_size => |lazy_ty| {
7069 return Type.smallestUnsignedBits(lazy_ty.toType().abiSize(mod)) + @boolToInt(sign);
7070 },
70787071 }
70797072}
70807073
src/Sema.zig+1338-1544
......@@ -28,10 +28,12 @@ owner_decl_index: Decl.Index,
2828/// For an inline or comptime function call, this will be the root parent function
2929/// which contains the callsite. Corresponds to `owner_decl`.
3030owner_func: ?*Module.Fn,
31owner_func_index: Module.Fn.OptionalIndex,
3132/// The function this ZIR code is the body of, according to the source code.
3233/// This starts out the same as `owner_func` and then diverges in the case of
3334/// an inline or comptime function call.
3435func: ?*Module.Fn,
36func_index: Module.Fn.OptionalIndex,
3537/// Used to restore the error return trace when returning a non-error from a function.
3638error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3739/// 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,
6567/// to use this instead of allocating a fresh one. This avoids an unnecessary
6668/// extra hash table lookup in the `monomorphed_funcs` set.
6769/// Sema will set this to null when it takes ownership.
68preallocated_new_func: ?*Module.Fn = null,
70preallocated_new_func: Module.Fn.OptionalIndex = .none,
6971/// The key is types that must be fully resolved prior to machine code
7072/// generation pass. Types are added to this set when resolving them
7173/// 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) = .{}
9294const std = @import("std");
9395const math = std.math;
9496const mem = std.mem;
95const Allocator = std.mem.Allocator;
97const Allocator = mem.Allocator;
9698const assert = std.debug.assert;
9799const log = std.log.scoped(.sema);
98100
......@@ -1777,7 +1779,7 @@ pub fn resolveConstString(
17771779 reason: []const u8,
17781780) ![]u8 {
17791781 const air_inst = try sema.resolveInst(zir_ref);
1780 const wanted_type = Type.const_slice_u8;
1782 const wanted_type = Type.slice_const_u8;
17811783 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
17821784 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
17831785 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);
......@@ -1866,11 +1868,10 @@ fn resolveConstMaybeUndefVal(
18661868 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
18671869 switch (val.ip_index) {
18681870 .generic_poison => return error.GenericPoison,
1869 .none => switch (val.tag()) {
1871 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
18701872 .variable => return sema.failWithNeededComptime(block, src, reason),
18711873 else => return val,
18721874 },
1873 else => return val,
18741875 }
18751876 }
18761877 return sema.failWithNeededComptime(block, src, reason);
......@@ -1889,11 +1890,11 @@ fn resolveConstValue(
18891890 switch (val.ip_index) {
18901891 .generic_poison => return error.GenericPoison,
18911892 .undef => return sema.failWithUseOfUndef(block, src),
1892 .none => switch (val.tag()) {
1893 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
1894 .undef => return sema.failWithUseOfUndef(block, src),
18931895 .variable => return sema.failWithNeededComptime(block, src, reason),
18941896 else => return val,
18951897 },
1896 else => return val,
18971898 }
18981899 }
18991900 return sema.failWithNeededComptime(block, src, reason);
......@@ -1928,11 +1929,11 @@ fn resolveMaybeUndefVal(
19281929 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
19291930 switch (val.ip_index) {
19301931 .generic_poison => return error.GenericPoison,
1931 .none => switch (val.tag()) {
1932 .none => return val,
1933 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
19321934 .variable => return null,
19331935 else => return val,
19341936 },
1935 else => return val,
19361937 }
19371938}
19381939
......@@ -1948,21 +1949,20 @@ fn resolveMaybeUndefValIntable(
19481949 var check = val;
19491950 while (true) switch (check.ip_index) {
19501951 .generic_poison => return error.GenericPoison,
1951 .none => switch (check.tag()) {
1952 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null,
1953 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
1954 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
1955 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
1956 else => {
1957 try sema.resolveLazyValue(val);
1958 return val;
1952 .none => break,
1953 else => switch (sema.mod.intern_pool.indexToKey(check.ip_index)) {
1954 .variable => return null,
1955 .ptr => |ptr| switch (ptr.addr) {
1956 .decl, .mut_decl, .comptime_field => return null,
1957 .int => break,
1958 .eu_payload, .opt_payload => |base| check = base.toValue(),
1959 .elem, .field => |base_index| check = base_index.base.toValue(),
19591960 },
1960 },
1961 else => {
1962 try sema.resolveLazyValue(val);
1963 return val;
1961 else => break,
19641962 },
19651963 };
1964 try sema.resolveLazyValue(val);
1965 return val;
19661966}
19671967
19681968/// Returns all Value tags including `variable` and `undef`.
......@@ -1994,7 +1994,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
19941994 if (air_tags[i] == .constant) {
19951995 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
19961996 const val = sema.air_values.items[ty_pl.payload];
1997 if (val.tagIsVariable()) return val;
1997 if (val.getVariable(sema.mod) != null) return val;
19981998 }
19991999 return opv;
20002000 }
......@@ -2003,7 +2003,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
20032003 .constant => {
20042004 const ty_pl = air_datas[i].ty_pl;
20052005 const val = sema.air_values.items[ty_pl.payload];
2006 if (val.isRuntimeValue()) make_runtime.* = true;
2006 if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;
20072007 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
20082008 return val;
20092009 },
......@@ -2489,13 +2489,13 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
24892489 .@"addrspace" = addr_space,
24902490 });
24912491 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
2492 return sema.addConstant(
2493 ptr_ty,
2494 try Value.Tag.decl_ref_mut.create(sema.arena, .{
2495 .decl_index = iac.data.decl_index,
2492 return sema.addConstant(ptr_ty, (try sema.mod.intern(.{ .ptr = .{
2493 .ty = ptr_ty.ip_index,
2494 .addr = .{ .mut_decl = .{
2495 .decl = iac.data.decl_index,
24962496 .runtime_index = block.runtime_index,
2497 }),
2498 );
2497 } },
2498 } })).toValue());
24992499 },
25002500 else => {},
25012501 }
......@@ -2949,12 +2949,18 @@ fn zirEnumDecl(
29492949 }
29502950
29512951 const prev_owner_func = sema.owner_func;
2952 const prev_owner_func_index = sema.owner_func_index;
29522953 sema.owner_func = null;
2954 sema.owner_func_index = .none;
29532955 defer sema.owner_func = prev_owner_func;
2956 defer sema.owner_func_index = prev_owner_func_index;
29542957
29552958 const prev_func = sema.func;
2959 const prev_func_index = sema.func_index;
29562960 sema.func = null;
2961 sema.func_index = .none;
29572962 defer sema.func = prev_func;
2963 defer sema.func_index = prev_func_index;
29582964
29592965 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
29602966 defer wip_captures.deinit();
......@@ -3735,14 +3741,13 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37353741 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
37363742
37373743 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3738 if (var_is_mut) {
3739 sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{
3740 .decl_index = decl_index,
3744 sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
3745 .ty = final_ptr_ty.ip_index,
3746 .addr = if (var_is_mut) .{ .mut_decl = .{
3747 .decl = decl_index,
37413748 .runtime_index = block.runtime_index,
3742 });
3743 } else {
3744 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index);
3745 }
3749 } } else .{ .decl = decl_index },
3750 } })).toValue();
37463751 },
37473752 .inferred_alloc => {
37483753 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
......@@ -3836,7 +3841,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38363841 // block so that codegen does not see it.
38373842 block.instructions.shrinkRetainingCapacity(search_index);
38383843 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3839 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
3844 sema.air_values.items[value_index] = (try sema.mod.intern(.{ .ptr = .{
3845 .ty = final_elem_ty.ip_index,
3846 .addr = .{ .decl = new_decl_index },
3847 } })).toValue();
38403848 // if bitcast ty ref needs to be made const, make_ptr_const
38413849 // ZIR handles it later, so we can just use the ty ref here.
38423850 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
......@@ -4332,12 +4340,16 @@ fn validateUnionInit(
43324340 // instead a single `store` to the result ptr with a comptime union value.
43334341 block.instructions.shrinkRetainingCapacity(first_block_index);
43344342
4335 var union_val = try Value.Tag.@"union".create(sema.arena, .{
4336 .tag = tag_val,
4337 .val = val,
4338 });
4339 if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);
4340 const union_init = try sema.addConstant(union_ty, union_val);
4343 var union_val = try mod.intern(.{ .un = .{
4344 .ty = union_ty.ip_index,
4345 .tag = tag_val.ip_index,
4346 .val = val.ip_index,
4347 } });
4348 if (make_runtime) union_val = try mod.intern(.{ .runtime_value = .{
4349 .ty = union_ty.ip_index,
4350 .val = union_val,
4351 } });
4352 const union_init = try sema.addConstant(union_ty, union_val.toValue());
43414353 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
43424354 return;
43434355 } else if (try sema.typeRequiresComptime(union_ty)) {
......@@ -4464,14 +4476,15 @@ fn validateStructInit(
44644476
44654477 // We collect the comptime field values in case the struct initialization
44664478 // ends up being comptime-known.
4467 const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount(mod));
4479 const field_values = try sema.gpa.alloc(InternPool.Index, struct_ty.structFieldCount(mod));
4480 defer sema.gpa.free(field_values);
44684481
44694482 field: for (found_fields, 0..) |field_ptr, i| {
44704483 if (field_ptr != 0) {
44714484 // Determine whether the value stored to this pointer is comptime-known.
44724485 const field_ty = struct_ty.structFieldType(i, mod);
44734486 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
4474 field_values[i] = opv;
4487 field_values[i] = opv.ip_index;
44754488 continue;
44764489 }
44774490
......@@ -4536,7 +4549,7 @@ fn validateStructInit(
45364549 first_block_index = @min(first_block_index, block_index);
45374550 }
45384551 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4539 field_values[i] = val;
4552 field_values[i] = val.ip_index;
45404553 } else if (require_comptime) {
45414554 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
45424555 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
......@@ -4570,7 +4583,7 @@ fn validateStructInit(
45704583 }
45714584 continue;
45724585 }
4573 field_values[i] = default_val;
4586 field_values[i] = default_val.ip_index;
45744587 }
45754588
45764589 if (root_msg) |msg| {
......@@ -4593,9 +4606,15 @@ fn validateStructInit(
45934606 // instead a single `store` to the struct_ptr with a comptime struct value.
45944607
45954608 block.instructions.shrinkRetainingCapacity(first_block_index);
4596 var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);
4597 if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);
4598 const struct_init = try sema.addConstant(struct_ty, struct_val);
4609 var struct_val = try mod.intern(.{ .aggregate = .{
4610 .ty = struct_ty.ip_index,
4611 .storage = .{ .elems = field_values },
4612 } });
4613 if (make_runtime) struct_val = try mod.intern(.{ .runtime_value = .{
4614 .ty = struct_ty.ip_index,
4615 .val = struct_val,
4616 } });
4617 const struct_init = try sema.addConstant(struct_ty, struct_val.toValue());
45994618 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
46004619 return;
46014620 }
......@@ -4611,7 +4630,7 @@ fn validateStructInit(
46114630 else
46124631 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
46134632 const field_ty = sema.typeOf(default_field_ptr).childType(mod);
4614 const init = try sema.addConstant(field_ty, field_values[i]);
4633 const init = try sema.addConstant(field_ty, field_values[i].toValue());
46154634 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
46164635 }
46174636}
......@@ -4691,7 +4710,8 @@ fn zirValidateArrayInit(
46914710 // Collect the comptime element values in case the array literal ends up
46924711 // being comptime-known.
46934712 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel(mod));
4694 const element_vals = try sema.arena.alloc(Value, array_len_s);
4713 const element_vals = try sema.gpa.alloc(InternPool.Index, array_len_s);
4714 defer sema.gpa.free(element_vals);
46954715 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);
46964716 const air_tags = sema.air_instructions.items(.tag);
46974717 const air_datas = sema.air_instructions.items(.data);
......@@ -4701,13 +4721,13 @@ fn zirValidateArrayInit(
47014721
47024722 if (array_ty.isTuple(mod)) {
47034723 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
4704 element_vals[i] = opv;
4724 element_vals[i] = opv.ip_index;
47054725 continue;
47064726 }
47074727 } else {
47084728 // Array has one possible value, so value is always comptime-known
47094729 if (opt_opv) |opv| {
4710 element_vals[i] = opv;
4730 element_vals[i] = opv.ip_index;
47114731 continue;
47124732 }
47134733 }
......@@ -4768,7 +4788,7 @@ fn zirValidateArrayInit(
47684788 first_block_index = @min(first_block_index, block_index);
47694789 }
47704790 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4771 element_vals[i] = val;
4791 element_vals[i] = val.ip_index;
47724792 } else {
47734793 array_is_comptime = false;
47744794 }
......@@ -4780,9 +4800,12 @@ fn zirValidateArrayInit(
47804800
47814801 if (array_is_comptime) {
47824802 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {
4783 if (ptr_val.tag() == .comptime_field_ptr) {
4784 // This store was validated by the individual elem ptrs.
4785 return;
4803 switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
4804 .ptr => |ptr| switch (ptr.addr) {
4805 .comptime_field => return, // This store was validated by the individual elem ptrs.
4806 else => {},
4807 },
4808 else => {},
47864809 }
47874810 }
47884811
......@@ -4790,14 +4813,20 @@ fn zirValidateArrayInit(
47904813 // instead a single `store` to the array_ptr with a comptime struct value.
47914814 // Also to populate the sentinel value, if any.
47924815 if (array_ty.sentinel(mod)) |sentinel_val| {
4793 element_vals[instrs.len] = sentinel_val;
4816 element_vals[instrs.len] = sentinel_val.ip_index;
47944817 }
47954818
47964819 block.instructions.shrinkRetainingCapacity(first_block_index);
47974820
4798 var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);
4799 if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);
4800 const array_init = try sema.addConstant(array_ty, array_val);
4821 var array_val = try mod.intern(.{ .aggregate = .{
4822 .ty = array_ty.ip_index,
4823 .storage = .{ .elems = element_vals },
4824 } });
4825 if (make_runtime) array_val = try mod.intern(.{ .runtime_value = .{
4826 .ty = array_ty.ip_index,
4827 .val = array_val,
4828 } });
4829 const array_init = try sema.addConstant(array_ty, array_val.toValue());
48014830 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
48024831 }
48034832}
......@@ -5029,7 +5058,7 @@ fn storeToInferredAllocComptime(
50295058 // There will be only one store_to_inferred_ptr because we are running at comptime.
50305059 // The alloc will turn into a Decl.
50315060 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |operand_val| store: {
5032 if (operand_val.tagIsVariable()) break :store;
5061 if (operand_val.getVariable(sema.mod) != null) break :store;
50335062 var anon_decl = try block.startAnonDecl();
50345063 defer anon_decl.deinit();
50355064 iac.data.decl_index = try anon_decl.finish(
......@@ -5717,8 +5746,8 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
57175746 {
57185747 try mod.ensureDeclAnalyzed(decl_index);
57195748 const exported_decl = mod.declPtr(decl_index);
5720 if (exported_decl.val.castTag(.function)) |some| {
5721 return sema.analyzeExport(block, src, options, some.data.owner_decl);
5749 if (exported_decl.getFunction(mod)) |function| {
5750 return sema.analyzeExport(block, src, options, function.owner_decl);
57225751 }
57235752 }
57245753 try sema.analyzeExport(block, src, options, decl_index);
......@@ -5741,17 +5770,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
57415770 },
57425771 else => |e| return e,
57435772 };
5744 const decl_index = switch (operand.val.tag()) {
5745 .function => operand.val.castTag(.function).?.data.owner_decl,
5746 else => blk: {
5747 var anon_decl = try block.startAnonDecl();
5748 defer anon_decl.deinit();
5749 break :blk try anon_decl.finish(
5750 operand.ty,
5751 try operand.val.copy(anon_decl.arena()),
5752 0,
5753 );
5754 },
5773 const decl_index = if (operand.val.getFunction(sema.mod)) |function| function.owner_decl else blk: {
5774 var anon_decl = try block.startAnonDecl();
5775 defer anon_decl.deinit();
5776 break :blk try anon_decl.finish(
5777 operand.ty,
5778 try operand.val.copy(anon_decl.arena()),
5779 0,
5780 );
57555781 };
57565782 try sema.analyzeExport(block, src, options, decl_index);
57575783}
......@@ -5788,7 +5814,7 @@ pub fn analyzeExport(
57885814 }
57895815
57905816 // TODO: some backends might support re-exporting extern decls
5791 if (exported_decl.isExtern()) {
5817 if (exported_decl.isExtern(mod)) {
57925818 return sema.fail(block, src, "export target cannot be extern", .{});
57935819 }
57945820
......@@ -5796,7 +5822,7 @@ pub fn analyzeExport(
57965822 mod.markDeclAlive(exported_decl);
57975823 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
57985824
5799 const gpa = mod.gpa;
5825 const gpa = sema.gpa;
58005826
58015827 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
58025828 try mod.export_owners.ensureUnusedCapacity(gpa, 1);
......@@ -5852,8 +5878,9 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58525878 alignment,
58535879 });
58545880 }
5855 const func = sema.func orelse
5881 const func_index = sema.func_index.unwrap() orelse
58565882 return sema.fail(block, src, "@setAlignStack outside function body", .{});
5883 const func = mod.funcPtr(func_index);
58575884
58585885 const fn_owner_decl = mod.declPtr(func.owner_decl);
58595886 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
......@@ -5864,7 +5891,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58645891 },
58655892 }
58665893
5867 const gop = try mod.align_stack_fns.getOrPut(mod.gpa, func);
5894 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);
58685895 if (gop.found_existing) {
58695896 const msg = msg: {
58705897 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 {
61916218 const mod = sema.mod;
61926219 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
61936220 if (func_val.isUndef(mod)) return null;
6194 const owner_decl_index = switch (func_val.tag()) {
6195 .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,
6196 .function => func_val.castTag(.function).?.data.owner_decl,
6197 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
6221 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
6222 .extern_func => |extern_func| extern_func.decl,
6223 .func => |func| mod.funcPtr(func.index).owner_decl,
6224 .ptr => |ptr| switch (ptr.addr) {
6225 .decl => |decl| decl,
6226 else => return null,
6227 },
61986228 else => return null,
61996229 };
62006230 return mod.declPtr(owner_decl_index);
......@@ -6576,20 +6606,22 @@ const GenericCallAdapter = struct {
65766606 is_anytype: bool,
65776607 };
65786608
6579 pub fn eql(ctx: @This(), adapted_key: void, other_key: *Module.Fn) bool {
6609 pub fn eql(ctx: @This(), adapted_key: void, other_key: Module.Fn.Index) bool {
65806610 _ = adapted_key;
6611 const other_func = ctx.module.funcPtr(other_key);
6612
65816613 // Checking for equality may happen on an item that has been inserted
65826614 // into the map but is not yet fully initialized. In such case, the
65836615 // two initialized fields are `hash` and `generic_owner_decl`.
6584 if (ctx.generic_fn.owner_decl != other_key.generic_owner_decl.unwrap().?) return false;
6616 if (ctx.generic_fn.owner_decl != other_func.generic_owner_decl.unwrap().?) return false;
65856617
6586 const other_comptime_args = other_key.comptime_args.?;
6618 const other_comptime_args = other_func.comptime_args.?;
65876619 for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {
65886620 const this_arg = ctx.args[i];
65896621 const this_is_comptime = !this_arg.val.isGenericPoison();
65906622 const other_is_comptime = !other_arg.val.isGenericPoison();
65916623 const this_is_anytype = this_arg.is_anytype;
6592 const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i));
6624 const other_is_anytype = other_func.isAnytypeParam(ctx.module, @intCast(u32, i));
65936625
65946626 if (other_is_anytype != this_is_anytype) return false;
65956627 if (other_is_comptime != this_is_comptime) return false;
......@@ -6663,7 +6695,7 @@ fn analyzeCall(
66636695 );
66646696 errdefer msg.destroy(sema.gpa);
66656697
6666 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
6698 if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
66676699 break :msg msg;
66686700 };
66696701 return sema.failWithOwnedErrorMsg(msg);
......@@ -6760,18 +6792,21 @@ fn analyzeCall(
67606792 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
67616793 return err;
67626794 };
6763 const module_fn = switch (func_val.tag()) {
6764 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
6765 .function => func_val.castTag(.function).?.data,
6766 .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{
6795 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
6796 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
67676797 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
67686798 }),
6769 else => {
6770 assert(callee_ty.isPtrAtRuntime(mod));
6771 return sema.fail(block, call_src, "{s} call of function pointer", .{
6772 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6773 });
6799 .func => |function| function.index,
6800 .ptr => |ptr| switch (ptr.addr) {
6801 .decl => |decl| mod.declPtr(decl).getFunctionIndex(mod).unwrap().?,
6802 else => {
6803 assert(callee_ty.isPtrAtRuntime(mod));
6804 return sema.fail(block, call_src, "{s} call of function pointer", .{
6805 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6806 });
6807 },
67746808 },
6809 else => unreachable,
67756810 };
67766811 if (func_ty_info.is_var_args) {
67776812 return sema.fail(block, call_src, "{s} call of variadic function", .{
......@@ -6804,6 +6839,7 @@ fn analyzeCall(
68046839 // In order to save a bit of stack space, directly modify Sema rather
68056840 // than create a child one.
68066841 const parent_zir = sema.code;
6842 const module_fn = mod.funcPtr(module_fn_index);
68076843 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
68086844 sema.code = fn_owner_decl.getFileScope(mod).zir;
68096845 defer sema.code = parent_zir;
......@@ -6819,8 +6855,11 @@ fn analyzeCall(
68196855 }
68206856
68216857 const parent_func = sema.func;
6858 const parent_func_index = sema.func_index;
68226859 sema.func = module_fn;
6860 sema.func_index = module_fn_index.toOptional();
68236861 defer sema.func = parent_func;
6862 defer sema.func_index = parent_func_index;
68246863
68256864 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
68266865 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
......@@ -6856,7 +6895,7 @@ fn analyzeCall(
68566895 defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);
68576896 if (is_comptime_call) {
68586897 memoized_call_key = .{
6859 .func = module_fn,
6898 .func = module_fn_index,
68606899 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
68616900 };
68626901 delete_memoized_call_key = true;
......@@ -6889,7 +6928,7 @@ fn analyzeCall(
68896928 &child_block,
68906929 .unneeded,
68916930 inst,
6892 new_fn_info,
6931 &new_fn_info,
68936932 &arg_i,
68946933 uncasted_args,
68956934 is_comptime_call,
......@@ -6907,7 +6946,7 @@ fn analyzeCall(
69076946 &child_block,
69086947 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
69096948 inst,
6910 new_fn_info,
6949 &new_fn_info,
69116950 &arg_i,
69126951 uncasted_args,
69136952 is_comptime_call,
......@@ -6950,7 +6989,7 @@ fn analyzeCall(
69506989 const fn_ret_ty = blk: {
69516990 if (module_fn.hasInferredErrorSet(mod)) {
69526991 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
6953 .func = module_fn,
6992 .func = module_fn_index,
69546993 });
69556994 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
69566995 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
......@@ -6982,7 +7021,7 @@ fn analyzeCall(
69827021
69837022 const new_func_resolved_ty = try mod.funcType(new_fn_info);
69847023 if (!is_comptime_call and !block.is_typeof) {
6985 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
7024 try sema.emitDbgInline(block, parent_func_index.unwrap().?, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
69867025
69877026 const zir_tags = sema.code.instructions.items(.tag);
69887027 for (fn_info.param_body) |param| switch (zir_tags[param]) {
......@@ -7014,7 +7053,7 @@ fn analyzeCall(
70147053 error.ComptimeReturn => break :result inlining.comptime_result,
70157054 error.AnalysisFail => {
70167055 const err_msg = sema.err orelse return err;
7017 if (std.mem.eql(u8, err_msg.msg, recursive_msg)) return err;
7056 if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;
70187057 try sema.errNote(block, call_src, err_msg, "called from here", .{});
70197058 err_msg.clearTrace(sema.gpa);
70207059 return err;
......@@ -7027,8 +7066,8 @@ fn analyzeCall(
70277066 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {
70287067 try sema.emitDbgInline(
70297068 block,
7030 module_fn,
7031 parent_func.?,
7069 module_fn_index,
7070 parent_func_index.unwrap().?,
70327071 mod.declPtr(parent_func.?.owner_decl).ty,
70337072 .dbg_inline_end,
70347073 );
......@@ -7120,8 +7159,8 @@ fn analyzeCall(
71207159 }
71217160
71227161 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7123 if (func_val.castTag(.function)) |func_obj| {
7124 try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);
7162 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7163 try sema.mod.ensureFuncBodyAnalysisQueued(func_index);
71257164 }
71267165 }
71277166
......@@ -7147,9 +7186,9 @@ fn analyzeCall(
71477186 // Function pointers and extern functions aren't guaranteed to
71487187 // actually be noreturn so we add a safety check for them.
71497188 check: {
7150 var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
7151 switch (func_val.tag()) {
7152 .function, .decl_ref => {
7189 const func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
7190 switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7191 .func, .extern_func, .ptr => {
71537192 _ = try block.addNoOp(.unreach);
71547193 return Air.Inst.Ref.unreachable_value;
71557194 },
......@@ -7196,7 +7235,7 @@ fn analyzeInlineCallArg(
71967235 param_block: *Block,
71977236 arg_src: LazySrcLoc,
71987237 inst: Zir.Inst.Index,
7199 new_fn_info: InternPool.Key.FuncType,
7238 new_fn_info: *InternPool.Key.FuncType,
72007239 arg_i: *usize,
72017240 uncasted_args: []const Air.Inst.Ref,
72027241 is_comptime_call: bool,
......@@ -7263,7 +7302,7 @@ fn analyzeInlineCallArg(
72637302 try sema.resolveLazyValue(arg_val);
72647303 },
72657304 }
7266 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
72677306 memoized_call_key.args[arg_i.*] = .{
72687307 .ty = param_ty.toType(),
72697308 .val = arg_val,
......@@ -7302,7 +7341,7 @@ fn analyzeInlineCallArg(
73027341 try sema.resolveLazyValue(arg_val);
73037342 },
73047343 }
7305 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
7344 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState(sema.mod);
73067345 memoized_call_key.args[arg_i.*] = .{
73077346 .ty = sema.typeOf(uncasted_arg),
73087347 .val = arg_val,
......@@ -7387,11 +7426,11 @@ fn instantiateGenericCall(
73877426 const gpa = sema.gpa;
73887427
73897428 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");
7390 const module_fn = switch (func_val.tag()) {
7391 .function => func_val.castTag(.function).?.data,
7392 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
7429 const module_fn = mod.funcPtr(switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
7430 .func => |function| function.index,
7431 .ptr => |ptr| mod.declPtr(ptr.addr.decl).getFunctionIndex(mod).unwrap().?,
73937432 else => unreachable,
7394 };
7433 });
73957434 // Check the Module's generic function map with an adapted context, so that we
73967435 // can match against `uncasted_args` rather than doing the work below to create a
73977436 // generic Scope only to junk it if it matches an existing instantiation.
......@@ -7496,16 +7535,17 @@ fn instantiateGenericCall(
74967535 .args = generic_args,
74977536 .module = mod,
74987537 };
7499 const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);
7500 const callee = if (!gop.found_existing) callee: {
7501 const new_module_func = try gpa.create(Module.Fn);
7538 const gop = try mod.monomorphed_funcs.getOrPutContextAdapted(gpa, {}, adapter, .{ .mod = mod });
7539 const callee_index = if (!gop.found_existing) callee: {
7540 const new_module_func_index = try mod.createFunc(undefined);
7541 const new_module_func = mod.funcPtr(new_module_func_index);
75027542
75037543 // This ensures that we can operate on the hash map before the Module.Fn
75047544 // struct is fully initialized.
75057545 new_module_func.hash = precomputed_hash;
75067546 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
75077547 new_module_func.comptime_args = null;
7508 gop.key_ptr.* = new_module_func;
7548 gop.key_ptr.* = new_module_func_index;
75097549
75107550 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
75117551
......@@ -7549,7 +7589,7 @@ fn instantiateGenericCall(
75497589 new_decl_index,
75507590 uncasted_args,
75517591 module_fn,
7552 new_module_func,
7592 new_module_func_index,
75537593 namespace_index,
75547594 func_ty_info,
75557595 call_src,
......@@ -7565,12 +7605,12 @@ fn instantiateGenericCall(
75657605 }
75667606 assert(namespace.anon_decls.orderedRemove(new_decl_index));
75677607 mod.destroyDecl(new_decl_index);
7568 assert(mod.monomorphed_funcs.remove(new_module_func));
7569 gpa.destroy(new_module_func);
7608 assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
7609 mod.destroyFunc(new_module_func_index);
75707610 return err;
75717611 },
75727612 else => {
7573 assert(mod.monomorphed_funcs.remove(new_module_func));
7613 assert(mod.monomorphed_funcs.removeContext(new_module_func_index, .{ .mod = mod }));
75747614 {
75757615 errdefer new_decl_arena.deinit();
75767616 try new_decl.finalizeNewArena(&new_decl_arena);
......@@ -7590,6 +7630,7 @@ fn instantiateGenericCall(
75907630 try new_decl.finalizeNewArena(&new_decl_arena);
75917631 break :callee new_func;
75927632 } else gop.key_ptr.*;
7633 const callee = mod.funcPtr(callee_index);
75937634
75947635 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
75957636
......@@ -7645,7 +7686,7 @@ fn instantiateGenericCall(
76457686 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
76467687 }
76477688
7648 try sema.mod.ensureFuncBodyAnalysisQueued(callee);
7689 try sema.mod.ensureFuncBodyAnalysisQueued(callee_index);
76497690
76507691 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
76517692 runtime_args_len);
......@@ -7682,12 +7723,12 @@ fn resolveGenericInstantiationType(
76827723 new_decl_index: Decl.Index,
76837724 uncasted_args: []const Air.Inst.Ref,
76847725 module_fn: *Module.Fn,
7685 new_module_func: *Module.Fn,
7726 new_module_func: Module.Fn.Index,
76867727 namespace: Namespace.Index,
76877728 func_ty_info: InternPool.Key.FuncType,
76887729 call_src: LazySrcLoc,
76897730 bound_arg_src: ?LazySrcLoc,
7690) !*Module.Fn {
7731) !Module.Fn.Index {
76917732 const mod = sema.mod;
76927733 const gpa = sema.gpa;
76937734
......@@ -7707,11 +7748,13 @@ fn resolveGenericInstantiationType(
77077748 .owner_decl = new_decl,
77087749 .owner_decl_index = new_decl_index,
77097750 .func = null,
7751 .func_index = .none,
77107752 .fn_ret_ty = Type.void,
77117753 .owner_func = null,
7754 .owner_func_index = .none,
77127755 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
77137756 .comptime_args_fn_inst = module_fn.zir_body_inst,
7714 .preallocated_new_func = new_module_func,
7757 .preallocated_new_func = new_module_func.toOptional(),
77157758 .is_generic_instantiation = true,
77167759 .branch_quota = sema.branch_quota,
77177760 .branch_count = sema.branch_count,
......@@ -7802,8 +7845,8 @@ fn resolveGenericInstantiationType(
78027845
78037846 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
78047847 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7805 const new_func = new_func_val.castTag(.function).?.data;
7806 errdefer new_func.deinit(gpa);
7848 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
7849 errdefer mod.destroyFunc(new_func);
78077850 assert(new_func == new_module_func);
78087851
78097852 arg_i = 0;
......@@ -7867,7 +7910,10 @@ fn resolveGenericInstantiationType(
78677910 return error.GenericPoison;
78687911 }
78697912
7870 new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
7913 new_decl.val = (try mod.intern(.{ .func = .{
7914 .ty = new_decl.ty.ip_index,
7915 .index = new_func,
7916 } })).toValue();
78717917 new_decl.@"align" = 0;
78727918 new_decl.has_tv = true;
78737919 new_decl.owns_tv = true;
......@@ -7900,8 +7946,8 @@ fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type)
79007946fn emitDbgInline(
79017947 sema: *Sema,
79027948 block: *Block,
7903 old_func: *Module.Fn,
7904 new_func: *Module.Fn,
7949 old_func: Module.Fn.Index,
7950 new_func: Module.Fn.Index,
79057951 new_func_ty: Type,
79067952 tag: Air.Inst.Tag,
79077953) CompileError!void {
......@@ -7910,7 +7956,10 @@ fn emitDbgInline(
79107956 // Recursive inline call; no dbg_inline needed.
79117957 if (old_func == new_func) return;
79127958
7913 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
7959 try sema.air_values.append(sema.gpa, (try sema.mod.intern(.{ .func = .{
7960 .ty = new_func_ty.ip_index,
7961 .index = new_func,
7962 } })).toValue());
79147963 _ = try block.addInst(.{
79157964 .tag = tag,
79167965 .data = .{ .ty_pl = .{
......@@ -8078,12 +8127,11 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
80788127 const name = inst_data.get(sema.code);
80798128 // Create an error set type with only this error value, and return the value.
80808129 const kv = try sema.mod.getErrorValue(name);
8081 return sema.addConstant(
8082 try mod.singleErrorSetType(kv.key),
8083 try Value.Tag.@"error".create(sema.arena, .{
8084 .name = kv.key,
8085 }),
8086 );
8130 const error_set_type = try mod.singleErrorSetType(kv.key);
8131 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
8132 .ty = error_set_type.ip_index,
8133 .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
8134 } })).toValue());
80878135}
80888136
80898137fn 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
81018149 if (val.isUndef(mod)) {
81028150 return sema.addConstUndef(Type.err_int);
81038151 }
8104 switch (val.tag()) {
8105 .@"error" => {
8106 return sema.addConstant(
8107 Type.err_int,
8108 try mod.intValue(
8109 Type.err_int,
8110 (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,
8111 ),
8112 );
8113 },
8114
8115 // This is not a valid combination with the type `anyerror`.
8116 .the_only_possible_value => unreachable,
8117
8118 // Assume it's already encoded as an integer.
8119 else => return sema.addConstant(Type.err_int, val),
8120 }
8152 const err_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
8153 return sema.addConstant(Type.err_int, try mod.intValue(
8154 Type.err_int,
8155 (try mod.getErrorValue(mod.intern_pool.stringToSlice(err_name))).value,
8156 ));
81218157 }
81228158
81238159 const op_ty = sema.typeOf(uncasted_operand);
......@@ -8142,23 +8178,21 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
81428178 const tracy = trace(@src());
81438179 defer tracy.end();
81448180
8181 const mod = sema.mod;
81458182 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
81468183 const src = LazySrcLoc.nodeOffset(extra.node);
81478184 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
81488185 const uncasted_operand = try sema.resolveInst(extra.operand);
81498186 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
8150 const mod = sema.mod;
81518187
81528188 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
81538189 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
81548190 if (int > sema.mod.global_error_set.count() or int == 0)
81558191 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8156 const payload = try sema.arena.create(Value.Payload.Error);
8157 payload.* = .{
8158 .base = .{ .tag = .@"error" },
8159 .data = .{ .name = sema.mod.error_name_list.items[int] },
8160 };
8161 return sema.addConstant(Type.anyerror, Value.initPayload(&payload.base));
8192 return sema.addConstant(Type.anyerror, (try mod.intern(.{ .err = .{
8193 .ty = .anyerror_type,
8194 .name = mod.intern_pool.getString(sema.mod.error_name_list.items[int]).unwrap().?,
8195 } })).toValue());
81628196 }
81638197 try sema.requireRuntimeBlock(block, src, operand_src);
81648198 if (block.wantSafety()) {
......@@ -8234,12 +8268,12 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
82348268 const tracy = trace(@src());
82358269 defer tracy.end();
82368270
8271 const mod = sema.mod;
82378272 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
8238 const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));
8239 return sema.addConstant(
8240 .{ .ip_index = .enum_literal_type },
8241 try Value.Tag.enum_literal.create(sema.arena, duped_name),
8242 );
8273 const name = inst_data.get(sema.code);
8274 return sema.addConstant(.{ .ip_index = .enum_literal_type }, (try mod.intern(.{
8275 .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name),
8276 })).toValue());
82438277}
82448278
82458279fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -8404,32 +8438,26 @@ fn analyzeOptionalPayloadPtr(
84048438
84058439 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
84068440 if (initializing) {
8407 if (!ptr_val.isComptimeMutablePtr()) {
8441 if (!ptr_val.isComptimeMutablePtr(mod)) {
84088442 // If the pointer resulting from this function was stored at comptime,
84098443 // the optional non-null bit would be set that way. But in this case,
84108444 // we need to emit a runtime instruction to do it.
84118445 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
84128446 }
8413 return sema.addConstant(
8414 child_pointer,
8415 try Value.Tag.opt_payload_ptr.create(sema.arena, .{
8416 .container_ptr = ptr_val,
8417 .container_ty = optional_ptr_ty.childType(mod),
8418 }),
8419 );
8447 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8448 .ty = child_pointer.ip_index,
8449 .addr = .{ .opt_payload = ptr_val.ip_index },
8450 } })).toValue());
84208451 }
84218452 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
84228453 if (val.isNull(mod)) {
84238454 return sema.fail(block, src, "unable to unwrap null", .{});
84248455 }
84258456 // The same Value represents the pointer to the optional and the payload.
8426 return sema.addConstant(
8427 child_pointer,
8428 try Value.Tag.opt_payload_ptr.create(sema.arena, .{
8429 .container_ptr = ptr_val,
8430 .container_ty = optional_ptr_ty.childType(mod),
8431 }),
8432 );
8457 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8458 .ty = child_pointer.ip_index,
8459 .addr = .{ .opt_payload = ptr_val.ip_index },
8460 } })).toValue());
84338461 }
84348462 }
84358463
......@@ -8532,11 +8560,13 @@ fn analyzeErrUnionPayload(
85328560 const mod = sema.mod;
85338561 const payload_ty = err_union_ty.errorUnionPayload(mod);
85348562 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
8535 if (val.getError()) |name| {
8563 if (val.getError(mod)) |name| {
85368564 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
85378565 }
8538 const data = val.castTag(.eu_payload).?.data;
8539 return sema.addConstant(payload_ty, data);
8566 return sema.addConstant(
8567 payload_ty,
8568 mod.intern_pool.indexToKey(val.ip_index).error_union.val.payload.toValue(),
8569 );
85408570 }
85418571
85428572 try sema.requireRuntimeBlock(block, src, null);
......@@ -8595,33 +8625,26 @@ fn analyzeErrUnionPayloadPtr(
85958625
85968626 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {
85978627 if (initializing) {
8598 if (!ptr_val.isComptimeMutablePtr()) {
8628 if (!ptr_val.isComptimeMutablePtr(mod)) {
85998629 // If the pointer resulting from this function was stored at comptime,
86008630 // the error union error code would be set that way. But in this case,
86018631 // we need to emit a runtime instruction to do it.
86028632 try sema.requireRuntimeBlock(block, src, null);
86038633 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
86048634 }
8605 return sema.addConstant(
8606 operand_pointer_ty,
8607 try Value.Tag.eu_payload_ptr.create(sema.arena, .{
8608 .container_ptr = ptr_val,
8609 .container_ty = operand_ty.childType(mod),
8610 }),
8611 );
8635 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8636 .ty = operand_pointer_ty.ip_index,
8637 .addr = .{ .eu_payload = ptr_val.ip_index },
8638 } })).toValue());
86128639 }
86138640 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
8614 if (val.getError()) |name| {
8641 if (val.getError(mod)) |name| {
86158642 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
86168643 }
8617
8618 return sema.addConstant(
8619 operand_pointer_ty,
8620 try Value.Tag.eu_payload_ptr.create(sema.arena, .{
8621 .container_ptr = ptr_val,
8622 .container_ty = operand_ty.childType(mod),
8623 }),
8624 );
8644 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8645 .ty = operand_pointer_ty.ip_index,
8646 .addr = .{ .eu_payload = ptr_val.ip_index },
8647 } })).toValue());
86258648 }
86268649 }
86278650
......@@ -8664,7 +8687,7 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air
86648687 const result_ty = operand_ty.errorUnionSet(mod);
86658688
86668689 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8667 assert(val.getError() != null);
8690 assert(val.getError(mod) != null);
86688691 return sema.addConstant(result_ty, val);
86698692 }
86708693
......@@ -8694,7 +8717,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
86948717
86958718 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
86968719 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
8697 assert(val.getError() != null);
8720 assert(val.getError(mod) != null);
86988721 return sema.addConstant(result_ty, val);
86998722 }
87008723 }
......@@ -8931,20 +8954,21 @@ fn funcCommon(
89318954 }
89328955
89338956 var destroy_fn_on_error = false;
8934 const new_func: *Module.Fn = new_func: {
8957 const new_func_index = new_func: {
89358958 if (!has_body) break :new_func undefined;
89368959 if (sema.comptime_args_fn_inst == func_inst) {
8937 const new_func = sema.preallocated_new_func.?;
8938 sema.preallocated_new_func = null; // take ownership
8939 break :new_func new_func;
8960 const new_func_index = sema.preallocated_new_func.unwrap().?;
8961 sema.preallocated_new_func = .none; // take ownership
8962 break :new_func new_func_index;
89408963 }
89418964 destroy_fn_on_error = true;
8942 const new_func = try gpa.create(Module.Fn);
8965 var new_func: Module.Fn = undefined;
89438966 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
89448967 new_func.owner_decl = sema.owner_decl_index;
8945 break :new_func new_func;
8968 const new_func_index = try mod.createFunc(new_func);
8969 break :new_func new_func_index;
89468970 };
8947 errdefer if (destroy_fn_on_error) gpa.destroy(new_func);
8971 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
89488972
89498973 const target = sema.mod.getTarget();
89508974 const fn_ty: Type = fn_ty: {
......@@ -9008,7 +9032,7 @@ fn funcCommon(
90089032 else blk: {
90099033 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
90109034 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
9011 .func = new_func,
9035 .func = new_func_index,
90129036 });
90139037 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
90149038 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
......@@ -9158,26 +9182,16 @@ fn funcCommon(
91589182 sema.owner_decl.@"addrspace" = address_space orelse .generic;
91599183
91609184 if (is_extern) {
9161 const new_extern_fn = try gpa.create(Module.ExternFn);
9162 errdefer gpa.destroy(new_extern_fn);
9163
9164 new_extern_fn.* = Module.ExternFn{
9165 .owner_decl = sema.owner_decl_index,
9166 .lib_name = null,
9167 };
9168
9169 if (opt_lib_name) |lib_name| {
9170 new_extern_fn.lib_name = try sema.handleExternLibName(block, .{
9171 .node_offset_lib_name = src_node_offset,
9172 }, lib_name);
9173 }
9174
9175 const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn);
9176 extern_fn_payload.* = .{
9177 .base = .{ .tag = .extern_fn },
9178 .data = new_extern_fn,
9179 };
9180 return sema.addConstant(fn_ty, Value.initPayload(&extern_fn_payload.base));
9185 return sema.addConstant(fn_ty, (try mod.intern(.{ .extern_func = .{
9186 .ty = fn_ty.ip_index,
9187 .decl = sema.owner_decl_index,
9188 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9189 gpa,
9190 try sema.handleExternLibName(block, .{
9191 .node_offset_lib_name = src_node_offset,
9192 }, lib_name),
9193 )).toOptional() else .none,
9194 } })).toValue());
91819195 }
91829196
91839197 if (!has_body) {
......@@ -9191,9 +9205,9 @@ fn funcCommon(
91919205 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
91929206 } else null;
91939207
9208 const new_func = mod.funcPtr(new_func_index);
91949209 const hash = new_func.hash;
91959210 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
9196 const fn_payload = try sema.arena.create(Value.Payload.Function);
91979211 new_func.* = .{
91989212 .state = anal_state,
91999213 .zir_body_inst = func_inst,
......@@ -9208,11 +9222,10 @@ fn funcCommon(
92089222 .branch_quota = default_branch_quota,
92099223 .is_noinline = is_noinline,
92109224 };
9211 fn_payload.* = .{
9212 .base = .{ .tag = .function },
9213 .data = new_func,
9214 };
9215 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
9225 return sema.addConstant(fn_ty, (try mod.intern(.{ .func = .{
9226 .ty = fn_ty.ip_index,
9227 .index = new_func_index,
9228 } })).toValue());
92169229}
92179230
92189231fn analyzeParameter(
......@@ -9312,7 +9325,7 @@ fn zirParam(
93129325 const prev_preallocated_new_func = sema.preallocated_new_func;
93139326 const prev_no_partial_func_type = sema.no_partial_func_ty;
93149327 block.params = .{};
9315 sema.preallocated_new_func = null;
9328 sema.preallocated_new_func = .none;
93169329 sema.no_partial_func_ty = true;
93179330 defer {
93189331 block.params.deinit(sema.gpa);
......@@ -9369,7 +9382,7 @@ fn zirParam(
93699382 else => |e| return e,
93709383 } or comptime_syntax;
93719384 if (sema.inst_map.get(inst)) |arg| {
9372 if (is_comptime and sema.preallocated_new_func != null) {
9385 if (is_comptime and sema.preallocated_new_func != .none) {
93739386 // We have a comptime value for this parameter so it should be elided from the
93749387 // function type of the function instruction in this block.
93759388 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
......@@ -9392,7 +9405,7 @@ fn zirParam(
93929405 assert(sema.inst_map.remove(inst));
93939406 }
93949407
9395 if (sema.preallocated_new_func != null) {
9408 if (sema.preallocated_new_func != .none) {
93969409 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
93979410 // In this case we are instantiating a generic function call with a non-comptime
93989411 // non-anytype parameter that ended up being a one-possible-type.
......@@ -9640,8 +9653,8 @@ fn intCast(
96409653
96419654 if (wanted_bits == 0) {
96429655 const ok = if (is_vector) ok: {
9643 const zeros = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
9644 const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
9656 const zeros = try sema.splat(operand_ty, try mod.intValue(operand_scalar_ty, 0));
9657 const zero_inst = try sema.addConstant(operand_ty, zeros);
96459658 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
96469659 const all_in_range = try block.addInst(.{
96479660 .tag = .reduce,
......@@ -9649,7 +9662,7 @@ fn intCast(
96499662 });
96509663 break :ok all_in_range;
96519664 } else ok: {
9652 const zero_inst = try sema.addConstant(sema.typeOf(operand), try mod.intValue(operand_ty, 0));
9665 const zero_inst = try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0));
96539666 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
96549667 break :ok is_in_range;
96559668 };
......@@ -9673,10 +9686,7 @@ fn intCast(
96739686 // requirement: int value fits into target type
96749687 if (wanted_value_bits < actual_value_bits) {
96759688 const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_ty);
9676 const dest_max_val = if (is_vector)
9677 try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar)
9678 else
9679 dest_max_val_scalar;
9689 const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
96809690 const dest_max = try sema.addConstant(operand_ty, dest_max_val);
96819691 const diff = try block.addBinOp(.subwrap, dest_max, operand);
96829692
......@@ -9732,7 +9742,8 @@ fn intCast(
97329742 // no shrinkage, yes sign loss
97339743 // requirement: signed to unsigned >= 0
97349744 const ok = if (is_vector) ok: {
9735 const zero_val = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
9745 const scalar_zero = try mod.intValue(operand_scalar_ty, 0);
9746 const zero_val = try sema.splat(operand_ty, scalar_zero);
97369747 const zero_inst = try sema.addConstant(operand_ty, zero_val);
97379748 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
97389749 const all_in_range = try block.addInst(.{
......@@ -10139,17 +10150,18 @@ fn zirSwitchCapture(
1013910150 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
1014010151 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
1014110152 });
10142 return sema.addConstant(
10143 ptr_field_ty,
10144 try Value.Tag.field_ptr.create(sema.arena, .{
10145 .container_ptr = union_val,
10146 .container_ty = operand_ty,
10147 .field_index = field_index,
10148 }),
10149 );
10153 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
10154 .ty = ptr_field_ty.ip_index,
10155 .addr = .{ .field = .{
10156 .base = union_val.ip_index,
10157 .index = field_index,
10158 } },
10159 } })).toValue());
1015010160 }
10151 const tag_and_val = union_val.castTag(.@"union").?.data;
10152 return sema.addConstant(field_ty, tag_and_val.val);
10161 return sema.addConstant(
10162 field_ty,
10163 mod.intern_pool.indexToKey(union_val.ip_index).un.val.toValue(),
10164 );
1015310165 }
1015410166 if (is_ref) {
1015510167 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
......@@ -10243,14 +10255,13 @@ fn zirSwitchCapture(
1024310255 });
1024410256
1024510257 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
10246 return sema.addConstant(
10247 field_ty_ptr,
10248 try Value.Tag.field_ptr.create(sema.arena, .{
10249 .container_ptr = op_ptr_val,
10250 .container_ty = operand_ty,
10251 .field_index = first_field_index,
10252 }),
10253 );
10258 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10259 .ty = field_ty_ptr.ip_index,
10260 .addr = .{ .field = .{
10261 .base = op_ptr_val.ip_index,
10262 .index = first_field_index,
10263 } },
10264 } })).toValue());
1025410265 }
1025510266 try sema.requireRuntimeBlock(block, operand_src, null);
1025610267 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
......@@ -10273,7 +10284,7 @@ fn zirSwitchCapture(
1027310284 const item_ref = try sema.resolveInst(item);
1027410285 // Previous switch validation ensured this will succeed
1027510286 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
10276 const name_ip = try mod.intern_pool.getOrPutString(gpa, item_val.getError().?);
10287 const name_ip = try mod.intern_pool.getOrPutString(gpa, item_val.getError(mod).?);
1027710288 names.putAssumeCapacityNoClobber(name_ip, {});
1027810289 }
1027910290 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
......@@ -10284,7 +10295,7 @@ fn zirSwitchCapture(
1028410295 // Previous switch validation ensured this will succeed
1028510296 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
1028610297
10287 const item_ty = try mod.singleErrorSetType(item_val.getError().?);
10298 const item_ty = try mod.singleErrorSetType(item_val.getError(mod).?);
1028810299 return sema.bitCast(block, item_ty, operand, operand_src, null);
1028910300 }
1029010301 },
......@@ -10809,10 +10820,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1080910820
1081010821 check_range: {
1081110822 if (operand_ty.zigTypeTag(mod) == .Int) {
10812 var arena = std.heap.ArenaAllocator.init(gpa);
10813 defer arena.deinit();
10814
10815 const min_int = try operand_ty.minInt(arena.allocator(), mod);
10823 const min_int = try operand_ty.minInt(mod);
1081610824 const max_int = try operand_ty.maxIntScalar(mod, Type.comptime_int);
1081710825 if (try range_set.spans(min_int, max_int, operand_ty)) {
1081810826 if (special_prong == .@"else") {
......@@ -11493,8 +11501,11 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1149311501 if (seen_errors.contains(error_name)) continue;
1149411502 cases_len += 1;
1149511503
11496 const item_val = try Value.Tag.@"error".create(sema.arena, .{ .name = error_name });
11497 const item_ref = try sema.addConstant(operand_ty, item_val);
11504 const item_val = try mod.intern(.{ .err = .{
11505 .ty = operand_ty.ip_index,
11506 .name = error_name_ip,
11507 } });
11508 const item_ref = try sema.addConstant(operand_ty, item_val.toValue());
1149811509 case_block.inline_case_capture = item_ref;
1149911510
1150011511 case_block.instructions.shrinkRetainingCapacity(0);
......@@ -11665,7 +11676,7 @@ const RangeSetUnhandledIterator = struct {
1166511676
1166611677 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
1166711678 const mod = sema.mod;
11668 const min = try ty.minInt(sema.arena, mod);
11679 const min = try ty.minInt(mod);
1166911680 const max = try ty.maxIntScalar(mod, Type.comptime_int);
1167011681
1167111682 return RangeSetUnhandledIterator{
......@@ -11788,9 +11799,10 @@ fn validateSwitchItemError(
1178811799 src_node_offset: i32,
1178911800 switch_prong_src: Module.SwitchProngSrc,
1179011801) CompileError!void {
11802 const ip = &sema.mod.intern_pool;
1179111803 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
1179211804 // TODO: Do i need to typecheck here?
11793 const error_name = item_tv.val.castTag(.@"error").?.data.name;
11805 const error_name = ip.stringToSlice(ip.indexToKey(item_tv.val.ip_index).err.name);
1179411806 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
1179511807 prev.value
1179611808 else
......@@ -11983,7 +11995,7 @@ fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Ind
1198311995 }
1198411996 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
1198511997 if (!operand_ty.isError(mod)) return;
11986 if (val.getError() == null) return;
11998 if (val.getError(mod) == null) return;
1198711999 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
1198812000 }
1198912001}
......@@ -12005,7 +12017,7 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
1200512017 const src = inst_data.src();
1200612018
1200712019 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
12008 if (val.getError()) |name| {
12020 if (val.getError(sema.mod)) |name| {
1200912021 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
1201012022 }
1201112023 }
......@@ -12172,11 +12184,11 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
1217212184
1217312185 // Return the error code from the function.
1217412186 const kv = try mod.getErrorValue(err_name);
12175 const result_inst = try sema.addConstant(
12176 try mod.singleErrorSetType(kv.key),
12177 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
12178 );
12179 return result_inst;
12187 const error_set_type = try mod.singleErrorSetType(kv.key);
12188 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
12189 .ty = error_set_type.ip_index,
12190 .name = mod.intern_pool.getString(kv.key).unwrap().?,
12191 } })).toValue());
1218012192}
1218112193
1218212194fn zirShl(
......@@ -12301,7 +12313,7 @@ fn zirShl(
1230112313 {
1230212314 const max_int = try sema.addConstant(
1230312315 lhs_ty,
12304 try lhs_ty.maxInt(sema.arena, mod, lhs_ty),
12316 try lhs_ty.maxInt(mod, lhs_ty),
1230512317 );
1230612318 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });
1230712319 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
......@@ -12316,7 +12328,7 @@ fn zirShl(
1231612328 if (!std.math.isPowerOfTwo(bit_count)) {
1231712329 const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);
1231812330 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12319 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12331 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
1232012332 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1232112333 break :ok try block.addInst(.{
1232212334 .tag = .reduce,
......@@ -12466,7 +12478,7 @@ fn zirShr(
1246612478 const bit_count_val = try mod.intValue(scalar_ty, bit_count);
1246712479
1246812480 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12469 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12481 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
1247012482 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1247112483 break :ok try block.addInst(.{
1247212484 .tag = .reduce,
......@@ -13179,11 +13191,7 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1317913191 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
1318013192 }
1318113193
13182 const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
13183 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
13184 else
13185 try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
13186
13194 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
1318713195 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
1318813196}
1318913197
......@@ -13203,11 +13211,7 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1320313211 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),
1320413212 }
1320513213
13206 const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
13207 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
13208 else
13209 try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
13210
13214 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
1321113215 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
1321213216}
1321313217
......@@ -13254,8 +13258,6 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1325413258 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1325513259 });
1325613260
13257 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13258
1325913261 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1326013262 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1326113263
......@@ -13325,9 +13327,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1332513327 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
1332613328 else => unreachable,
1332713329 };
13328 const zero_val = if (is_vector) b: {
13329 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13330 } else scalar_zero;
13330 const zero_val = try sema.splat(resolved_type, scalar_zero);
1333113331 return sema.addConstant(resolved_type, zero_val);
1333213332 }
1333313333 }
......@@ -13427,8 +13427,6 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1342713427 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1342813428 });
1342913429
13430 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13431
1343213430 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1343313431 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1343413432
......@@ -13469,9 +13467,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1346913467 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
1347013468 else => unreachable,
1347113469 };
13472 const zero_val = if (is_vector) b: {
13473 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13474 } else scalar_zero;
13470 const zero_val = try sema.splat(resolved_type, scalar_zero);
1347513471 return sema.addConstant(resolved_type, zero_val);
1347613472 }
1347713473 }
......@@ -13555,7 +13551,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1355513551 else => unreachable,
1355613552 };
1355713553 if (resolved_type.zigTypeTag(mod) == .Vector) {
13558 const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
13554 const zero_val = try sema.splat(resolved_type, scalar_zero);
1355913555 const zero = try sema.addConstant(resolved_type, zero_val);
1356013556 const eql = try block.addCmpVector(remainder, zero, .eq);
1356113557 break :ok try block.addInst(.{
......@@ -13600,8 +13596,6 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1360013596 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1360113597 });
1360213598
13603 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13604
1360513599 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1360613600 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1360713601
......@@ -13644,9 +13638,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1364413638 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
1364513639 else => unreachable,
1364613640 };
13647 const zero_val = if (is_vector) b: {
13648 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13649 } else scalar_zero;
13641 const zero_val = try sema.splat(resolved_type, scalar_zero);
1365013642 return sema.addConstant(resolved_type, zero_val);
1365113643 }
1365213644 }
......@@ -13721,8 +13713,6 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1372113713 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1372213714 });
1372313715
13724 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
13725
1372613716 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1372713717 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1372813718
......@@ -13765,9 +13755,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1376513755 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
1376613756 else => unreachable,
1376713757 };
13768 const zero_val = if (is_vector) b: {
13769 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
13770 } else scalar_zero;
13758 const zero_val = try sema.splat(resolved_type, scalar_zero);
1377113759 return sema.addConstant(resolved_type, zero_val);
1377213760 }
1377313761 }
......@@ -13843,12 +13831,9 @@ fn addDivIntOverflowSafety(
1384313831 return;
1384413832 }
1384513833
13846 const min_int = try resolved_type.minInt(sema.arena, mod);
13834 const min_int = try resolved_type.minInt(mod);
1384713835 const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
13848 const neg_one = if (resolved_type.zigTypeTag(mod) == .Vector)
13849 try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
13850 else
13851 neg_one_scalar;
13836 const neg_one = try sema.splat(resolved_type, neg_one_scalar);
1385213837
1385313838 // If the LHS is comptime-known to be not equal to the min int,
1385413839 // no overflow is possible.
......@@ -13924,7 +13909,7 @@ fn addDivByZeroSafety(
1392413909 else
1392513910 try mod.floatValue(resolved_type.scalarType(mod), 0);
1392613911 const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
13927 const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
13912 const zero_val = try sema.splat(resolved_type, scalar_zero);
1392813913 const zero = try sema.addConstant(resolved_type, zero_val);
1392913914 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
1393013915 break :ok try block.addInst(.{
......@@ -14012,9 +13997,10 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1401213997 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
1401313998 else => unreachable,
1401413999 };
14015 const zero_val = if (is_vector) b: {
14016 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14017 } else scalar_zero;
14000 const zero_val = if (is_vector) (try mod.intern(.{ .aggregate = .{
14001 .ty = resolved_type.ip_index,
14002 .storage = .{ .repeated_elem = scalar_zero.ip_index },
14003 } })).toValue() else scalar_zero;
1401814004 return sema.addConstant(resolved_type, zero_val);
1401914005 }
1402014006 } else if (lhs_scalar_ty.isSignedInt(mod)) {
......@@ -14399,12 +14385,12 @@ fn zirOverflowArithmetic(
1439914385 // Otherwise, if either of the argument is undefined, undefined is returned.
1440014386 if (maybe_lhs_val) |lhs_val| {
1440114387 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14402 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
14388 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
1440314389 }
1440414390 }
1440514391 if (maybe_rhs_val) |rhs_val| {
1440614392 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14407 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14393 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
1440814394 }
1440914395 }
1441014396 if (maybe_lhs_val) |lhs_val| {
......@@ -14425,7 +14411,7 @@ fn zirOverflowArithmetic(
1442514411 if (rhs_val.isUndef(mod)) {
1442614412 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1442714413 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14428 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14414 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
1442914415 } else if (maybe_lhs_val) |lhs_val| {
1443014416 if (lhs_val.isUndef(mod)) {
1443114417 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
......@@ -14444,9 +14430,9 @@ fn zirOverflowArithmetic(
1444414430 if (maybe_lhs_val) |lhs_val| {
1444514431 if (!lhs_val.isUndef(mod)) {
1444614432 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14447 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14448 } else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
14449 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
14433 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
14434 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14435 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
1445014436 }
1445114437 }
1445214438 }
......@@ -14454,9 +14440,9 @@ fn zirOverflowArithmetic(
1445414440 if (maybe_rhs_val) |rhs_val| {
1445514441 if (!rhs_val.isUndef(mod)) {
1445614442 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14457 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
14458 } else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
14459 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14443 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = rhs };
14444 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14445 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
1446014446 }
1446114447 }
1446214448 }
......@@ -14478,12 +14464,12 @@ fn zirOverflowArithmetic(
1447814464 // Oterhwise if either of the arguments is undefined, both results are undefined.
1447914465 if (maybe_lhs_val) |lhs_val| {
1448014466 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14481 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14467 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
1448214468 }
1448314469 }
1448414470 if (maybe_rhs_val) |rhs_val| {
1448514471 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14486 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
14472 break :result .{ .overflow_bit = try sema.splat(dest_ty, zero), .inst = lhs };
1448714473 }
1448814474 }
1448914475 if (maybe_lhs_val) |lhs_val| {
......@@ -14544,10 +14530,14 @@ fn zirOverflowArithmetic(
1454414530 return block.addAggregateInit(tuple_ty, element_refs);
1454514531}
1454614532
14547fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {
14533fn splat(sema: *Sema, ty: Type, val: Value) !Value {
1454814534 const mod = sema.mod;
1454914535 if (ty.zigTypeTag(mod) != .Vector) return val;
14550 return Value.Tag.repeated.create(sema.arena, val);
14536 const repeated = try mod.intern(.{ .aggregate = .{
14537 .ty = ty.ip_index,
14538 .storage = .{ .repeated_elem = val.ip_index },
14539 } });
14540 return repeated.toValue();
1455114541}
1455214542
1455314543fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
......@@ -14603,8 +14593,6 @@ fn analyzeArithmetic(
1460314593 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1460414594 });
1460514595
14606 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
14607
1460814596 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1460914597 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1461014598
......@@ -14853,9 +14841,7 @@ fn analyzeArithmetic(
1485314841 } else if (resolved_type.isAnyFloat()) {
1485414842 break :lz;
1485514843 }
14856 const zero_val = if (is_vector) b: {
14857 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14858 } else scalar_zero;
14844 const zero_val = try sema.splat(resolved_type, scalar_zero);
1485914845 return sema.addConstant(resolved_type, zero_val);
1486014846 }
1486114847 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -14886,9 +14872,7 @@ fn analyzeArithmetic(
1488614872 } else if (resolved_type.isAnyFloat()) {
1488714873 break :rz;
1488814874 }
14889 const zero_val = if (is_vector) b: {
14890 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14891 } else scalar_zero;
14875 const zero_val = try sema.splat(resolved_type, scalar_zero);
1489214876 return sema.addConstant(resolved_type, zero_val);
1489314877 }
1489414878 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -14931,9 +14915,7 @@ fn analyzeArithmetic(
1493114915 if (maybe_lhs_val) |lhs_val| {
1493214916 if (!lhs_val.isUndef(mod)) {
1493314917 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14934 const zero_val = if (is_vector) b: {
14935 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14936 } else scalar_zero;
14918 const zero_val = try sema.splat(resolved_type, scalar_zero);
1493714919 return sema.addConstant(resolved_type, zero_val);
1493814920 }
1493914921 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -14947,9 +14929,7 @@ fn analyzeArithmetic(
1494714929 return sema.addConstUndef(resolved_type);
1494814930 }
1494914931 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14950 const zero_val = if (is_vector) b: {
14951 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14952 } else scalar_zero;
14932 const zero_val = try sema.splat(resolved_type, scalar_zero);
1495314933 return sema.addConstant(resolved_type, zero_val);
1495414934 }
1495514935 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -14979,9 +14959,7 @@ fn analyzeArithmetic(
1497914959 if (maybe_lhs_val) |lhs_val| {
1498014960 if (!lhs_val.isUndef(mod)) {
1498114961 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14982 const zero_val = if (is_vector) b: {
14983 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14984 } else scalar_zero;
14962 const zero_val = try sema.splat(resolved_type, scalar_zero);
1498514963 return sema.addConstant(resolved_type, zero_val);
1498614964 }
1498714965 if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -14994,9 +14972,7 @@ fn analyzeArithmetic(
1499414972 return sema.addConstUndef(resolved_type);
1499514973 }
1499614974 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14997 const zero_val = if (is_vector) b: {
14998 break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
14999 } else scalar_zero;
14975 const zero_val = try sema.splat(resolved_type, scalar_zero);
1500014976 return sema.addConstant(resolved_type, zero_val);
1500114977 }
1500214978 if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
......@@ -15138,7 +15114,7 @@ fn analyzePtrArithmetic(
1513815114 if (air_tag == .ptr_sub) {
1513915115 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
1514015116 }
15141 const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int, sema.mod);
15117 const new_ptr_val = try ptr_val.elemPtr(ptr_ty, offset_int, sema.mod);
1514215118 return sema.addConstant(new_ptr_ty, new_ptr_val);
1514315119 } else break :rs offset_src;
1514415120 } else break :rs ptr_src;
......@@ -15184,7 +15160,7 @@ fn zirAsm(
1518415160 const inputs_len = @truncate(u5, extended.small >> 5);
1518515161 const clobbers_len = @truncate(u5, extended.small >> 10);
1518615162 const is_volatile = @truncate(u1, extended.small >> 15) != 0;
15187 const is_global_assembly = sema.func == null;
15163 const is_global_assembly = sema.func_index == .none;
1518815164
1518915165 const asm_source: []const u8 = if (tmpl_is_expr) blk: {
1519015166 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);
......@@ -15387,12 +15363,7 @@ fn zirCmpEq(
1538715363 if (lval.isUndef(mod) or rval.isUndef(mod)) {
1538815364 return sema.addConstUndef(Type.bool);
1538915365 }
15390 // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
15391 // or calling to Module.getErrorValue to get the values and then compare them is
15392 // faster.
15393 const lhs_name = lval.castTag(.@"error").?.data.name;
15394 const rhs_name = rval.castTag(.@"error").?.data.name;
15395 if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
15366 if (lval.toIntern() == rval.toIntern()) {
1539615367 return Air.Inst.Ref.bool_true;
1539715368 } else {
1539815369 return Air.Inst.Ref.bool_false;
......@@ -15650,8 +15621,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1565015621 .AnyFrame,
1565115622 => {},
1565215623 }
15653 const val = try ty.lazyAbiSize(mod, sema.arena);
15654 if (val.isLazySize()) {
15624 const val = try ty.lazyAbiSize(mod);
15625 if (val.isLazySize(mod)) {
1565515626 try sema.queueFullTypeResolution(ty);
1565615627 }
1565715628 return sema.addConstant(Type.comptime_int, val);
......@@ -15760,11 +15731,11 @@ fn zirClosureGet(
1576015731 scope = scope.parent.?;
1576115732 };
1576215733
15763 if (tv.val.ip_index == .unreachable_value and !block.is_typeof and sema.func == null) {
15734 if (tv.val.ip_index == .unreachable_value and !block.is_typeof and sema.func_index == .none) {
1576415735 const msg = msg: {
1576515736 const name = name: {
1576615737 const file = sema.owner_decl.getFileScope(mod);
15767 const tree = file.getTree(mod.gpa) catch |err| {
15738 const tree = file.getTree(sema.gpa) catch |err| {
1576815739 // In this case we emit a warning + a less precise source location.
1576915740 log.warn("unable to load {s}: {s}", .{
1577015741 file.sub_file_path, @errorName(err),
......@@ -15788,11 +15759,11 @@ fn zirClosureGet(
1578815759 return sema.failWithOwnedErrorMsg(msg);
1578915760 }
1579015761
15791 if (tv.val.ip_index == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) {
15762 if (tv.val.ip_index == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func_index != .none) {
1579215763 const msg = msg: {
1579315764 const name = name: {
1579415765 const file = sema.owner_decl.getFileScope(mod);
15795 const tree = file.getTree(mod.gpa) catch |err| {
15766 const tree = file.getTree(sema.gpa) catch |err| {
1579615767 // In this case we emit a warning + a less precise source location.
1579715768 log.warn("unable to load {s}: {s}", .{
1579815769 file.sub_file_path, @errorName(err),
......@@ -15868,14 +15839,17 @@ fn zirBuiltinSrc(
1586815839 const func_name_val = blk: {
1586915840 var anon_decl = try block.startAnonDecl();
1587015841 defer anon_decl.deinit();
15871 const name = std.mem.span(fn_owner_decl.name);
15842 const name = mem.span(fn_owner_decl.name);
1587215843 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
1587315844 const new_decl = try anon_decl.finish(
1587415845 try Type.array(anon_decl.arena(), bytes.len - 1, try mod.intValue(Type.u8, 0), Type.u8, mod),
1587515846 try Value.Tag.bytes.create(anon_decl.arena(), bytes),
1587615847 0, // default alignment
1587715848 );
15878 break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
15849 break :blk try mod.intern(.{ .ptr = .{
15850 .ty = .slice_const_u8_sentinel_0_type,
15851 .addr = .{ .decl = new_decl },
15852 } });
1587915853 };
1588015854
1588115855 const file_name_val = blk: {
......@@ -15888,27 +15862,35 @@ fn zirBuiltinSrc(
1588815862 try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
1588915863 0, // default alignment
1589015864 );
15891 break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
15865 break :blk try mod.intern(.{ .ptr = .{
15866 .ty = .slice_const_u8_sentinel_0_type,
15867 .addr = .{ .decl = new_decl },
15868 } });
1589215869 };
1589315870
15894 const field_values = try sema.arena.alloc(Value, 4);
15895 // file: [:0]const u8,
15896 field_values[0] = file_name_val;
15897 // fn_name: [:0]const u8,
15898 field_values[1] = func_name_val;
15899 // line: u32
15900 field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try mod.intValue(Type.u32, extra.line + 1));
15901 // column: u32,
15902 field_values[3] = try mod.intValue(Type.u32, extra.column + 1);
15903
15904 return sema.addConstant(
15905 try sema.getBuiltinType("SourceLocation"),
15906 try Value.Tag.aggregate.create(sema.arena, field_values),
15907 );
15871 const src_loc_ty = try sema.getBuiltinType("SourceLocation");
15872 const fields = .{
15873 // file: [:0]const u8,
15874 file_name_val,
15875 // fn_name: [:0]const u8,
15876 func_name_val,
15877 // line: u32,
15878 try mod.intern(.{ .runtime_value = .{
15879 .ty = .u32_type,
15880 .val = (try mod.intValue(Type.u32, extra.line + 1)).ip_index,
15881 } }),
15882 // column: u32,
15883 (try mod.intValue(Type.u32, extra.column + 1)).ip_index,
15884 };
15885 return sema.addConstant(src_loc_ty, (try mod.intern(.{ .aggregate = .{
15886 .ty = src_loc_ty.ip_index,
15887 .storage = .{ .elems = &fields },
15888 } })).toValue());
1590815889}
1590915890
1591015891fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1591115892 const mod = sema.mod;
15893 const gpa = sema.gpa;
1591215894 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1591315895 const src = inst_data.src();
1591415896 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
1591615898 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;
1591715899
1591815900 switch (ty.zigTypeTag(mod)) {
15919 .Type => return sema.addConstant(
15920 type_info_ty,
15921 try Value.Tag.@"union".create(sema.arena, .{
15922 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Type)),
15923 .val = Value.void,
15924 }),
15925 ),
15926 .Void => return sema.addConstant(
15927 type_info_ty,
15928 try Value.Tag.@"union".create(sema.arena, .{
15929 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Void)),
15930 .val = Value.void,
15931 }),
15932 ),
15933 .Bool => return sema.addConstant(
15934 type_info_ty,
15935 try Value.Tag.@"union".create(sema.arena, .{
15936 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Bool)),
15937 .val = Value.void,
15938 }),
15939 ),
15940 .NoReturn => return sema.addConstant(
15941 type_info_ty,
15942 try Value.Tag.@"union".create(sema.arena, .{
15943 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.NoReturn)),
15944 .val = Value.void,
15945 }),
15946 ),
15947 .ComptimeFloat => return sema.addConstant(
15948 type_info_ty,
15949 try Value.Tag.@"union".create(sema.arena, .{
15950 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ComptimeFloat)),
15951 .val = Value.void,
15952 }),
15953 ),
15954 .ComptimeInt => return sema.addConstant(
15955 type_info_ty,
15956 try Value.Tag.@"union".create(sema.arena, .{
15957 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ComptimeInt)),
15958 .val = Value.void,
15959 }),
15960 ),
15961 .Undefined => return sema.addConstant(
15962 type_info_ty,
15963 try Value.Tag.@"union".create(sema.arena, .{
15964 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Undefined)),
15965 .val = Value.void,
15966 }),
15967 ),
15968 .Null => return sema.addConstant(
15969 type_info_ty,
15970 try Value.Tag.@"union".create(sema.arena, .{
15971 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Null)),
15972 .val = Value.void,
15973 }),
15974 ),
15975 .EnumLiteral => return sema.addConstant(
15976 type_info_ty,
15977 try Value.Tag.@"union".create(sema.arena, .{
15978 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.EnumLiteral)),
15979 .val = Value.void,
15980 }),
15981 ),
15901 .Type,
15902 .Void,
15903 .Bool,
15904 .NoReturn,
15905 .ComptimeFloat,
15906 .ComptimeInt,
15907 .Undefined,
15908 .Null,
15909 .EnumLiteral,
15910 => |type_info_tag| return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
15911 .ty = type_info_ty.ip_index,
15912 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(type_info_tag))).ip_index,
15913 .val = .void_value,
15914 } })).toValue()),
1598215915 .Fn => {
1598315916 // TODO: look into memoizing this result.
1598415917 const info = mod.typeToFunc(ty).?;
......@@ -15986,11 +15919,34 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1598615919 var params_anon_decl = try block.startAnonDecl();
1598715920 defer params_anon_decl.deinit();
1598815921
15989 const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
15922 const fn_info_decl_index = (try sema.namespaceLookup(
15923 block,
15924 src,
15925 type_info_ty.getNamespaceIndex(mod).unwrap().?,
15926 "Fn",
15927 )).?;
15928 try mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
15929 try sema.ensureDeclAnalyzed(fn_info_decl_index);
15930 const fn_info_decl = mod.declPtr(fn_info_decl_index);
15931 const fn_info_ty = fn_info_decl.val.toType();
15932
15933 const param_info_decl_index = (try sema.namespaceLookup(
15934 block,
15935 src,
15936 fn_info_ty.getNamespaceIndex(mod).unwrap().?,
15937 "Param",
15938 )).?;
15939 try mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
15940 try sema.ensureDeclAnalyzed(param_info_decl_index);
15941 const param_info_decl = mod.declPtr(param_info_decl_index);
15942 const param_info_ty = param_info_decl.val.toType();
15943
15944 const param_vals = try gpa.alloc(InternPool.Index, info.param_types.len);
15945 defer gpa.free(param_vals);
1599015946 for (param_vals, info.param_types, 0..) |*param_val, param_ty, i| {
1599115947 const is_generic = param_ty == .generic_poison_type;
15992 const param_ty_val = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
15993 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
15948 const param_ty_val = try mod.intern_pool.get(gpa, .{ .opt = .{
15949 .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
1599415950 .val = if (is_generic) .none else param_ty,
1599515951 } });
1599615952
......@@ -15999,87 +15955,74 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1599915955 break :blk @truncate(u1, info.noalias_bits >> index) != 0;
1600015956 };
1600115957
16002 const param_fields = try params_anon_decl.arena().create([3]Value);
16003 param_fields.* = .{
15958 const param_fields = .{
1600415959 // is_generic: bool,
16005 Value.makeBool(is_generic),
15960 Value.makeBool(is_generic).ip_index,
1600615961 // is_noalias: bool,
16007 Value.makeBool(is_noalias),
15962 Value.makeBool(is_noalias).ip_index,
1600815963 // type: ?type,
16009 param_ty_val.toValue(),
15964 param_ty_val,
1601015965 };
16011 param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);
15966 param_val.* = try mod.intern(.{ .aggregate = .{
15967 .ty = param_info_ty.ip_index,
15968 .storage = .{ .elems = &param_fields },
15969 } });
1601215970 }
1601315971
1601415972 const args_val = v: {
16015 const fn_info_decl_index = (try sema.namespaceLookup(
16016 block,
16017 src,
16018 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16019 "Fn",
16020 )).?;
16021 try mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
16022 try sema.ensureDeclAnalyzed(fn_info_decl_index);
16023 const fn_info_decl = mod.declPtr(fn_info_decl_index);
16024 const fn_ty = fn_info_decl.val.toType();
16025 const param_info_decl_index = (try sema.namespaceLookup(
16026 block,
16027 src,
16028 fn_ty.getNamespaceIndex(mod).unwrap().?,
16029 "Param",
16030 )).?;
16031 try mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
16032 try sema.ensureDeclAnalyzed(param_info_decl_index);
16033 const param_info_decl = mod.declPtr(param_info_decl_index);
16034 const param_ty = param_info_decl.val.toType();
15973 const args_slice_ty = try mod.ptrType(.{
15974 .elem_type = param_info_ty.ip_index,
15975 .size = .Slice,
15976 .is_const = true,
15977 });
1603515978 const new_decl = try params_anon_decl.finish(
1603615979 try mod.arrayType(.{
1603715980 .len = param_vals.len,
16038 .child = param_ty.ip_index,
15981 .child = param_info_ty.ip_index,
1603915982 .sentinel = .none,
1604015983 }),
16041 try Value.Tag.aggregate.create(
16042 params_anon_decl.arena(),
16043 param_vals,
16044 ),
15984 (try mod.intern(.{ .aggregate = .{
15985 .ty = args_slice_ty.ip_index,
15986 .storage = .{ .elems = param_vals },
15987 } })).toValue(),
1604515988 0, // default alignment
1604615989 );
16047 break :v try Value.Tag.slice.create(sema.arena, .{
16048 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16049 .len = try mod.intValue(Type.usize, param_vals.len),
16050 });
15990 break :v try mod.intern(.{ .ptr = .{
15991 .ty = args_slice_ty.ip_index,
15992 .addr = .{ .decl = new_decl },
15993 .len = (try mod.intValue(Type.usize, param_vals.len)).ip_index,
15994 } });
1605115995 };
1605215996
16053 const ret_ty_opt = try mod.intern_pool.get(mod.gpa, .{ .opt = .{
16054 .ty = try mod.intern_pool.get(mod.gpa, .{ .opt_type = .type_type }),
15997 const ret_ty_opt = try mod.intern(.{ .opt = .{
15998 .ty = try mod.intern_pool.get(gpa, .{ .opt_type = .type_type }),
1605515999 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
1605616000 } });
1605716001
1605816002 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1605916003
16060 const field_values = try sema.arena.create([6]Value);
16061 field_values.* = .{
16004 const field_values = .{
1606216005 // calling_convention: CallingConvention,
16063 try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc)),
16006 (try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc))).ip_index,
1606416007 // alignment: comptime_int,
16065 try mod.intValue(Type.comptime_int, ty.abiAlignment(mod)),
16008 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).ip_index,
1606616009 // is_generic: bool,
16067 Value.makeBool(info.is_generic),
16010 Value.makeBool(info.is_generic).ip_index,
1606816011 // is_var_args: bool,
16069 Value.makeBool(info.is_var_args),
16012 Value.makeBool(info.is_var_args).ip_index,
1607016013 // return_type: ?type,
16071 ret_ty_opt.toValue(),
16014 ret_ty_opt,
1607216015 // args: []const Fn.Param,
1607316016 args_val,
1607416017 };
16075
16076 return sema.addConstant(
16077 type_info_ty,
16078 try Value.Tag.@"union".create(sema.arena, .{
16079 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn)),
16080 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16081 }),
16082 );
16018 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16019 .ty = type_info_ty.ip_index,
16020 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn))).ip_index,
16021 .val = try mod.intern(.{ .aggregate = .{
16022 .ty = fn_info_ty.ip_index,
16023 .storage = .{ .elems = &field_values },
16024 } }),
16025 } })).toValue());
1608316026 },
1608416027 .Int => {
1608516028 const signedness_ty = try sema.getBuiltinType("Signedness");
......@@ -16099,24 +16042,36 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1609916042 );
1610016043 },
1610116044 .Float => {
16102 const field_values = try sema.arena.alloc(Value, 1);
16103 // bits: u16,
16104 field_values[0] = try mod.intValue(Type.u16, ty.bitSize(mod));
16105
16106 return sema.addConstant(
16107 type_info_ty,
16108 try Value.Tag.@"union".create(sema.arena, .{
16109 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float)),
16110 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16111 }),
16112 );
16045 const float_info_decl_index = (try sema.namespaceLookup(
16046 block,
16047 src,
16048 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16049 "Float",
16050 )).?;
16051 try mod.declareDeclDependency(sema.owner_decl_index, float_info_decl_index);
16052 try sema.ensureDeclAnalyzed(float_info_decl_index);
16053 const float_info_decl = mod.declPtr(float_info_decl_index);
16054 const float_ty = float_info_decl.val.toType();
16055
16056 const field_vals = .{
16057 // bits: u16,
16058 (try mod.intValue(Type.u16, ty.bitSize(mod))).ip_index,
16059 };
16060 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16061 .ty = type_info_ty.ip_index,
16062 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float))).ip_index,
16063 .val = try mod.intern(.{ .aggregate = .{
16064 .ty = float_ty.ip_index,
16065 .storage = .{ .elems = &field_vals },
16066 } }),
16067 } })).toValue());
1611316068 },
1611416069 .Pointer => {
1611516070 const info = ty.ptrInfo(mod);
1611616071 const alignment = if (info.@"align" != 0)
1611716072 try mod.intValue(Type.comptime_int, info.@"align")
1611816073 else
16119 try info.pointee_type.lazyAbiAlignment(mod, sema.arena);
16074 try info.pointee_type.lazyAbiAlignment(mod);
1612016075
1612116076 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
1612216077 const pointer_ty = t: {
......@@ -16245,9 +16200,10 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1624516200 // Build our list of Error values
1624616201 // Optional value is only null if anyerror
1624716202 // Value can be zero-length slice otherwise
16248 const error_field_vals: ?[]Value = if (ty.isAnyError(mod)) null else blk: {
16203 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
1624916204 const names = ty.errorSetNames(mod);
16250 const vals = try fields_anon_decl.arena().alloc(Value, names.len);
16205 const vals = try gpa.alloc(InternPool.Index, names.len);
16206 defer gpa.free(vals);
1625116207 for (vals, names) |*field_val, name_ip| {
1625216208 const name = mod.intern_pool.stringToSlice(name_ip);
1625316209 const name_val = v: {
......@@ -16259,70 +16215,91 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1625916215 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1626016216 0, // default alignment
1626116217 );
16262 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16218 break :v try mod.intern(.{ .ptr = .{
16219 .ty = .slice_const_u8_type,
16220 .addr = .{ .decl = new_decl },
16221 } });
1626316222 };
1626416223
16265 const error_field_fields = try fields_anon_decl.arena().create([1]Value);
16266 error_field_fields.* = .{
16224 const error_field_fields = .{
1626716225 // name: []const u8,
1626816226 name_val,
1626916227 };
16270
16271 field_val.* = try Value.Tag.aggregate.create(
16272 fields_anon_decl.arena(),
16273 error_field_fields,
16274 );
16228 field_val.* = try mod.intern(.{ .aggregate = .{
16229 .ty = error_field_ty.ip_index,
16230 .storage = .{ .elems = &error_field_fields },
16231 } });
1627516232 }
1627616233
1627716234 break :blk vals;
1627816235 };
1627916236
1628016237 // Build our ?[]const Error value
16281 const errors_val = if (error_field_vals) |vals| v: {
16238 const slice_errors_ty = try mod.ptrType(.{
16239 .elem_type = error_field_ty.ip_index,
16240 .size = .Slice,
16241 .is_const = true,
16242 });
16243 const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.ip_index);
16244 const errors_payload_val: InternPool.Index = if (error_field_vals) |vals| v: {
16245 const array_errors_ty = try mod.arrayType(.{
16246 .len = vals.len,
16247 .child = error_field_ty.ip_index,
16248 .sentinel = .none,
16249 });
1628216250 const new_decl = try fields_anon_decl.finish(
16283 try mod.arrayType(.{
16284 .len = vals.len,
16285 .child = error_field_ty.ip_index,
16286 .sentinel = .none,
16287 }),
16288 try Value.Tag.aggregate.create(
16289 fields_anon_decl.arena(),
16290 vals,
16291 ),
16251 array_errors_ty,
16252 (try mod.intern(.{ .aggregate = .{
16253 .ty = array_errors_ty.ip_index,
16254 .storage = .{ .elems = vals },
16255 } })).toValue(),
1629216256 0, // default alignment
1629316257 );
16294
16295 const new_decl_val = try Value.Tag.decl_ref.create(sema.arena, new_decl);
16296 const slice_val = try Value.Tag.slice.create(sema.arena, .{
16297 .ptr = new_decl_val,
16298 .len = try mod.intValue(Type.usize, vals.len),
16299 });
16300 break :v try Value.Tag.opt_payload.create(sema.arena, slice_val);
16301 } else Value.null;
16258 break :v try mod.intern(.{ .ptr = .{
16259 .ty = slice_errors_ty.ip_index,
16260 .addr = .{ .decl = new_decl },
16261 } });
16262 } else .none;
16263 const errors_val = try mod.intern(.{ .opt = .{
16264 .ty = opt_slice_errors_ty.ip_index,
16265 .val = errors_payload_val,
16266 } });
1630216267
1630316268 // Construct Type{ .ErrorSet = errors_val }
16304 return sema.addConstant(
16305 type_info_ty,
16306 try Value.Tag.@"union".create(sema.arena, .{
16307 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet)),
16308 .val = errors_val,
16309 }),
16310 );
16269 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16270 .ty = type_info_ty.ip_index,
16271 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet))).ip_index,
16272 .val = errors_val,
16273 } })).toValue());
1631116274 },
1631216275 .ErrorUnion => {
16313 const field_values = try sema.arena.alloc(Value, 2);
16314 // error_set: type,
16315 field_values[0] = ty.errorUnionSet(mod).toValue();
16316 // payload: type,
16317 field_values[1] = ty.errorUnionPayload(mod).toValue();
16276 const error_union_field_ty = t: {
16277 const error_union_field_ty_decl_index = (try sema.namespaceLookup(
16278 block,
16279 src,
16280 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16281 "ErrorUnion",
16282 )).?;
16283 try mod.declareDeclDependency(sema.owner_decl_index, error_union_field_ty_decl_index);
16284 try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index);
16285 const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index);
16286 break :t error_union_field_ty_decl.val.toType();
16287 };
1631816288
16319 return sema.addConstant(
16320 type_info_ty,
16321 try Value.Tag.@"union".create(sema.arena, .{
16322 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion)),
16323 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16324 }),
16325 );
16289 const field_values = .{
16290 // error_set: type,
16291 ty.errorUnionSet(mod).ip_index,
16292 // payload: type,
16293 ty.errorUnionPayload(mod).ip_index,
16294 };
16295 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16296 .ty = type_info_ty.ip_index,
16297 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion))).ip_index,
16298 .val = try mod.intern(.{ .aggregate = .{
16299 .ty = error_union_field_ty.ip_index,
16300 .storage = .{ .elems = &field_values },
16301 } }),
16302 } })).toValue());
1632616303 },
1632716304 .Enum => {
1632816305 // TODO: look into memoizing this result.
......@@ -16346,7 +16323,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1634616323 break :t enum_field_ty_decl.val.toType();
1634716324 };
1634816325
16349 const enum_field_vals = try fields_anon_decl.arena().alloc(Value, enum_type.names.len);
16326 const enum_field_vals = try gpa.alloc(InternPool.Index, enum_type.names.len);
16327 defer gpa.free(enum_field_vals);
1635016328
1635116329 for (enum_field_vals, 0..) |*field_val, i| {
1635216330 const name_ip = enum_type.names[i];
......@@ -16360,56 +16338,81 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1636016338 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1636116339 0, // default alignment
1636216340 );
16363 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16341 break :v try mod.intern(.{ .ptr = .{
16342 .ty = .slice_const_u8_type,
16343 .addr = .{ .decl = new_decl },
16344 } });
1636416345 };
1636516346
16366 const enum_field_fields = try fields_anon_decl.arena().create([2]Value);
16367 enum_field_fields.* = .{
16347 const enum_field_fields = .{
1636816348 // name: []const u8,
1636916349 name_val,
1637016350 // value: comptime_int,
16371 try mod.intValue(Type.comptime_int, i),
16351 (try mod.intValue(Type.comptime_int, i)).ip_index,
1637216352 };
16373 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), enum_field_fields);
16353 field_val.* = try mod.intern(.{ .aggregate = .{
16354 .ty = enum_field_ty.ip_index,
16355 .storage = .{ .elems = &enum_field_fields },
16356 } });
1637416357 }
1637516358
1637616359 const fields_val = v: {
16360 const fields_array_ty = try mod.arrayType(.{
16361 .len = enum_field_vals.len,
16362 .child = enum_field_ty.ip_index,
16363 .sentinel = .none,
16364 });
1637716365 const new_decl = try fields_anon_decl.finish(
16378 try mod.arrayType(.{
16379 .len = enum_field_vals.len,
16380 .child = enum_field_ty.ip_index,
16381 .sentinel = .none,
16382 }),
16383 try Value.Tag.aggregate.create(
16384 fields_anon_decl.arena(),
16385 enum_field_vals,
16386 ),
16366 fields_array_ty,
16367 (try mod.intern(.{ .aggregate = .{
16368 .ty = fields_array_ty.ip_index,
16369 .storage = .{ .elems = enum_field_vals },
16370 } })).toValue(),
1638716371 0, // default alignment
1638816372 );
16389 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
16373 break :v try mod.intern(.{ .ptr = .{
16374 .ty = (try mod.ptrType(.{
16375 .elem_type = enum_field_ty.ip_index,
16376 .size = .Slice,
16377 .is_const = true,
16378 })).ip_index,
16379 .addr = .{ .decl = new_decl },
16380 } });
1639016381 };
1639116382
1639216383 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, enum_type.namespace);
1639316384
16394 const field_values = try sema.arena.create([4]Value);
16395 field_values.* = .{
16385 const type_enum_ty = t: {
16386 const type_enum_ty_decl_index = (try sema.namespaceLookup(
16387 block,
16388 src,
16389 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16390 "Enum",
16391 )).?;
16392 try mod.declareDeclDependency(sema.owner_decl_index, type_enum_ty_decl_index);
16393 try sema.ensureDeclAnalyzed(type_enum_ty_decl_index);
16394 const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index);
16395 break :t type_enum_ty_decl.val.toType();
16396 };
16397
16398 const field_values = .{
1639616399 // tag_type: type,
16397 enum_type.tag_ty.toValue(),
16400 enum_type.tag_ty,
1639816401 // fields: []const EnumField,
1639916402 fields_val,
1640016403 // decls: []const Declaration,
1640116404 decls_val,
1640216405 // is_exhaustive: bool,
16403 is_exhaustive,
16406 is_exhaustive.ip_index,
1640416407 };
16405
16406 return sema.addConstant(
16407 type_info_ty,
16408 try Value.Tag.@"union".create(sema.arena, .{
16409 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum)),
16410 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16411 }),
16412 );
16408 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16409 .ty = type_info_ty.ip_index,
16410 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum))).ip_index,
16411 .val = try mod.intern(.{ .aggregate = .{
16412 .ty = type_enum_ty.ip_index,
16413 .storage = .{ .elems = &field_values },
16414 } }),
16415 } })).toValue());
1641316416 },
1641416417 .Union => {
1641516418 // TODO: look into memoizing this result.
......@@ -16417,6 +16420,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1641716420 var fields_anon_decl = try block.startAnonDecl();
1641816421 defer fields_anon_decl.deinit();
1641916422
16423 const type_union_ty = t: {
16424 const type_union_ty_decl_index = (try sema.namespaceLookup(
16425 block,
16426 src,
16427 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16428 "Union",
16429 )).?;
16430 try mod.declareDeclDependency(sema.owner_decl_index, type_union_ty_decl_index);
16431 try sema.ensureDeclAnalyzed(type_union_ty_decl_index);
16432 const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index);
16433 break :t type_union_ty_decl.val.toType();
16434 };
16435
1642016436 const union_field_ty = t: {
1642116437 const union_field_ty_decl_index = (try sema.namespaceLookup(
1642216438 block,
......@@ -16435,7 +16451,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1643516451 const layout = union_ty.containerLayout(mod);
1643616452
1643716453 const union_fields = union_ty.unionFields(mod);
16438 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());
16454 const union_field_vals = try gpa.alloc(InternPool.Index, union_fields.count());
16455 defer gpa.free(union_field_vals);
1643916456
1644016457 for (union_field_vals, 0..) |*field_val, i| {
1644116458 const field = union_fields.values()[i];
......@@ -16449,51 +16466,62 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1644916466 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1645016467 0, // default alignment
1645116468 );
16452 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16469 break :v try mod.intern(.{ .ptr = .{
16470 .ty = .slice_const_u8_type,
16471 .addr = .{ .decl = new_decl },
16472 } });
1645316473 };
1645416474
16455 const union_field_fields = try fields_anon_decl.arena().create([3]Value);
1645616475 const alignment = switch (layout) {
1645716476 .Auto, .Extern => try sema.unionFieldAlignment(field),
1645816477 .Packed => 0,
1645916478 };
1646016479
16461 union_field_fields.* = .{
16480 const union_field_fields = .{
1646216481 // name: []const u8,
1646316482 name_val,
1646416483 // type: type,
16465 field.ty.toValue(),
16484 field.ty.ip_index,
1646616485 // alignment: comptime_int,
16467 try mod.intValue(Type.comptime_int, alignment),
16486 (try mod.intValue(Type.comptime_int, alignment)).ip_index,
1646816487 };
16469 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), union_field_fields);
16488 field_val.* = try mod.intern(.{ .aggregate = .{
16489 .ty = union_field_ty.ip_index,
16490 .storage = .{ .elems = &union_field_fields },
16491 } });
1647016492 }
1647116493
1647216494 const fields_val = v: {
16495 const array_fields_ty = try mod.arrayType(.{
16496 .len = union_field_vals.len,
16497 .child = union_field_ty.ip_index,
16498 .sentinel = .none,
16499 });
1647316500 const new_decl = try fields_anon_decl.finish(
16474 try mod.arrayType(.{
16475 .len = union_field_vals.len,
16476 .child = union_field_ty.ip_index,
16477 .sentinel = .none,
16478 }),
16479 try Value.Tag.aggregate.create(
16480 fields_anon_decl.arena(),
16481 try fields_anon_decl.arena().dupe(Value, union_field_vals),
16482 ),
16501 array_fields_ty,
16502 (try mod.intern(.{ .aggregate = .{
16503 .ty = array_fields_ty.ip_index,
16504 .storage = .{ .elems = union_field_vals },
16505 } })).toValue(),
1648316506 0, // default alignment
1648416507 );
16485 break :v try Value.Tag.slice.create(sema.arena, .{
16486 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16487 .len = try mod.intValue(Type.usize, union_field_vals.len),
16488 });
16508 break :v try mod.intern(.{ .ptr = .{
16509 .ty = (try mod.ptrType(.{
16510 .elem_type = union_field_ty.ip_index,
16511 .size = .Slice,
16512 .is_const = true,
16513 })).ip_index,
16514 .addr = .{ .decl = new_decl },
16515 .len = (try mod.intValue(Type.usize, union_field_vals.len)).ip_index,
16516 } });
1648916517 };
1649016518
1649116519 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespaceIndex(mod));
1649216520
16493 const enum_tag_ty_val = if (union_ty.unionTagType(mod)) |tag_ty| v: {
16494 const ty_val = tag_ty.toValue();
16495 break :v try Value.Tag.opt_payload.create(sema.arena, ty_val);
16496 } else Value.null;
16521 const enum_tag_ty_val = try mod.intern(.{ .opt = .{
16522 .ty = (try mod.optionalType(.type_type)).ip_index,
16523 .val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.ip_index else .none,
16524 } });
1649716525
1649816526 const container_layout_ty = t: {
1649916527 const decl_index = (try sema.namespaceLookup(
......@@ -16508,10 +16536,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1650816536 break :t decl.val.toType();
1650916537 };
1651016538
16511 const field_values = try sema.arena.create([4]Value);
16512 field_values.* = .{
16539 const field_values = .{
1651316540 // layout: ContainerLayout,
16514 try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),
16541 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
1651516542
1651616543 // tag_type: ?type,
1651716544 enum_tag_ty_val,
......@@ -16520,14 +16547,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1652016547 // decls: []const Declaration,
1652116548 decls_val,
1652216549 };
16523
16524 return sema.addConstant(
16525 type_info_ty,
16526 try Value.Tag.@"union".create(sema.arena, .{
16527 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union)),
16528 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16529 }),
16530 );
16550 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16551 .ty = type_info_ty.ip_index,
16552 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union))).ip_index,
16553 .val = try mod.intern(.{ .aggregate = .{
16554 .ty = type_union_ty.ip_index,
16555 .storage = .{ .elems = &field_values },
16556 } }),
16557 } })).toValue());
1653116558 },
1653216559 .Struct => {
1653316560 // TODO: look into memoizing this result.
......@@ -16535,6 +16562,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1653516562 var fields_anon_decl = try block.startAnonDecl();
1653616563 defer fields_anon_decl.deinit();
1653716564
16565 const type_struct_ty = t: {
16566 const type_struct_ty_decl_index = (try sema.namespaceLookup(
16567 block,
16568 src,
16569 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16570 "Struct",
16571 )).?;
16572 try mod.declareDeclDependency(sema.owner_decl_index, type_struct_ty_decl_index);
16573 try sema.ensureDeclAnalyzed(type_struct_ty_decl_index);
16574 const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index);
16575 break :t type_struct_ty_decl.val.toType();
16576 };
16577
1653816578 const struct_field_ty = t: {
1653916579 const struct_field_ty_decl_index = (try sema.namespaceLookup(
1654016580 block,
......@@ -16547,14 +16587,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1654716587 const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
1654816588 break :t struct_field_ty_decl.val.toType();
1654916589 };
16590
1655016591 const struct_ty = try sema.resolveTypeFields(ty);
1655116592 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
1655216593 const layout = struct_ty.containerLayout(mod);
1655316594
16554 const struct_field_vals = fv: {
16595 var struct_field_vals: []InternPool.Index = &.{};
16596 defer gpa.free(struct_field_vals);
16597 fv: {
1655516598 const struct_type = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
1655616599 .anon_struct_type => |tuple| {
16557 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, tuple.types.len);
16600 struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);
1655816601 for (
1655916602 tuple.types,
1656016603 tuple.values,
......@@ -16574,38 +16617,40 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1657416617 try Value.Tag.bytes.create(anon_decl.arena(), bytes.ptr[0 .. bytes.len + 1]),
1657516618 0, // default alignment
1657616619 );
16577 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16578 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16579 .len = try mod.intValue(Type.usize, bytes.len),
16580 });
16620 break :v try mod.intern(.{ .ptr = .{
16621 .ty = .slice_const_u8_type,
16622 .addr = .{ .decl = new_decl },
16623 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16624 } });
1658116625 };
1658216626
16583 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
1658416627 const is_comptime = field_val != .none;
1658516628 const opt_default_val = if (is_comptime) field_val.toValue() else null;
1658616629 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
16587 struct_field_fields.* = .{
16630 const struct_field_fields = .{
1658816631 // name: []const u8,
1658916632 name_val,
1659016633 // type: type,
16591 field_ty.toValue(),
16634 field_ty,
1659216635 // default_value: ?*const anyopaque,
16593 try default_val_ptr.copy(fields_anon_decl.arena()),
16636 default_val_ptr.ip_index,
1659416637 // is_comptime: bool,
16595 Value.makeBool(is_comptime),
16638 Value.makeBool(is_comptime).ip_index,
1659616639 // alignment: comptime_int,
16597 try field_ty.toType().lazyAbiAlignment(mod, fields_anon_decl.arena()),
16640 (try mod.intValue(Type.comptime_int, field_ty.toType().abiAlignment(mod))).ip_index,
1659816641 };
16599 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16642 struct_field_val.* = try mod.intern(.{ .aggregate = .{
16643 .ty = struct_field_ty.ip_index,
16644 .storage = .{ .elems = &struct_field_fields },
16645 } });
1660016646 }
16601 break :fv struct_field_vals;
16647 break :fv;
1660216648 },
1660316649 .struct_type => |s| s,
1660416650 else => unreachable,
1660516651 };
16606 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
16607 break :fv &[0]Value{};
16608 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_obj.fields.count());
16652 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :fv;
16653 struct_field_vals = try gpa.alloc(InternPool.Index, struct_obj.fields.count());
1660916654
1661016655 for (
1661116656 struct_field_vals,
......@@ -16621,13 +16666,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1662116666 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1662216667 0, // default alignment
1662316668 );
16624 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16625 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16626 .len = try mod.intValue(Type.usize, bytes.len),
16627 });
16669 break :v try mod.intern(.{ .ptr = .{
16670 .ty = .slice_const_u8_type,
16671 .addr = .{ .decl = new_decl },
16672 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16673 } });
1662816674 };
1662916675
16630 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
1663116676 const opt_default_val = if (field.default_val.ip_index == .unreachable_value)
1663216677 null
1663316678 else
......@@ -16635,55 +16680,61 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1663516680 const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);
1663616681 const alignment = field.alignment(mod, layout);
1663716682
16638 struct_field_fields.* = .{
16683 const struct_field_fields = .{
1663916684 // name: []const u8,
1664016685 name_val,
1664116686 // type: type,
16642 field.ty.toValue(),
16687 field.ty.ip_index,
1664316688 // default_value: ?*const anyopaque,
16644 try default_val_ptr.copy(fields_anon_decl.arena()),
16689 default_val_ptr.ip_index,
1664516690 // is_comptime: bool,
16646 Value.makeBool(field.is_comptime),
16691 Value.makeBool(field.is_comptime).ip_index,
1664716692 // alignment: comptime_int,
16648 try mod.intValue(Type.comptime_int, alignment),
16693 (try mod.intValue(Type.comptime_int, alignment)).ip_index,
1664916694 };
16650 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16695 field_val.* = try mod.intern(.{ .aggregate = .{
16696 .ty = struct_field_ty.ip_index,
16697 .storage = .{ .elems = &struct_field_fields },
16698 } });
1665116699 }
16652 break :fv struct_field_vals;
16653 };
16700 }
1665416701
1665516702 const fields_val = v: {
16703 const array_fields_ty = try mod.arrayType(.{
16704 .len = struct_field_vals.len,
16705 .child = struct_field_ty.ip_index,
16706 .sentinel = .none,
16707 });
1665616708 const new_decl = try fields_anon_decl.finish(
16657 try mod.arrayType(.{
16658 .len = struct_field_vals.len,
16659 .child = struct_field_ty.ip_index,
16660 .sentinel = .none,
16661 }),
16662 try Value.Tag.aggregate.create(
16663 fields_anon_decl.arena(),
16664 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
16665 ),
16709 array_fields_ty,
16710 (try mod.intern(.{ .aggregate = .{
16711 .ty = array_fields_ty.ip_index,
16712 .storage = .{ .elems = struct_field_vals },
16713 } })).toValue(),
1666616714 0, // default alignment
1666716715 );
16668 break :v try Value.Tag.slice.create(sema.arena, .{
16669 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16670 .len = try mod.intValue(Type.usize, struct_field_vals.len),
16671 });
16716 break :v try mod.intern(.{ .ptr = .{
16717 .ty = (try mod.ptrType(.{
16718 .elem_type = struct_field_ty.ip_index,
16719 .size = .Slice,
16720 .is_const = true,
16721 })).ip_index,
16722 .addr = .{ .decl = new_decl },
16723 .len = (try mod.intValue(Type.usize, struct_field_vals.len)).ip_index,
16724 } });
1667216725 };
1667316726
1667416727 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));
1667516728
16676 const backing_integer_val = blk: {
16677 if (layout == .Packed) {
16729 const backing_integer_val = try mod.intern(.{ .opt = .{
16730 .ty = (try mod.optionalType(.type_type)).ip_index,
16731 .val = if (layout == .Packed) val: {
1667816732 const struct_obj = mod.typeToStruct(struct_ty).?;
1667916733 assert(struct_obj.haveLayout());
1668016734 assert(struct_obj.backing_int_ty.isInt(mod));
16681 const backing_int_ty_val = struct_obj.backing_int_ty.toValue();
16682 break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);
16683 } else {
16684 break :blk Value.null;
16685 }
16686 };
16735 break :val struct_obj.backing_int_ty.ip_index;
16736 } else .none,
16737 } });
1668716738
1668816739 const container_layout_ty = t: {
1668916740 const decl_index = (try sema.namespaceLookup(
......@@ -16698,10 +16749,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1669816749 break :t decl.val.toType();
1669916750 };
1670016751
16701 const field_values = try sema.arena.create([5]Value);
16702 field_values.* = .{
16752 const field_values = [_]InternPool.Index{
1670316753 // layout: ContainerLayout,
16704 try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout)),
16754 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).ip_index,
1670516755 // backing_integer: ?type,
1670616756 backing_integer_val,
1670716757 // fields: []const StructField,
......@@ -16709,36 +16759,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1670916759 // decls: []const Declaration,
1671016760 decls_val,
1671116761 // is_tuple: bool,
16712 Value.makeBool(struct_ty.isTuple(mod)),
16762 Value.makeBool(struct_ty.isTuple(mod)).ip_index,
1671316763 };
16714
16715 return sema.addConstant(
16716 type_info_ty,
16717 try Value.Tag.@"union".create(sema.arena, .{
16718 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct)),
16719 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16720 }),
16721 );
16764 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16765 .ty = type_info_ty.ip_index,
16766 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct))).ip_index,
16767 .val = try mod.intern(.{ .aggregate = .{
16768 .ty = type_struct_ty.ip_index,
16769 .storage = .{ .elems = &field_values },
16770 } }),
16771 } })).toValue());
1672216772 },
1672316773 .Opaque => {
1672416774 // TODO: look into memoizing this result.
1672516775
16776 const type_opaque_ty = t: {
16777 const type_opaque_ty_decl_index = (try sema.namespaceLookup(
16778 block,
16779 src,
16780 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16781 "Opaque",
16782 )).?;
16783 try mod.declareDeclDependency(sema.owner_decl_index, type_opaque_ty_decl_index);
16784 try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index);
16785 const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index);
16786 break :t type_opaque_ty_decl.val.toType();
16787 };
16788
1672616789 const opaque_ty = try sema.resolveTypeFields(ty);
1672716790 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespaceIndex(mod));
1672816791
16729 const field_values = try sema.arena.create([1]Value);
16730 field_values.* = .{
16792 const field_values = .{
1673116793 // decls: []const Declaration,
1673216794 decls_val,
1673316795 };
16734
16735 return sema.addConstant(
16736 type_info_ty,
16737 try Value.Tag.@"union".create(sema.arena, .{
16738 .tag = try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque)),
16739 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16740 }),
16741 );
16796 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16797 .ty = type_info_ty.ip_index,
16798 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque))).ip_index,
16799 .val = try mod.intern(.{ .aggregate = .{
16800 .ty = type_opaque_ty.ip_index,
16801 .storage = .{ .elems = &field_values },
16802 } }),
16803 } })).toValue());
1674216804 },
1674316805 .Frame => return sema.failWithUseOfAsync(block, src),
1674416806 .AnyFrame => return sema.failWithUseOfAsync(block, src),
......@@ -16751,7 +16813,7 @@ fn typeInfoDecls(
1675116813 src: LazySrcLoc,
1675216814 type_info_ty: Type,
1675316815 opt_namespace: Module.Namespace.OptionalIndex,
16754) CompileError!Value {
16816) CompileError!InternPool.Index {
1675516817 const mod = sema.mod;
1675616818 var decls_anon_decl = try block.startAnonDecl();
1675716819 defer decls_anon_decl.deinit();
......@@ -16770,7 +16832,7 @@ fn typeInfoDecls(
1677016832 };
1677116833 try sema.queueFullTypeResolution(declaration_ty);
1677216834
16773 var decl_vals = std.ArrayList(Value).init(sema.gpa);
16835 var decl_vals = std.ArrayList(InternPool.Index).init(sema.gpa);
1677416836 defer decl_vals.deinit();
1677516837
1677616838 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
......@@ -16778,33 +16840,39 @@ fn typeInfoDecls(
1677816840
1677916841 if (opt_namespace.unwrap()) |namespace_index| {
1678016842 const namespace = mod.namespacePtr(namespace_index);
16781 try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), namespace, &decl_vals, &seen_namespaces);
16843 try sema.typeInfoNamespaceDecls(block, namespace, declaration_ty, &decl_vals, &seen_namespaces);
1678216844 }
1678316845
16846 const array_decl_ty = try mod.arrayType(.{
16847 .len = decl_vals.items.len,
16848 .child = declaration_ty.ip_index,
16849 .sentinel = .none,
16850 });
1678416851 const new_decl = try decls_anon_decl.finish(
16785 try mod.arrayType(.{
16786 .len = decl_vals.items.len,
16787 .child = declaration_ty.ip_index,
16788 .sentinel = .none,
16789 }),
16790 try Value.Tag.aggregate.create(
16791 decls_anon_decl.arena(),
16792 try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16793 ),
16852 array_decl_ty,
16853 (try mod.intern(.{ .aggregate = .{
16854 .ty = array_decl_ty.ip_index,
16855 .storage = .{ .elems = decl_vals.items },
16856 } })).toValue(),
1679416857 0, // default alignment
1679516858 );
16796 return try Value.Tag.slice.create(sema.arena, .{
16797 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16798 .len = try mod.intValue(Type.usize, decl_vals.items.len),
16799 });
16859 return try mod.intern(.{ .ptr = .{
16860 .ty = (try mod.ptrType(.{
16861 .elem_type = declaration_ty.ip_index,
16862 .size = .Slice,
16863 .is_const = true,
16864 })).ip_index,
16865 .addr = .{ .decl = new_decl },
16866 .len = (try mod.intValue(Type.usize, decl_vals.items.len)).ip_index,
16867 } });
1680016868}
1680116869
1680216870fn typeInfoNamespaceDecls(
1680316871 sema: *Sema,
1680416872 block: *Block,
16805 decls_anon_decl: Allocator,
1680616873 namespace: *Namespace,
16807 decl_vals: *std.ArrayList(Value),
16874 declaration_ty: Type,
16875 decl_vals: *std.ArrayList(InternPool.Index),
1680816876 seen_namespaces: *std.AutoHashMap(*Namespace, void),
1680916877) !void {
1681016878 const mod = sema.mod;
......@@ -16817,7 +16885,7 @@ fn typeInfoNamespaceDecls(
1681716885 if (decl.analysis == .in_progress) continue;
1681816886 try mod.ensureDeclAnalyzed(decl_index);
1681916887 const new_ns = decl.val.toType().getNamespace(mod).?;
16820 try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
16888 try sema.typeInfoNamespaceDecls(block, new_ns, declaration_ty, decl_vals, seen_namespaces);
1682116889 continue;
1682216890 }
1682316891 if (decl.kind != .named) continue;
......@@ -16830,20 +16898,23 @@ fn typeInfoNamespaceDecls(
1683016898 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
1683116899 0, // default alignment
1683216900 );
16833 break :v try Value.Tag.slice.create(decls_anon_decl, .{
16834 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
16835 .len = try mod.intValue(Type.usize, bytes.len),
16836 });
16901 break :v try mod.intern(.{ .ptr = .{
16902 .ty = .slice_const_u8_type,
16903 .addr = .{ .decl = new_decl },
16904 .len = (try mod.intValue(Type.usize, bytes.len)).ip_index,
16905 } });
1683716906 };
1683816907
16839 const fields = try decls_anon_decl.create([2]Value);
16840 fields.* = .{
16908 const fields = .{
1684116909 //name: []const u8,
1684216910 name_val,
1684316911 //is_pub: bool,
16844 Value.makeBool(decl.is_pub),
16912 Value.makeBool(decl.is_pub).ip_index,
1684516913 };
16846 try decl_vals.append(try Value.Tag.aggregate.create(decls_anon_decl, fields));
16914 try decl_vals.append(try mod.intern(.{ .aggregate = .{
16915 .ty = declaration_ty.ip_index,
16916 .storage = .{ .elems = &fields },
16917 } }));
1684716918 }
1684816919}
1684916920
......@@ -17454,10 +17525,11 @@ fn zirRetErrValue(
1745417525
1745517526 // Return the error code from the function.
1745617527 const kv = try mod.getErrorValue(err_name);
17457 const result_inst = try sema.addConstant(
17458 try mod.singleErrorSetType(err_name),
17459 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
17460 );
17528 const error_set_type = try mod.singleErrorSetType(err_name);
17529 const result_inst = try sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
17530 .ty = error_set_type.ip_index,
17531 .name = try mod.intern_pool.getOrPutString(sema.gpa, kv.key),
17532 } })).toValue());
1746117533 return sema.analyzeRet(block, result_inst, src);
1746217534}
1746317535
......@@ -17782,10 +17854,12 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1778217854 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");
1778317855 // Check if this happens to be the lazy alignment of our element type, in
1778417856 // which case we can make this 0 without resolving it.
17785 if (val.castTag(.lazy_align)) |payload| {
17786 if (payload.data.eql(elem_ty, sema.mod)) {
17787 break :blk .none;
17788 }
17857 switch (mod.intern_pool.indexToKey(val.ip_index)) {
17858 .int => |int| switch (int.storage) {
17859 .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.ip_index) break :blk .none,
17860 else => {},
17861 },
17862 else => {},
1778917863 }
1779017864 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);
1779117865 try sema.validateAlign(block, align_src, abi_align);
......@@ -17910,12 +17984,10 @@ fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) Com
1791017984 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});
1791117985 }
1791217986 }
17913 if (obj_ty.sentinel(mod)) |sentinel| {
17914 const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);
17915 return sema.addConstant(obj_ty, val);
17916 } else {
17917 return sema.addConstant(obj_ty, Value.initTag(.empty_array));
17918 }
17987 return sema.addConstant(obj_ty, (try mod.intern(.{ .aggregate = .{
17988 .ty = obj_ty.ip_index,
17989 .storage = .{ .elems = &.{} },
17990 } })).toValue());
1791917991}
1792017992
1792117993fn 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
1867918751 if (ty.isNoReturn(mod)) {
1868018752 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
1868118753 }
18682 const val = try ty.lazyAbiAlignment(mod, sema.arena);
18683 if (val.isLazyAlign()) {
18754 const val = try ty.lazyAbiAlignment(mod);
18755 if (val.isLazyAlign(mod)) {
1868418756 try sema.queueFullTypeResolution(ty);
1868518757 }
1868618758 return sema.addConstant(Type.comptime_int, val);
......@@ -18704,7 +18776,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1870418776 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1870518777
1870618778 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
18707 const bytes = val.castTag(.@"error").?.data.name;
18779 const err_name = sema.mod.intern_pool.indexToKey(val.ip_index).err.name;
18780 const bytes = sema.mod.intern_pool.stringToSlice(err_name);
1870818781 return sema.addStrLit(block, bytes);
1870918782 }
1871018783
......@@ -18794,7 +18867,8 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1879418867 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
1879518868 .EnumLiteral => {
1879618869 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
18797 const bytes = val.castTag(.enum_literal).?.data;
18870 const tag_name = mod.intern_pool.indexToKey(val.ip_index).enum_literal;
18871 const bytes = mod.intern_pool.stringToSlice(tag_name);
1879818872 return sema.addStrLit(block, bytes);
1879918873 },
1880018874 .Enum => operand_ty,
......@@ -18883,11 +18957,8 @@ fn zirReify(
1888318957 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,
1888418958 .Int => {
1888518959 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18886 const signedness_index = fields.getIndex("signedness").?;
18887 const bits_index = fields.getIndex("bits").?;
18888
18889 const signedness_val = try union_val.val.fieldValue(fields.values()[signedness_index].ty, mod, signedness_index);
18890 const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index);
18960 const signedness_val = try union_val.val.fieldValue(mod, fields.getIndex("signedness").?);
18961 const bits_val = try union_val.val.fieldValue(mod, fields.getIndex("bits").?);
1889118962
1889218963 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
1889318964 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
......@@ -18896,11 +18967,8 @@ fn zirReify(
1889618967 },
1889718968 .Vector => {
1889818969 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18899 const len_index = fields.getIndex("len").?;
18900 const child_index = fields.getIndex("child").?;
18901
18902 const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index);
18903 const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
18970 const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
18971 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
1890418972
1890518973 const len = @intCast(u32, len_val.toUnsignedInt(mod));
1890618974 const child_ty = child_val.toType();
......@@ -18915,9 +18983,7 @@ fn zirReify(
1891518983 },
1891618984 .Float => {
1891718985 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18918 const bits_index = fields.getIndex("bits").?;
18919
18920 const bits_val = try union_val.val.fieldValue(fields.values()[bits_index].ty, mod, bits_index);
18986 const bits_val = try union_val.val.fieldValue(mod, fields.getIndex("bits").?);
1892118987
1892218988 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
1892318989 const ty = switch (bits) {
......@@ -18932,23 +18998,14 @@ fn zirReify(
1893218998 },
1893318999 .Pointer => {
1893419000 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
18935 const size_index = fields.getIndex("size").?;
18936 const is_const_index = fields.getIndex("is_const").?;
18937 const is_volatile_index = fields.getIndex("is_volatile").?;
18938 const alignment_index = fields.getIndex("alignment").?;
18939 const address_space_index = fields.getIndex("address_space").?;
18940 const child_index = fields.getIndex("child").?;
18941 const is_allowzero_index = fields.getIndex("is_allowzero").?;
18942 const sentinel_index = fields.getIndex("sentinel").?;
18943
18944 const size_val = try union_val.val.fieldValue(fields.values()[size_index].ty, mod, size_index);
18945 const is_const_val = try union_val.val.fieldValue(fields.values()[is_const_index].ty, mod, is_const_index);
18946 const is_volatile_val = try union_val.val.fieldValue(fields.values()[is_volatile_index].ty, mod, is_volatile_index);
18947 const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index);
18948 const address_space_val = try union_val.val.fieldValue(fields.values()[address_space_index].ty, mod, address_space_index);
18949 const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
18950 const is_allowzero_val = try union_val.val.fieldValue(fields.values()[is_allowzero_index].ty, mod, is_allowzero_index);
18951 const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index);
19001 const size_val = try union_val.val.fieldValue(mod, fields.getIndex("size").?);
19002 const is_const_val = try union_val.val.fieldValue(mod, fields.getIndex("is_const").?);
19003 const is_volatile_val = try union_val.val.fieldValue(mod, fields.getIndex("is_volatile").?);
19004 const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
19005 const address_space_val = try union_val.val.fieldValue(mod, fields.getIndex("address_space").?);
19006 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
19007 const is_allowzero_val = try union_val.val.fieldValue(mod, fields.getIndex("is_allowzero").?);
19008 const sentinel_val = try union_val.val.fieldValue(mod, fields.getIndex("sentinel").?);
1895219009
1895319010 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
1895419011 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
......@@ -19032,22 +19089,18 @@ fn zirReify(
1903219089 },
1903319090 .Array => {
1903419091 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19035 const len_index = fields.getIndex("len").?;
19036 const child_index = fields.getIndex("child").?;
19037 const sentinel_index = fields.getIndex("sentinel").?;
19038
19039 const len_val = try union_val.val.fieldValue(fields.values()[len_index].ty, mod, len_index);
19040 const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
19041 const sentinel_val = try union_val.val.fieldValue(fields.values()[sentinel_index].ty, mod, sentinel_index);
19092 const len_val = try union_val.val.fieldValue(mod, fields.getIndex("len").?);
19093 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
19094 const sentinel_val = try union_val.val.fieldValue(mod, fields.getIndex("sentinel").?);
1904219095
1904319096 const len = len_val.toUnsignedInt(mod);
1904419097 const child_ty = child_val.toType();
19045 const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {
19098 const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {
1904619099 const ptr_ty = try Type.ptr(sema.arena, mod, .{
1904719100 .@"addrspace" = .generic,
1904819101 .pointee_type = child_ty,
1904919102 });
19050 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;
19103 break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
1905119104 } else null;
1905219105
1905319106 const ty = try Type.array(sema.arena, len, sentinel, child_ty, mod);
......@@ -19055,9 +19108,7 @@ fn zirReify(
1905519108 },
1905619109 .Optional => {
1905719110 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19058 const child_index = fields.getIndex("child").?;
19059
19060 const child_val = try union_val.val.fieldValue(fields.values()[child_index].ty, mod, child_index);
19111 const child_val = try union_val.val.fieldValue(mod, fields.getIndex("child").?);
1906119112
1906219113 const child_ty = child_val.toType();
1906319114
......@@ -19066,11 +19117,8 @@ fn zirReify(
1906619117 },
1906719118 .ErrorUnion => {
1906819119 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19069 const error_set_index = fields.getIndex("error_set").?;
19070 const payload_index = fields.getIndex("payload").?;
19071
19072 const error_set_val = try union_val.val.fieldValue(fields.values()[error_set_index].ty, mod, error_set_index);
19073 const payload_val = try union_val.val.fieldValue(fields.values()[payload_index].ty, mod, payload_index);
19120 const error_set_val = try union_val.val.fieldValue(mod, fields.getIndex("error_set").?);
19121 const payload_val = try union_val.val.fieldValue(mod, fields.getIndex("payload").?);
1907419122
1907519123 const error_set_ty = error_set_val.toType();
1907619124 const payload_ty = payload_val.toType();
......@@ -19085,18 +19133,17 @@ fn zirReify(
1908519133 .ErrorSet => {
1908619134 const payload_val = union_val.val.optionalValue(mod) orelse
1908719135 return sema.addType(Type.anyerror);
19088 const slice_val = payload_val.castTag(.slice).?.data;
1908919136
19090 const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod));
19137 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
1909119138 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1909219139 try names.ensureUnusedCapacity(sema.arena, len);
1909319140 for (0..len) |i| {
19094 const elem_val = try slice_val.ptr.elemValue(mod, i);
19141 const elem_val = try payload_val.elemValue(mod, i);
1909519142 const struct_val = elem_val.castTag(.aggregate).?.data;
1909619143 // TODO use reflection instead of magic numbers here
1909719144 // error_set: type,
1909819145 const name_val = struct_val[0];
19099 const name_str = try name_val.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
19146 const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
1910019147 const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str);
1910119148 const gop = names.getOrPutAssumeCapacity(name_ip);
1910219149 if (gop.found_existing) {
......@@ -19109,17 +19156,11 @@ fn zirReify(
1910919156 },
1911019157 .Struct => {
1911119158 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19112 const layout_index = fields.getIndex("layout").?;
19113 const backing_integer_index = fields.getIndex("backing_integer").?;
19114 const fields_index = fields.getIndex("fields").?;
19115 const decls_index = fields.getIndex("decls").?;
19116 const is_tuple_index = fields.getIndex("is_tuple").?;
19117
19118 const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index);
19119 const backing_integer_val = try union_val.val.fieldValue(fields.values()[backing_integer_index].ty, mod, backing_integer_index);
19120 const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
19121 const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
19122 const is_tuple_val = try union_val.val.fieldValue(fields.values()[is_tuple_index].ty, mod, is_tuple_index);
19159 const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
19160 const backing_integer_val = try union_val.val.fieldValue(mod, fields.getIndex("backing_integer").?);
19161 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19162 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
19163 const is_tuple_val = try union_val.val.fieldValue(mod, fields.getIndex("is_tuple").?);
1912319164
1912419165 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
1912519166
......@@ -19136,15 +19177,10 @@ fn zirReify(
1913619177 },
1913719178 .Enum => {
1913819179 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19139 const tag_type_index = fields.getIndex("tag_type").?;
19140 const fields_index = fields.getIndex("fields").?;
19141 const decls_index = fields.getIndex("decls").?;
19142 const is_exhaustive_index = fields.getIndex("is_exhaustive").?;
19143
19144 const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index);
19145 const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
19146 const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
19147 const is_exhaustive_val = try union_val.val.fieldValue(fields.values()[is_exhaustive_index].ty, mod, is_exhaustive_index);
19180 const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
19181 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19182 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
19183 const is_exhaustive_val = try union_val.val.fieldValue(mod, fields.getIndex("is_exhaustive").?);
1914819184
1914919185 // Decls
1915019186 if (decls_val.sliceLen(mod) > 0) {
......@@ -19195,7 +19231,7 @@ fn zirReify(
1919519231 const value_val = field_struct_val[1];
1919619232
1919719233 const field_name = try name_val.toAllocatedBytes(
19198 Type.const_slice_u8,
19234 Type.slice_const_u8,
1919919235 sema.arena,
1920019236 mod,
1920119237 );
......@@ -19237,9 +19273,7 @@ fn zirReify(
1923719273 },
1923819274 .Opaque => {
1923919275 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19240 const decls_index = fields.getIndex("decls").?;
19241
19242 const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
19276 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
1924319277
1924419278 // Decls
1924519279 if (decls_val.sliceLen(mod) > 0) {
......@@ -19283,15 +19317,10 @@ fn zirReify(
1928319317 },
1928419318 .Union => {
1928519319 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19286 const layout_index = fields.getIndex("layout").?;
19287 const tag_type_index = fields.getIndex("tag_type").?;
19288 const fields_index = fields.getIndex("fields").?;
19289 const decls_index = fields.getIndex("decls").?;
19290
19291 const layout_val = try union_val.val.fieldValue(fields.values()[layout_index].ty, mod, layout_index);
19292 const tag_type_val = try union_val.val.fieldValue(fields.values()[tag_type_index].ty, mod, tag_type_index);
19293 const fields_val = try union_val.val.fieldValue(fields.values()[fields_index].ty, mod, fields_index);
19294 const decls_val = try union_val.val.fieldValue(fields.values()[decls_index].ty, mod, decls_index);
19320 const layout_val = try union_val.val.fieldValue(mod, fields.getIndex("layout").?);
19321 const tag_type_val = try union_val.val.fieldValue(mod, fields.getIndex("tag_type").?);
19322 const fields_val = try union_val.val.fieldValue(mod, fields.getIndex("fields").?);
19323 const decls_val = try union_val.val.fieldValue(mod, fields.getIndex("decls").?);
1929519324
1929619325 // Decls
1929719326 if (decls_val.sliceLen(mod) > 0) {
......@@ -19386,7 +19415,7 @@ fn zirReify(
1938619415 const alignment_val = field_struct_val[2];
1938719416
1938819417 const field_name = try name_val.toAllocatedBytes(
19389 Type.const_slice_u8,
19418 Type.slice_const_u8,
1939019419 new_decl_arena_allocator,
1939119420 mod,
1939219421 );
......@@ -19489,19 +19518,12 @@ fn zirReify(
1948919518 },
1949019519 .Fn => {
1949119520 const fields = ip.typeOf(union_val.val.ip_index).toType().structFields(mod);
19492 const calling_convention_index = fields.getIndex("calling_convention").?;
19493 const alignment_index = fields.getIndex("alignment").?;
19494 const is_generic_index = fields.getIndex("is_generic").?;
19495 const is_var_args_index = fields.getIndex("is_var_args").?;
19496 const return_type_index = fields.getIndex("return_type").?;
19497 const params_index = fields.getIndex("params").?;
19498
19499 const calling_convention_val = try union_val.val.fieldValue(fields.values()[calling_convention_index].ty, mod, calling_convention_index);
19500 const alignment_val = try union_val.val.fieldValue(fields.values()[alignment_index].ty, mod, alignment_index);
19501 const is_generic_val = try union_val.val.fieldValue(fields.values()[is_generic_index].ty, mod, is_generic_index);
19502 const is_var_args_val = try union_val.val.fieldValue(fields.values()[is_var_args_index].ty, mod, is_var_args_index);
19503 const return_type_val = try union_val.val.fieldValue(fields.values()[return_type_index].ty, mod, return_type_index);
19504 const params_val = try union_val.val.fieldValue(fields.values()[params_index].ty, mod, params_index);
19521 const calling_convention_val = try union_val.val.fieldValue(mod, fields.getIndex("calling_convention").?);
19522 const alignment_val = try union_val.val.fieldValue(mod, fields.getIndex("alignment").?);
19523 const is_generic_val = try union_val.val.fieldValue(mod, fields.getIndex("is_generic").?);
19524 const is_var_args_val = try union_val.val.fieldValue(mod, fields.getIndex("is_var_args").?);
19525 const return_type_val = try union_val.val.fieldValue(mod, fields.getIndex("return_type").?);
19526 const params_val = try union_val.val.fieldValue(mod, fields.getIndex("params").?);
1950519527
1950619528 const is_generic = is_generic_val.toBool(mod);
1950719529 if (is_generic) {
......@@ -19528,14 +19550,12 @@ fn zirReify(
1952819550 const return_type = return_type_val.optionalValue(mod) orelse
1952919551 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
1953019552
19531 const args_slice_val = params_val.castTag(.slice).?.data;
19532 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod));
19533
19553 const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));
1953419554 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
1953519555
1953619556 var noalias_bits: u32 = 0;
1953719557 for (param_types, 0..) |*param_type, i| {
19538 const arg = try args_slice_val.ptr.elemValue(mod, i);
19558 const arg = try params_val.elemValue(mod, i);
1953919559 const arg_val = arg.castTag(.aggregate).?.data;
1954019560 // TODO use reflection instead of magic numbers here
1954119561 // is_generic: bool,
......@@ -19676,7 +19696,7 @@ fn reifyStruct(
1967619696 }
1967719697
1967819698 const field_name = try name_val.toAllocatedBytes(
19679 Type.const_slice_u8,
19699 Type.slice_const_u8,
1968019700 new_decl_arena_allocator,
1968119701 mod,
1968219702 );
......@@ -19707,7 +19727,7 @@ fn reifyStruct(
1970719727 }
1970819728
1970919729 const default_val = if (default_value_val.optionalValue(mod)) |opt_val| blk: {
19710 const payload_val = if (opt_val.pointerDecl()) |opt_decl|
19730 const payload_val = if (opt_val.pointerDecl(mod)) |opt_decl|
1971119731 mod.declPtr(opt_decl).val
1971219732 else
1971319733 opt_val;
......@@ -20137,7 +20157,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
2013720157
2013820158 if (maybe_operand_val) |val| {
2013920159 if (!dest_ty.isAnyError(mod)) {
20140 const error_name = val.castTag(.@"error").?.data.name;
20160 const error_name = mod.intern_pool.stringToSlice(mod.intern_pool.indexToKey(val.ip_index).err.name);
2014120161 if (!dest_ty.errorSetHasField(error_name, mod)) {
2014220162 const msg = msg: {
2014320163 const msg = try sema.errMsg(
......@@ -20279,7 +20299,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2027920299 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
2028020300 }
2028120301 if (dest_ty.zigTypeTag(mod) == .Optional and sema.typeOf(ptr).zigTypeTag(mod) != .Optional) {
20282 return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val));
20302 return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{
20303 .ty = dest_ty.ip_index,
20304 .val = operand_val.toIntern(),
20305 } })).toValue());
2028320306 }
2028420307 return sema.addConstant(aligned_dest_ty, operand_val);
2028520308 }
......@@ -20944,7 +20967,7 @@ fn checkPtrIsNotComptimeMutable(
2094420967 operand_src: LazySrcLoc,
2094520968) CompileError!void {
2094620969 _ = operand_src;
20947 if (ptr_val.isComptimeMutablePtr()) {
20970 if (ptr_val.isComptimeMutablePtr(sema.mod)) {
2094820971 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});
2094920972 }
2095020973}
......@@ -20953,7 +20976,7 @@ fn checkComptimeVarStore(
2095320976 sema: *Sema,
2095420977 block: *Block,
2095520978 src: LazySrcLoc,
20956 decl_ref_mut: Value.Payload.DeclRefMut.Data,
20979 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
2095720980) CompileError!void {
2095820981 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {
2095920982 if (block.runtime_cond) |cond_src| {
......@@ -21159,7 +21182,7 @@ fn resolveExportOptions(
2115921182
2116021183 const name_operand = try sema.fieldVal(block, src, options, "name", name_src);
2116121184 const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known");
21162 const name_ty = Type.const_slice_u8;
21185 const name_ty = Type.slice_const_u8;
2116321186 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);
2116421187
2116521188 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);
......@@ -21168,7 +21191,7 @@ fn resolveExportOptions(
2116821191
2116921192 const section_operand = try sema.fieldVal(block, src, options, "section", section_src);
2117021193 const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known");
21171 const section_ty = Type.const_slice_u8;
21194 const section_ty = Type.slice_const_u8;
2117221195 const section = if (section_opt_val.optionalValue(mod)) |section_val|
2117321196 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)
2117421197 else
......@@ -21298,12 +21321,14 @@ fn zirCmpxchg(
2129821321 }
2129921322 const ptr_ty = sema.typeOf(ptr);
2130021323 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
21301 const result_val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
21302 try sema.storePtr(block, src, ptr, new_value);
21303 break :blk Value.null;
21304 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);
21305
21306 return sema.addConstant(result_ty, result_val);
21324 const result_val = try mod.intern(.{ .opt = .{
21325 .ty = result_ty.ip_index,
21326 .val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
21327 try sema.storePtr(block, src, ptr, new_value);
21328 break :blk .none;
21329 } else stored_val.toIntern(),
21330 } });
21331 return sema.addConstant(result_ty, result_val.toValue());
2130721332 } else break :rs new_value_src;
2130821333 } else break :rs expected_src;
2130921334 } else ptr_src;
......@@ -21342,11 +21367,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2134221367 });
2134321368 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
2134421369 if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
21345
21346 return sema.addConstant(
21347 vector_ty,
21348 try Value.Tag.repeated.create(sema.arena, scalar_val),
21349 );
21370 return sema.addConstant(vector_ty, try sema.splat(vector_ty, scalar_val));
2135021371 }
2135121372
2135221373 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
2180021821 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
2180121822 break :rs operand_src;
2180221823 };
21803 if (ptr_val.isComptimeMutablePtr()) {
21824 if (ptr_val.isComptimeMutablePtr(mod)) {
2180421825 const ptr_ty = sema.typeOf(ptr);
2180521826 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
2180621827 const new_val = switch (op) {
......@@ -22081,10 +22102,15 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2208122102 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
2208222103
2208322104 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
22084 const payload = field_ptr_val.castTag(.field_ptr) orelse {
22085 return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
22086 };
22087 if (payload.data.field_index != field_index) {
22105 const field = switch (mod.intern_pool.indexToKey(field_ptr_val.ip_index)) {
22106 .ptr => |ptr| switch (ptr.addr) {
22107 .field => |field| field,
22108 else => null,
22109 },
22110 else => null,
22111 } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
22112
22113 if (field.index != field_index) {
2208822114 const msg = msg: {
2208922115 const msg = try sema.errMsg(
2209022116 block,
......@@ -22093,7 +22119,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2209322119 .{
2209422120 field_name,
2209522121 field_index,
22096 payload.data.field_index,
22122 field.index,
2209722123 parent_ty.fmt(sema.mod),
2209822124 },
2209922125 );
......@@ -22103,7 +22129,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2210322129 };
2210422130 return sema.failWithOwnedErrorMsg(msg);
2210522131 }
22106 return sema.addConstant(result_ptr, payload.data.container_ptr);
22132 return sema.addConstant(result_ptr, field.base.toValue());
2210722133 }
2210822134
2210922135 try sema.requireRuntimeBlock(block, src, ptr_src);
......@@ -22335,13 +22361,13 @@ fn analyzeMinMax(
2233522361
2233622362 // Compute the final bounds based on the runtime type and the comptime-known bound type
2233722363 const min_val = switch (air_tag) {
22338 .min => try unrefined_elem_ty.minInt(sema.arena, mod),
22339 .max => try comptime_elem_ty.minInt(sema.arena, mod), // @max(ct, rt) >= ct
22364 .min => try unrefined_elem_ty.minInt(mod),
22365 .max => try comptime_elem_ty.minInt(mod), // @max(ct, rt) >= ct
2234022366 else => unreachable,
2234122367 };
2234222368 const max_val = switch (air_tag) {
22343 .min => try comptime_elem_ty.maxInt(sema.arena, mod, Type.comptime_int), // @min(ct, rt) <= ct
22344 .max => try unrefined_elem_ty.maxInt(sema.arena, mod, Type.comptime_int),
22369 .min => try comptime_elem_ty.maxInt(mod, Type.comptime_int), // @min(ct, rt) <= ct
22370 .max => try unrefined_elem_ty.maxInt(mod, Type.comptime_int),
2234522371 else => unreachable,
2234622372 };
2234722373
......@@ -22464,7 +22490,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2246422490 }
2246522491
2246622492 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
22467 if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src;
22493 if (!dest_ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
2246822494 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
2246922495 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;
2247022496 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
2261822644 return;
2261922645 }
2262022646
22621 if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;
22647 if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
2262222648 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {
2262322649 for (0..len) |i| {
2262422650 const elem_index = try sema.addIntUnsigned(Type.usize, i);
......@@ -22696,6 +22722,7 @@ fn zirVarExtended(
2269622722 block: *Block,
2269722723 extended: Zir.Inst.Extended.InstData,
2269822724) CompileError!Air.Inst.Ref {
22725 const mod = sema.mod;
2269922726 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
2270022727 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
2270122728 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
......@@ -22737,32 +22764,17 @@ fn zirVarExtended(
2273722764
2273822765 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2273922766
22740 const new_var = try sema.gpa.create(Module.Var);
22741 errdefer sema.gpa.destroy(new_var);
22742
22743 log.debug("created variable {*} owner_decl: {*} ({s})", .{
22744 new_var, sema.owner_decl, sema.owner_decl.name,
22745 });
22746
22747 new_var.* = .{
22748 .owner_decl = sema.owner_decl_index,
22749 .init = init_val,
22767 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
22768 .ty = var_ty.ip_index,
22769 .init = init_val.toIntern(),
22770 .decl = sema.owner_decl_index,
22771 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
22772 sema.gpa,
22773 try sema.handleExternLibName(block, ty_src, lname),
22774 )).toOptional() else .none,
2275022775 .is_extern = small.is_extern,
22751 .is_mutable = true,
2275222776 .is_threadlocal = small.is_threadlocal,
22753 .is_weak_linkage = false,
22754 .lib_name = null,
22755 };
22756
22757 if (lib_name) |lname| {
22758 new_var.lib_name = try sema.handleExternLibName(block, ty_src, lname);
22759 }
22760
22761 const result = try sema.addConstant(
22762 var_ty,
22763 try Value.Tag.variable.create(sema.arena, new_var),
22764 );
22765 return result;
22777 } })).toValue());
2276622778}
2276722779
2276822780fn 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
2286122873 const body = sema.code.extra[extra_index..][0..body_len];
2286222874 extra_index += body.len;
2286322875
22864 const ty = Type.const_slice_u8;
22876 const ty = Type.slice_const_u8;
2286522877 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
2286622878 if (val.isGenericPoison()) {
2286722879 break :blk FuncLinkSection{ .generic = {} };
......@@ -23133,10 +23145,10 @@ fn resolveExternOptions(
2313323145 src: LazySrcLoc,
2313423146 zir_ref: Zir.Inst.Ref,
2313523147) CompileError!std.builtin.ExternOptions {
23148 const mod = sema.mod;
2313623149 const options_inst = try sema.resolveInst(zir_ref);
2313723150 const extern_options_ty = try sema.getBuiltinType("ExternOptions");
2313823151 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
23139 const mod = sema.mod;
2314023152
2314123153 const name_src = sema.maybeOptionsSrc(block, src, "name");
2314223154 const library_src = sema.maybeOptionsSrc(block, src, "library");
......@@ -23145,7 +23157,7 @@ fn resolveExternOptions(
2314523157
2314623158 const name_ref = try sema.fieldVal(block, src, options, "name", name_src);
2314723159 const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime-known");
23148 const name = try name_val.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
23160 const name = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2314923161
2315023162 const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);
2315123163 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(
2315723169 const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);
2315823170 const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known");
2315923171
23160 const library_name = if (!library_name_val.isNull(mod)) blk: {
23161 const payload = library_name_val.castTag(.opt_payload).?.data;
23162 const library_name = try payload.toAllocatedBytes(Type.const_slice_u8, sema.arena, mod);
23172 const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
23173 const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2316323174 if (library_name.len == 0) {
2316423175 return sema.fail(block, library_src, "library name cannot be empty", .{});
2316523176 }
......@@ -23227,40 +23238,36 @@ fn zirBuiltinExtern(
2322723238 new_decl.name = try sema.gpa.dupeZ(u8, options.name);
2322823239
2322923240 {
23230 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
23231 errdefer new_decl_arena.deinit();
23232 const new_decl_arena_allocator = new_decl_arena.allocator();
23233
23234 const new_var = try new_decl_arena_allocator.create(Module.Var);
23235 new_var.* = .{
23236 .owner_decl = sema.owner_decl_index,
23237 .init = Value.@"unreachable",
23241 const new_var = try mod.intern(.{ .variable = .{
23242 .ty = ty.ip_index,
23243 .init = .none,
23244 .decl = sema.owner_decl_index,
2323823245 .is_extern = true,
23239 .is_mutable = false,
23246 .is_const = true,
2324023247 .is_threadlocal = options.is_thread_local,
2324123248 .is_weak_linkage = options.linkage == .Weak,
23242 .lib_name = null,
23243 };
23249 } });
2324423250
2324523251 new_decl.src_line = sema.owner_decl.src_line;
2324623252 // We only access this decl through the decl_ref with the correct type created
2324723253 // below, so this type doesn't matter
23248 new_decl.ty = Type.anyopaque;
23249 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
23254 new_decl.ty = ty;
23255 new_decl.val = new_var.toValue();
2325023256 new_decl.@"align" = 0;
2325123257 new_decl.@"linksection" = null;
2325223258 new_decl.has_tv = true;
2325323259 new_decl.analysis = .complete;
2325423260 new_decl.generation = mod.generation;
23255
23256 try new_decl.finalizeNewArena(&new_decl_arena);
2325723261 }
2325823262
2325923263 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
2326023264 try sema.ensureDeclAnalyzed(new_decl_index);
2326123265
23262 const ref = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
23263 return sema.addConstant(ty, ref);
23266 const ref = try mod.intern(.{ .ptr = .{
23267 .ty = (try mod.singleConstPtrType(ty)).ip_index,
23268 .addr = .{ .decl = new_decl_index },
23269 } });
23270 return sema.addConstant(ty, ref.toValue());
2326423271}
2326523272
2326623273fn zirWorkItem(
......@@ -24117,7 +24124,6 @@ fn fieldVal(
2411724124
2411824125 const mod = sema.mod;
2411924126 const gpa = sema.gpa;
24120 const arena = sema.arena;
2412124127 const ip = &mod.intern_pool;
2412224128 const object_src = src; // TODO better source location
2412324129 const object_ty = sema.typeOf(object);
......@@ -24221,13 +24227,14 @@ fn fieldVal(
2422124227 else => unreachable,
2422224228 }
2422324229
24224 return sema.addConstant(
24225 if (!child_type.isAnyError(mod))
24226 child_type
24227 else
24228 try mod.singleErrorSetTypeNts(name),
24229 try Value.Tag.@"error".create(arena, .{ .name = ip.stringToSlice(name) }),
24230 );
24230 const error_set_type = if (!child_type.isAnyError(mod))
24231 child_type
24232 else
24233 try mod.singleErrorSetTypeNts(name);
24234 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
24235 .ty = error_set_type.ip_index,
24236 .name = name,
24237 } })).toValue());
2423124238 },
2423224239 .Union => {
2423324240 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
......@@ -24368,14 +24375,13 @@ fn fieldPtr(
2436824375 });
2436924376
2437024377 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24371 return sema.addConstant(
24372 result_ty,
24373 try Value.Tag.field_ptr.create(sema.arena, .{
24374 .container_ptr = val,
24375 .container_ty = inner_ty,
24376 .field_index = Value.Payload.Slice.ptr_index,
24377 }),
24378 );
24378 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24379 .ty = result_ty.ip_index,
24380 .addr = .{ .field = .{
24381 .base = val.ip_index,
24382 .index = Value.slice_ptr_index,
24383 } },
24384 } })).toValue());
2437924385 }
2438024386 try sema.requireRuntimeBlock(block, src, null);
2438124387
......@@ -24389,14 +24395,13 @@ fn fieldPtr(
2438924395 });
2439024396
2439124397 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24392 return sema.addConstant(
24393 result_ty,
24394 try Value.Tag.field_ptr.create(sema.arena, .{
24395 .container_ptr = val,
24396 .container_ty = inner_ty,
24397 .field_index = Value.Payload.Slice.len_index,
24398 }),
24399 );
24398 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24399 .ty = result_ty.ip_index,
24400 .addr = .{ .field = .{
24401 .base = val.ip_index,
24402 .index = Value.slice_len_index,
24403 } },
24404 } })).toValue());
2440024405 }
2440124406 try sema.requireRuntimeBlock(block, src, null);
2440224407
......@@ -24442,14 +24447,16 @@ fn fieldPtr(
2444224447
2444324448 var anon_decl = try block.startAnonDecl();
2444424449 defer anon_decl.deinit();
24450 const error_set_type = if (!child_type.isAnyError(mod))
24451 child_type
24452 else
24453 try mod.singleErrorSetTypeNts(name);
2444524454 return sema.analyzeDeclRef(try anon_decl.finish(
24446 if (!child_type.isAnyError(mod))
24447 child_type
24448 else
24449 try mod.singleErrorSetTypeNts(name),
24450 try Value.Tag.@"error".create(anon_decl.arena(), .{
24451 .name = ip.stringToSlice(name),
24452 }),
24455 error_set_type,
24456 (try mod.intern(.{ .err = .{
24457 .ty = error_set_type.ip_index,
24458 .name = name,
24459 } })).toValue(),
2445324460 0, // default alignment
2445424461 ));
2445524462 },
......@@ -24714,14 +24721,13 @@ fn finishFieldCallBind(
2471424721 }
2471524722
2471624723 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
24717 const pointer = try sema.addConstant(
24718 ptr_field_ty,
24719 try Value.Tag.field_ptr.create(arena, .{
24720 .container_ptr = struct_ptr_val,
24721 .container_ty = container_ty,
24722 .field_index = field_index,
24723 }),
24724 );
24724 const pointer = try sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
24725 .ty = ptr_field_ty.ip_index,
24726 .addr = .{ .field = .{
24727 .base = struct_ptr_val.ip_index,
24728 .index = field_index,
24729 } },
24730 } })).toValue());
2472524731 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
2472624732 }
2472724733
......@@ -24901,22 +24907,22 @@ fn structFieldPtrByIndex(
2490124907 const ptr_field_ty = try Type.ptr(sema.arena, mod, ptr_ty_data);
2490224908
2490324909 if (field.is_comptime) {
24904 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
24905 .field_ty = field.ty,
24906 .field_val = try field.default_val.copy(sema.arena),
24907 });
24908 return sema.addConstant(ptr_field_ty, val);
24910 const val = try mod.intern(.{ .ptr = .{
24911 .ty = ptr_field_ty.ip_index,
24912 .addr = .{ .comptime_field = try field.default_val.intern(field.ty, mod) },
24913 } });
24914 return sema.addConstant(ptr_field_ty, val.toValue());
2490924915 }
2491024916
2491124917 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
24912 return sema.addConstant(
24913 ptr_field_ty,
24914 try Value.Tag.field_ptr.create(sema.arena, .{
24915 .container_ptr = struct_ptr_val,
24916 .container_ty = struct_ptr_ty.childType(mod),
24917 .field_index = field_index,
24918 }),
24919 );
24918 const val = try mod.intern(.{ .ptr = .{
24919 .ty = ptr_field_ty.ip_index,
24920 .addr = .{ .field = .{
24921 .base = try struct_ptr_val.intern(struct_ptr_ty, mod),
24922 .index = field_index,
24923 } },
24924 } });
24925 return sema.addConstant(ptr_field_ty, val.toValue());
2492024926 }
2492124927
2492224928 try sema.requireRuntimeBlock(block, src, null);
......@@ -24955,7 +24961,7 @@ fn structFieldVal(
2495524961 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
2495624962 return sema.addConstant(field.ty, opv);
2495724963 }
24958 return sema.addConstant(field.ty, try struct_val.fieldValue(field.ty, mod, field_index));
24964 return sema.addConstant(field.ty, try struct_val.fieldValue(mod, field_index));
2495924965 }
2496024966
2496124967 try sema.requireRuntimeBlock(block, src, null);
......@@ -24999,7 +25005,7 @@ fn tupleFieldIndex(
2499925005 field_name_src: LazySrcLoc,
2500025006) CompileError!u32 {
2500125007 const mod = sema.mod;
25002 assert(!std.mem.eql(u8, field_name, "len"));
25008 assert(!mem.eql(u8, field_name, "len"));
2500325009 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
2500425010 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
2500525011 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
......@@ -25109,14 +25115,13 @@ fn unionFieldPtr(
2510925115 },
2511025116 .Packed, .Extern => {},
2511125117 }
25112 return sema.addConstant(
25113 ptr_field_ty,
25114 try Value.Tag.field_ptr.create(arena, .{
25115 .container_ptr = union_ptr_val,
25116 .container_ty = union_ty,
25117 .field_index = field_index,
25118 }),
25119 );
25118 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25119 .ty = ptr_field_ty.ip_index,
25120 .addr = .{ .field = .{
25121 .base = union_ptr_val.ip_index,
25122 .index = field_index,
25123 } },
25124 } })).toValue());
2512025125 }
2512125126
2512225127 try sema.requireRuntimeBlock(block, src, null);
......@@ -25267,7 +25272,7 @@ fn elemPtrOneLayerOnly(
2526725272 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
2526825273 const index_val = maybe_index_val orelse break :rs elem_index_src;
2526925274 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25270 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, mod);
25275 const elem_ptr = try ptr_val.elemPtr(indexable_ty, index, mod);
2527125276 const result_ty = try sema.elemPtrType(indexable_ty, index);
2527225277 return sema.addConstant(result_ty, elem_ptr);
2527325278 };
......@@ -25313,7 +25318,7 @@ fn elemVal(
2531325318 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
2531425319 const index_val = maybe_index_val orelse break :rs elem_index_src;
2531525320 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25316 const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, mod);
25321 const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, index, mod);
2531725322 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {
2531825323 return sema.addConstant(indexable_ty.elemType2(mod), elem_val);
2531925324 }
......@@ -25407,22 +25412,20 @@ fn tupleFieldPtr(
2540725412 });
2540825413
2540925414 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
25410 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
25411 .field_ty = field_ty,
25412 .field_val = default_val,
25413 });
25414 return sema.addConstant(ptr_field_ty, val);
25415 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25416 .ty = ptr_field_ty.ip_index,
25417 .addr = .{ .comptime_field = default_val.ip_index },
25418 } })).toValue());
2541525419 }
2541625420
2541725421 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {
25418 return sema.addConstant(
25419 ptr_field_ty,
25420 try Value.Tag.field_ptr.create(sema.arena, .{
25421 .container_ptr = tuple_ptr_val,
25422 .container_ty = tuple_ty,
25423 .field_index = field_index,
25424 }),
25425 );
25422 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25423 .ty = ptr_field_ty.ip_index,
25424 .addr = .{ .field = .{
25425 .base = tuple_ptr_val.ip_index,
25426 .index = field_index,
25427 } },
25428 } })).toValue());
2542625429 }
2542725430
2542825431 if (!init) {
......@@ -25463,7 +25466,7 @@ fn tupleField(
2546325466
2546425467 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
2546525468 if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty);
25466 return sema.addConstant(field_ty, try tuple_val.fieldValue(tuple_ty, mod, field_index));
25469 return sema.addConstant(field_ty, try tuple_val.fieldValue(mod, field_index));
2546725470 }
2546825471
2546925472 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
......@@ -25575,7 +25578,7 @@ fn elemPtrArray(
2557525578 return sema.addConstUndef(elem_ptr_ty);
2557625579 }
2557725580 if (offset) |index| {
25578 const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, index, mod);
25581 const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, index, mod);
2557925582 return sema.addConstant(elem_ptr_ty, elem_ptr);
2558025583 }
2558125584 }
......@@ -25631,7 +25634,7 @@ fn elemValSlice(
2563125634 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
2563225635 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
2563325636 }
25634 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, mod);
25637 const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod);
2563525638 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {
2563625639 return sema.addConstant(elem_ty, elem_val);
2563725640 }
......@@ -25691,7 +25694,7 @@ fn elemPtrSlice(
2569125694 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
2569225695 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
2569325696 }
25694 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, mod);
25697 const elem_ptr_val = try slice_val.elemPtr(slice_ty, index, mod);
2569525698 return sema.addConstant(elem_ptr_ty, elem_ptr_val);
2569625699 }
2569725700 }
......@@ -25851,7 +25854,7 @@ fn coerceExtra(
2585125854 // Function body to function pointer.
2585225855 if (inst_ty.zigTypeTag(mod) == .Fn) {
2585325856 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
25854 const fn_decl = fn_val.pointerDecl().?;
25857 const fn_decl = fn_val.pointerDecl(mod).?;
2585525858 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
2585625859 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
2585725860 }
......@@ -26080,14 +26083,14 @@ fn coerceExtra(
2608026083 if (inst_child_ty.structFieldCount(mod) == 0) {
2608126084 // Optional slice is represented with a null pointer so
2608226085 // we use a dummy pointer value with the required alignment.
26083 const slice_val = try Value.Tag.slice.create(sema.arena, .{
26084 .ptr = if (dest_info.@"align" != 0)
26086 return sema.addConstant(dest_ty, (try mod.intern(.{ .ptr = .{
26087 .ty = dest_ty.ip_index,
26088 .addr = .{ .int = (if (dest_info.@"align" != 0)
2608526089 try mod.intValue(Type.usize, dest_info.@"align")
2608626090 else
26087 try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena),
26088 .len = try mod.intValue(Type.usize, 0),
26089 });
26090 return sema.addConstant(dest_ty, slice_val);
26091 try dest_info.pointee_type.lazyAbiAlignment(mod)).ip_index },
26092 .len = (try mod.intValue(Type.usize, 0)).ip_index,
26093 } })).toValue());
2609126094 }
2609226095
2609326096 // pointer to tuple to slice
......@@ -26255,7 +26258,8 @@ fn coerceExtra(
2625526258 .EnumLiteral => {
2625626259 // enum literal to enum
2625726260 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
26258 const bytes = val.castTag(.enum_literal).?.data;
26261 const string = mod.intern_pool.indexToKey(val.ip_index).enum_literal;
26262 const bytes = mod.intern_pool.stringToSlice(string);
2625926263 const field_index = dest_ty.enumFieldIndex(bytes, mod) orelse {
2626026264 const msg = msg: {
2626126265 const msg = try sema.errMsg(
......@@ -26292,26 +26296,30 @@ fn coerceExtra(
2629226296 if (maybe_inst_val) |inst_val| {
2629326297 switch (inst_val.ip_index) {
2629426298 .undef => return sema.addConstUndef(dest_ty),
26295 .none => switch (inst_val.tag()) {
26296 .eu_payload => {
26297 const payload = try sema.addConstant(
26298 inst_ty.errorUnionPayload(mod),
26299 inst_val.castTag(.eu_payload).?.data,
26300 );
26301 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
26302 error.NotCoercible => break :eu,
26303 else => |e| return e,
26304 };
26299 else => switch (mod.intern_pool.indexToKey(inst_val.ip_index)) {
26300 .error_union => |error_union| switch (error_union.val) {
26301 .err_name => |err_name| {
26302 const error_set_ty = inst_ty.errorUnionSet(mod);
26303 const error_set_val = try sema.addConstant(error_set_ty, (try mod.intern(.{ .err = .{
26304 .ty = error_set_ty.ip_index,
26305 .name = err_name,
26306 } })).toValue());
26307 return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src);
26308 },
26309 .payload => |payload| {
26310 const payload_val = try sema.addConstant(
26311 inst_ty.errorUnionPayload(mod),
26312 payload.toValue(),
26313 );
26314 return sema.wrapErrorUnionPayload(block, dest_ty, payload_val, inst_src) catch |err| switch (err) {
26315 error.NotCoercible => break :eu,
26316 else => |e| return e,
26317 };
26318 },
2630526319 },
26306 else => {},
26320 else => unreachable,
2630726321 },
26308 else => {},
2630926322 }
26310 const error_set = try sema.addConstant(
26311 inst_ty.errorUnionSet(mod),
26312 inst_val,
26313 );
26314 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
2631526323 }
2631626324 },
2631726325 .ErrorSet => {
......@@ -27029,7 +27037,7 @@ fn coerceInMemoryAllowedErrorSets(
2702927037 },
2703027038 }
2703127039
27032 if (dst_ies.func == sema.owner_func) {
27040 if (dst_ies.func == sema.owner_func_index.unwrap()) {
2703327041 // We are trying to coerce an error set to the current function's
2703427042 // inferred error set.
2703527043 try dst_ies.addErrorSet(src_ty, ip, gpa);
......@@ -27323,7 +27331,7 @@ fn coerceVarArgParam(
2732327331 ),
2732427332 .Fn => blk: {
2732527333 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
27326 const fn_decl = fn_val.pointerDecl().?;
27334 const fn_decl = fn_val.pointerDecl(mod).?;
2732727335 break :blk try sema.analyzeDeclRef(fn_decl);
2732827336 },
2732927337 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
......@@ -27441,7 +27449,7 @@ fn storePtr2(
2744127449 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
2744227450 break :rs operand_src;
2744327451 };
27444 if (ptr_val.isComptimeMutablePtr()) {
27452 if (ptr_val.isComptimeMutablePtr(mod)) {
2744527453 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
2744627454 return;
2744727455 } else break :rs ptr_src;
......@@ -27593,7 +27601,7 @@ fn storePtrVal(
2759327601}
2759427602
2759527603const ComptimePtrMutationKit = struct {
27596 decl_ref_mut: Value.Payload.DeclRefMut.Data,
27604 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
2759727605 pointee: union(enum) {
2759827606 /// The pointer type matches the actual comptime Value so a direct
2759927607 /// modification is possible.
......@@ -27619,12 +27627,12 @@ const ComptimePtrMutationKit = struct {
2761927627 decl_arena: std.heap.ArenaAllocator = undefined,
2762027628
2762127629 fn beginArena(self: *ComptimePtrMutationKit, mod: *Module) Allocator {
27622 const decl = mod.declPtr(self.decl_ref_mut.decl_index);
27630 const decl = mod.declPtr(self.decl_ref_mut.decl);
2762327631 return decl.value_arena.?.acquire(mod.gpa, &self.decl_arena);
2762427632 }
2762527633
2762627634 fn finishArena(self: *ComptimePtrMutationKit, mod: *Module) void {
27627 const decl = mod.declPtr(self.decl_ref_mut.decl_index);
27635 const decl = mod.declPtr(self.decl_ref_mut.decl);
2762827636 decl.value_arena.?.release(&self.decl_arena);
2762927637 self.decl_arena = undefined;
2763027638 }
......@@ -27637,6 +27645,7 @@ fn beginComptimePtrMutation(
2763727645 ptr_val: Value,
2763827646 ptr_elem_ty: Type,
2763927647) CompileError!ComptimePtrMutationKit {
27648 if (true) unreachable;
2764027649 const mod = sema.mod;
2764127650 switch (ptr_val.tag()) {
2764227651 .decl_ref_mut => {
......@@ -28169,7 +28178,7 @@ fn beginComptimePtrMutation(
2816928178 },
2817028179 }
2817128180 },
28172 .decl_ref => unreachable, // isComptimeMutablePtr() has been checked already
28181 .decl_ref => unreachable, // isComptimeMutablePtr has been checked already
2817328182 else => unreachable,
2817428183 }
2817528184}
......@@ -28189,7 +28198,7 @@ fn beginComptimePtrMutationInner(
2818928198
2819028199 const decl = mod.declPtr(decl_ref_mut.decl_index);
2819128200 var decl_arena: std.heap.ArenaAllocator = undefined;
28192 const allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena);
28201 const allocator = decl.value_arena.?.acquire(sema.gpa, &decl_arena);
2819328202 defer decl.value_arena.?.release(&decl_arena);
2819428203 decl_val.* = try decl_val.unintern(allocator, mod);
2819528204
......@@ -28273,44 +28282,83 @@ fn beginComptimePtrLoad(
2827328282 const mod = sema.mod;
2827428283 const target = mod.getTarget();
2827528284
28276 var deref: ComptimePtrLoadKit = switch (ptr_val.ip_index) {
28277 .null_value => {
28278 return sema.fail(block, src, "attempt to use null value", .{});
28279 },
28280
28281 .none => switch (ptr_val.tag()) {
28282 .decl_ref,
28283 .decl_ref_mut,
28284 => blk: {
28285 const decl_index = switch (ptr_val.tag()) {
28286 .decl_ref => ptr_val.castTag(.decl_ref).?.data,
28287 .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
28285 var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
28286 .ptr => |ptr| switch (ptr.addr) {
28287 .decl, .mut_decl => blk: {
28288 const decl_index = switch (ptr.addr) {
28289 .decl => |decl| decl,
28290 .mut_decl => |mut_decl| mut_decl.decl,
2828828291 else => unreachable,
2828928292 };
28290 const is_mutable = ptr_val.tag() == .decl_ref_mut;
2829128293 const decl = mod.declPtr(decl_index);
2829228294 const decl_tv = try decl.typedValue();
28293 if (decl_tv.val.tagIsVariable()) return error.RuntimeLoad;
28295 if (decl.getVariable(mod) != null) return error.RuntimeLoad;
2829428296
2829528297 const layout_defined = decl.ty.hasWellDefinedLayout(mod);
2829628298 break :blk ComptimePtrLoadKit{
2829728299 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
2829828300 .pointee = decl_tv,
28299 .is_mutable = is_mutable,
28301 .is_mutable = false,
2830028302 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
2830128303 };
2830228304 },
28305 .int => return error.RuntimeLoad,
28306 .eu_payload, .opt_payload => |container_ptr| blk: {
28307 const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
28308 const payload_ty = ptr.ty.toType().childType(mod);
28309 var deref = try sema.beginComptimePtrLoad(block, src, container_ptr.toValue(), container_ty);
2830328310
28304 .elem_ptr => blk: {
28305 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
28306 const elem_ty = elem_ptr.elem_ty;
28307 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null);
28311 // eu_payload and opt_payload never have a well-defined layout
28312 if (deref.parent != null) {
28313 deref.parent = null;
28314 deref.ty_without_well_defined_layout = container_ty;
28315 }
28316
28317 if (deref.pointee) |*tv| {
28318 const coerce_in_mem_ok =
28319 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28320 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28321 if (coerce_in_mem_ok) {
28322 const payload_val = switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
28323 .error_union => |error_union| switch (error_union.val) {
28324 .err_name => |err_name| return sema.fail(block, src, "attempt to unwrap error: {s}", .{mod.intern_pool.stringToSlice(err_name)}),
28325 .payload => |payload| payload,
28326 },
28327 .opt => |opt| switch (opt.val) {
28328 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28329 else => opt.val,
28330 },
28331 else => unreachable,
28332 };
28333 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val.toValue() };
28334 break :blk deref;
28335 }
28336 }
28337 deref.pointee = null;
28338 break :blk deref;
28339 },
28340 .comptime_field => |comptime_field| blk: {
28341 const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
28342 break :blk ComptimePtrLoadKit{
28343 .parent = null,
28344 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
28345 .is_mutable = false,
28346 .ty_without_well_defined_layout = field_ty,
28347 };
28348 },
28349 .elem => |elem_ptr| blk: {
28350 const elem_ty = ptr.ty.toType().childType(mod);
28351 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
2830828352
2830928353 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
2831028354 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
2831128355 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
28312 if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| {
28313 assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, mod)));
28356 switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
28357 .ptr => |base_ptr| switch (base_ptr.addr) {
28358 .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
28359 else => {},
28360 },
28361 else => {},
2831428362 }
2831528363
2831628364 if (elem_ptr.index != 0) {
......@@ -28327,7 +28375,7 @@ fn beginComptimePtrLoad(
2832728375 }
2832828376 }
2832928377
28330 // If we're loading an elem_ptr that was derived from a different type
28378 // If we're loading an elem that was derived from a different type
2833128379 // than the true type of the underlying decl, we cannot deref directly
2833228380 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
2833328381 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
......@@ -28373,31 +28421,25 @@ fn beginComptimePtrLoad(
2837328421 };
2837428422 break :blk deref;
2837528423 },
28424 .field => |field_ptr| blk: {
28425 const field_index = @intCast(u32, field_ptr.index);
28426 const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
28427 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
2837628428
28377 .slice => blk: {
28378 const slice = ptr_val.castTag(.slice).?.data;
28379 break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null);
28380 },
28381
28382 .field_ptr => blk: {
28383 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
28384 const field_index = @intCast(u32, field_ptr.field_index);
28385 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
28386
28387 if (field_ptr.container_ty.hasWellDefinedLayout(mod)) {
28388 const struct_obj = mod.typeToStruct(field_ptr.container_ty);
28429 if (container_ty.hasWellDefinedLayout(mod)) {
28430 const struct_obj = mod.typeToStruct(container_ty);
2838928431 if (struct_obj != null and struct_obj.?.layout == .Packed) {
2839028432 // packed structs are not byte addressable
2839128433 deref.parent = null;
2839228434 } else if (deref.parent) |*parent| {
2839328435 // Update the byte offset (in-place)
28394 try sema.resolveTypeLayout(field_ptr.container_ty);
28395 const field_offset = field_ptr.container_ty.structFieldOffset(field_index, mod);
28436 try sema.resolveTypeLayout(container_ty);
28437 const field_offset = container_ty.structFieldOffset(field_index, mod);
2839628438 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
2839728439 }
2839828440 } else {
2839928441 deref.parent = null;
28400 deref.ty_without_well_defined_layout = field_ptr.container_ty;
28442 deref.ty_without_well_defined_layout = container_ty;
2840128443 }
2840228444
2840328445 const tv = deref.pointee orelse {
......@@ -28405,294 +28447,40 @@ fn beginComptimePtrLoad(
2840528447 break :blk deref;
2840628448 };
2840728449 const coerce_in_mem_ok =
28408 (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28409 (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok;
28450 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28451 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
2841028452 if (!coerce_in_mem_ok) {
2841128453 deref.pointee = null;
2841228454 break :blk deref;
2841328455 }
2841428456
28415 if (field_ptr.container_ty.isSlice(mod)) {
28416 const slice_val = tv.val.castTag(.slice).?.data;
28457 if (container_ty.isSlice(mod)) {
2841728458 deref.pointee = switch (field_index) {
28418 Value.Payload.Slice.ptr_index => TypedValue{
28419 .ty = field_ptr.container_ty.slicePtrFieldType(mod),
28420 .val = slice_val.ptr,
28459 Value.slice_ptr_index => TypedValue{
28460 .ty = container_ty.slicePtrFieldType(mod),
28461 .val = tv.val.slicePtr(mod),
2842128462 },
28422 Value.Payload.Slice.len_index => TypedValue{
28463 Value.slice_len_index => TypedValue{
2842328464 .ty = Type.usize,
28424 .val = slice_val.len,
28465 .val = mod.intern_pool.indexToKey(tv.val.ip_index).ptr.len.toValue(),
2842528466 },
2842628467 else => unreachable,
2842728468 };
2842828469 } else {
28429 const field_ty = field_ptr.container_ty.structFieldType(field_index, mod);
28470 const field_ty = container_ty.structFieldType(field_index, mod);
2843028471 deref.pointee = TypedValue{
2843128472 .ty = field_ty,
28432 .val = try tv.val.fieldValue(tv.ty, mod, field_index),
28473 .val = try tv.val.fieldValue(mod, field_index),
2843328474 };
2843428475 }
2843528476 break :blk deref;
2843628477 },
28437
28438 .comptime_field_ptr => blk: {
28439 const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data;
28440 break :blk ComptimePtrLoadKit{
28441 .parent = null,
28442 .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val },
28443 .is_mutable = false,
28444 .ty_without_well_defined_layout = comptime_field_ptr.field_ty,
28445 };
28446 },
28447
28448 .opt_payload_ptr,
28449 .eu_payload_ptr,
28450 => blk: {
28451 const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
28452 const payload_ty = switch (ptr_val.tag()) {
28453 .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(mod),
28454 .opt_payload_ptr => payload_ptr.container_ty.optionalChild(mod),
28455 else => unreachable,
28456 };
28457 var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty);
28458
28459 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
28460 if (deref.parent != null) {
28461 deref.parent = null;
28462 deref.ty_without_well_defined_layout = payload_ptr.container_ty;
28463 }
28464
28465 if (deref.pointee) |*tv| {
28466 const coerce_in_mem_ok =
28467 (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28468 (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok;
28469 if (coerce_in_mem_ok) {
28470 const payload_val = switch (ptr_val.tag()) {
28471 .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
28472 return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});
28473 },
28474 .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {
28475 if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{});
28476 break :opt tv.val;
28477 },
28478 else => unreachable,
28479 };
28480 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
28481 break :blk deref;
28482 }
28483 }
28484 deref.pointee = null;
28485 break :blk deref;
28486 },
28487 .opt_payload => blk: {
28488 const opt_payload = ptr_val.castTag(.opt_payload).?.data;
28489 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
28490 },
28491
28492 .variable,
28493 .extern_fn,
28494 .function,
28495 => return error.RuntimeLoad,
28496
28497 else => unreachable,
2849828478 },
28499 else => switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
28500 .int => return error.RuntimeLoad,
28501 .ptr => |ptr| switch (ptr.addr) {
28502 .@"var", .int => return error.RuntimeLoad,
28503 .decl, .mut_decl => blk: {
28504 const decl_index = switch (ptr.addr) {
28505 .decl => |decl| decl,
28506 .mut_decl => |mut_decl| mut_decl.decl,
28507 else => unreachable,
28508 };
28509 const decl = mod.declPtr(decl_index);
28510 const decl_tv = try decl.typedValue();
28511 if (decl_tv.val.tagIsVariable()) return error.RuntimeLoad;
28512
28513 const layout_defined = decl.ty.hasWellDefinedLayout(mod);
28514 break :blk ComptimePtrLoadKit{
28515 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
28516 .pointee = decl_tv,
28517 .is_mutable = false,
28518 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
28519 };
28520 },
28521 .eu_payload, .opt_payload => |container_ptr| blk: {
28522 const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
28523 const payload_ty = ptr.ty.toType().childType(mod);
28524 var deref = try sema.beginComptimePtrLoad(block, src, container_ptr.toValue(), container_ty);
28525
28526 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
28527 if (deref.parent != null) {
28528 deref.parent = null;
28529 deref.ty_without_well_defined_layout = container_ty;
28530 }
28531
28532 if (deref.pointee) |*tv| {
28533 const coerce_in_mem_ok =
28534 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28535 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28536 if (coerce_in_mem_ok) {
28537 const payload_val = switch (ptr_val.tag()) {
28538 .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
28539 return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});
28540 },
28541 .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {
28542 if (tv.val.isNull(mod)) return sema.fail(block, src, "attempt to use null value", .{});
28543 break :opt tv.val;
28544 },
28545 else => unreachable,
28546 };
28547 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
28548 break :blk deref;
28549 }
28550 }
28551 deref.pointee = null;
28552 break :blk deref;
28553 },
28554 .comptime_field => |comptime_field| blk: {
28555 const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
28556 break :blk ComptimePtrLoadKit{
28557 .parent = null,
28558 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
28559 .is_mutable = false,
28560 .ty_without_well_defined_layout = field_ty,
28561 };
28562 },
28563 .elem => |elem_ptr| blk: {
28564 const elem_ty = ptr.ty.toType().childType(mod);
28565 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
28566
28567 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
28568 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
28569 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
28570 switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
28571 .ptr => |base_ptr| switch (base_ptr.addr) {
28572 .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
28573 else => {},
28574 },
28575 else => {},
28576 }
28577
28578 if (elem_ptr.index != 0) {
28579 if (elem_ty.hasWellDefinedLayout(mod)) {
28580 if (deref.parent) |*parent| {
28581 // Update the byte offset (in-place)
28582 const elem_size = try sema.typeAbiSize(elem_ty);
28583 const offset = parent.byte_offset + elem_size * elem_ptr.index;
28584 parent.byte_offset = try sema.usizeCast(block, src, offset);
28585 }
28586 } else {
28587 deref.parent = null;
28588 deref.ty_without_well_defined_layout = elem_ty;
28589 }
28590 }
28591
28592 // If we're loading an elem that was derived from a different type
28593 // than the true type of the underlying decl, we cannot deref directly
28594 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
28595 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
28596 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
28597 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
28598 } else false;
28599 if (!ty_matches) {
28600 deref.pointee = null;
28601 break :blk deref;
28602 }
28603
28604 var array_tv = deref.pointee.?;
28605 const check_len = array_tv.ty.arrayLenIncludingSentinel(mod);
28606 if (maybe_array_ty) |load_ty| {
28607 // It's possible that we're loading a [N]T, in which case we'd like to slice
28608 // the pointee array directly from our parent array.
28609 if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) {
28610 const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod));
28611 deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{
28612 .ty = try Type.array(sema.arena, N, null, elem_ty, mod),
28613 .val = try array_tv.val.sliceArray(mod, sema.arena, elem_ptr.index, elem_ptr.index + N),
28614 } else null;
28615 break :blk deref;
28616 }
28617 }
28618
28619 if (elem_ptr.index >= check_len) {
28620 deref.pointee = null;
28621 break :blk deref;
28622 }
28623 if (elem_ptr.index == check_len - 1) {
28624 if (array_tv.ty.sentinel(mod)) |sent| {
28625 deref.pointee = TypedValue{
28626 .ty = elem_ty,
28627 .val = sent,
28628 };
28629 break :blk deref;
28630 }
28631 }
28632 deref.pointee = TypedValue{
28633 .ty = elem_ty,
28634 .val = try array_tv.val.elemValue(mod, elem_ptr.index),
28635 };
28636 break :blk deref;
28637 },
28638 .field => |field_ptr| blk: {
28639 const field_index = @intCast(u32, field_ptr.index);
28640 const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
28641 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
28642
28643 if (container_ty.hasWellDefinedLayout(mod)) {
28644 const struct_obj = mod.typeToStruct(container_ty);
28645 if (struct_obj != null and struct_obj.?.layout == .Packed) {
28646 // packed structs are not byte addressable
28647 deref.parent = null;
28648 } else if (deref.parent) |*parent| {
28649 // Update the byte offset (in-place)
28650 try sema.resolveTypeLayout(container_ty);
28651 const field_offset = container_ty.structFieldOffset(field_index, mod);
28652 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
28653 }
28654 } else {
28655 deref.parent = null;
28656 deref.ty_without_well_defined_layout = container_ty;
28657 }
28658
28659 const tv = deref.pointee orelse {
28660 deref.pointee = null;
28661 break :blk deref;
28662 };
28663 const coerce_in_mem_ok =
28664 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28665 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28666 if (!coerce_in_mem_ok) {
28667 deref.pointee = null;
28668 break :blk deref;
28669 }
28670
28671 if (container_ty.isSlice(mod)) {
28672 const slice_val = tv.val.castTag(.slice).?.data;
28673 deref.pointee = switch (field_index) {
28674 Value.Payload.Slice.ptr_index => TypedValue{
28675 .ty = container_ty.slicePtrFieldType(mod),
28676 .val = slice_val.ptr,
28677 },
28678 Value.Payload.Slice.len_index => TypedValue{
28679 .ty = Type.usize,
28680 .val = slice_val.len,
28681 },
28682 else => unreachable,
28683 };
28684 } else {
28685 const field_ty = container_ty.structFieldType(field_index, mod);
28686 deref.pointee = TypedValue{
28687 .ty = field_ty,
28688 .val = try tv.val.fieldValue(tv.ty, mod, field_index),
28689 };
28690 }
28691 break :blk deref;
28692 },
28693 },
28694 else => unreachable,
28479 .opt => |opt| switch (opt.val) {
28480 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28481 else => try sema.beginComptimePtrLoad(block, src, opt.val.toValue(), null),
2869528482 },
28483 else => unreachable,
2869628484 };
2869728485
2869828486 if (deref.pointee) |tv| {
......@@ -28853,7 +28641,7 @@ fn coerceCompatiblePtrs(
2885328641 }
2885428642 // The comptime Value representation is compatible with both types.
2885528643 return sema.addConstant(dest_ty, (try mod.intern_pool.getCoerced(
28856 mod.gpa,
28644 sema.gpa,
2885728645 try val.intern(inst_ty, mod),
2885828646 dest_ty.ip_index,
2885928647 )).toValue());
......@@ -29538,7 +29326,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
2953829326 };
2953929327}
2954029328
29541fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
29329fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
2954229330 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
2954329331 if (sema.owner_func) |owner_func| {
2954429332 owner_func.state = .dependency_failure;
......@@ -29550,6 +29338,7 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
2955029338}
2955129339
2955229340fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
29341 const mod = sema.mod;
2955329342 var anon_decl = try block.startAnonDecl();
2955429343 defer anon_decl.deinit();
2955529344 const decl = try anon_decl.finish(
......@@ -29558,15 +29347,23 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
2955829347 0, // default alignment
2955929348 );
2956029349 try sema.maybeQueueFuncBodyAnalysis(decl);
29561 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);
29562 return try Value.Tag.decl_ref.create(sema.arena, decl);
29350 try mod.declareDeclDependency(sema.owner_decl_index, decl);
29351 const result = try mod.intern(.{ .ptr = .{
29352 .ty = (try mod.singleConstPtrType(ty)).ip_index,
29353 .addr = .{ .decl = decl },
29354 } });
29355 return result.toValue();
2956329356}
2956429357
2956529358fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
29359 const mod = sema.mod;
2956629360 const val = opt_val orelse return Value.null;
2956729361 const ptr_val = try sema.refValue(block, ty, val);
29568 const result = try Value.Tag.opt_payload.create(sema.arena, ptr_val);
29569 return result;
29362 const result = try mod.intern(.{ .opt = .{
29363 .ty = (try mod.optionalType((try mod.singleConstPtrType(ty)).ip_index)).ip_index,
29364 .val = ptr_val.ip_index,
29365 } });
29366 return result.toValue();
2957029367}
2957129368
2957229369fn 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
2958729384 const ptr_ty = try mod.ptrType(.{
2958829385 .elem_type = decl_tv.ty.ip_index,
2958929386 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29590 .is_const = if (decl_tv.val.castTag(.variable)) |payload|
29591 !payload.data.is_mutable
29592 else
29593 false,
29387 .is_const = if (decl.getVariable(mod)) |variable| variable.is_const else false,
2959429388 .address_space = decl.@"addrspace",
2959529389 });
2959629390 if (analyze_fn_body) {
......@@ -29608,8 +29402,8 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
2960829402 const tv = try decl.typedValue();
2960929403 if (tv.ty.zigTypeTag(mod) != .Fn) return;
2961029404 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
29611 const func = tv.val.castTag(.function) orelse return; // undef or extern_fn
29612 try mod.ensureFuncBodyAnalysisQueued(func.data);
29405 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
29406 try mod.ensureFuncBodyAnalysisQueued(func_index);
2961329407}
2961429408
2961529409fn analyzeRef(
......@@ -29622,14 +29416,12 @@ fn analyzeRef(
2962229416
2962329417 if (try sema.resolveMaybeUndefVal(operand)) |val| {
2962429418 switch (val.ip_index) {
29625 .none => switch (val.tag()) {
29626 .extern_fn, .function => {
29627 const decl_index = val.pointerDecl().?;
29628 return sema.analyzeDeclRef(decl_index);
29629 },
29419 .none => {},
29420 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
29421 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
29422 .func => |func| return sema.analyzeDeclRef(sema.mod.funcPtr(func.index).owner_decl),
2963029423 else => {},
2963129424 },
29632 else => {},
2963329425 }
2963429426 var anon_decl = try block.startAnonDecl();
2963529427 defer anon_decl.deinit();
......@@ -29854,7 +29646,7 @@ fn analyzeIsNonErrComptimeOnly(
2985429646
2985529647 if (other_ies.errors.count() != 0) break :blk;
2985629648 }
29857 if (ies.func == sema.owner_func) {
29649 if (ies.func == sema.owner_func_index.unwrap()) {
2985829650 // We're checking the inferred errorset of the current function and none of
2985929651 // its child inferred error sets contained any errors meaning that any value
2986029652 // so far with this type can't contain errors either.
......@@ -29873,7 +29665,7 @@ fn analyzeIsNonErrComptimeOnly(
2987329665 if (err_union.isUndef(mod)) {
2987429666 return sema.addConstUndef(Type.bool);
2987529667 }
29876 if (err_union.getError() == null) {
29668 if (err_union.getError(mod) == null) {
2987729669 return Air.Inst.Ref.bool_true;
2987829670 } else {
2987929671 return Air.Inst.Ref.bool_false;
......@@ -30137,7 +29929,7 @@ fn analyzeSlice(
3013729929 const end_int = end_val.getUnsignedInt(mod).?;
3013829930 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
3013929931
30140 const elem_ptr = try ptr_val.elemPtr(new_ptr_ty, sema.arena, sentinel_index, sema.mod);
29932 const elem_ptr = try ptr_val.elemPtr(new_ptr_ty, sentinel_index, sema.mod);
3014129933 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);
3014229934 const actual_sentinel = switch (res) {
3014329935 .runtime_load => break :sentinel_check,
......@@ -30233,7 +30025,7 @@ fn analyzeSlice(
3023330025
3023430026 if (!new_ptr_val.isUndef(mod)) {
3023530027 return sema.addConstant(return_ty, (try mod.intern_pool.getCoerced(
30236 mod.gpa,
30028 sema.gpa,
3023730029 try new_ptr_val.intern(new_ptr_ty, mod),
3023830030 return_ty.ip_index,
3023930031 )).toValue());
......@@ -30753,7 +30545,10 @@ fn wrapOptional(
3075330545 inst_src: LazySrcLoc,
3075430546) !Air.Inst.Ref {
3075530547 if (try sema.resolveMaybeUndefVal(inst)) |val| {
30756 return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, val));
30548 return sema.addConstant(dest_ty, (try sema.mod.intern(.{ .opt = .{
30549 .ty = dest_ty.ip_index,
30550 .val = val.ip_index,
30551 } })).toValue());
3075730552 }
3075830553
3075930554 try sema.requireRuntimeBlock(block, inst_src, null);
......@@ -30771,7 +30566,10 @@ fn wrapErrorUnionPayload(
3077130566 const dest_payload_ty = dest_ty.errorUnionPayload(mod);
3077230567 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });
3077330568 if (try sema.resolveMaybeUndefVal(coerced)) |val| {
30774 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
30569 return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{
30570 .ty = dest_ty.ip_index,
30571 .val = .{ .payload = val.ip_index },
30572 } })).toValue());
3077530573 }
3077630574 try sema.requireRuntimeBlock(block, inst_src, null);
3077730575 try sema.queueFullTypeResolution(dest_payload_ty);
......@@ -30794,27 +30592,20 @@ fn wrapErrorUnionSet(
3079430592 .anyerror_type => {},
3079530593 else => switch (ip.indexToKey(dest_err_set_ty.ip_index)) {
3079630594 .error_set_type => |error_set_type| ok: {
30797 const expected_name = val.castTag(.@"error").?.data.name;
30798 if (ip.getString(expected_name).unwrap()) |expected_name_interned| {
30799 if (error_set_type.nameIndex(ip, expected_name_interned) != null)
30800 break :ok;
30801 }
30595 const expected_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
30596 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
3080230597 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
3080330598 },
3080430599 .inferred_error_set_type => |ies_index| ok: {
3080530600 const ies = mod.inferredErrorSetPtr(ies_index);
30806 const expected_name = val.castTag(.@"error").?.data.name;
30601 const expected_name = mod.intern_pool.indexToKey(val.ip_index).err.name;
3080730602
3080830603 // We carefully do this in an order that avoids unnecessarily
3080930604 // resolving the destination error set type.
3081030605 if (ies.is_anyerror) break :ok;
3081130606
30812 if (ip.getString(expected_name).unwrap()) |expected_name_interned| {
30813 if (ies.errors.contains(expected_name_interned)) break :ok;
30814 }
30815 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
30816 break :ok;
30817 }
30607 if (ies.errors.contains(expected_name)) break :ok;
30608 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
3081830609
3081930610 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
3082030611 },
......@@ -31462,43 +31253,33 @@ pub fn resolveFnTypes(sema: *Sema, fn_info: InternPool.Key.FuncType) CompileErro
3146231253/// to a type not having its layout resolved.
3146331254fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {
3146431255 switch (val.ip_index) {
31465 .none => switch (val.tag()) {
31466 .lazy_align => {
31467 const ty = val.castTag(.lazy_align).?.data;
31468 return sema.resolveTypeLayout(ty);
31469 },
31470 .lazy_size => {
31471 const ty = val.castTag(.lazy_size).?.data;
31472 return sema.resolveTypeLayout(ty);
31473 },
31474 .comptime_field_ptr => {
31475 const field_ptr = val.castTag(.comptime_field_ptr).?.data;
31476 return sema.resolveLazyValue(field_ptr.field_val);
31477 },
31478 .eu_payload,
31479 .opt_payload,
31480 => {
31481 const sub_val = val.cast(Value.Payload.SubValue).?.data;
31482 return sema.resolveLazyValue(sub_val);
31483 },
31484 .@"union" => {
31485 const union_val = val.castTag(.@"union").?.data;
31486 return sema.resolveLazyValue(union_val.val);
31487 },
31488 .aggregate => {
31489 const aggregate = val.castTag(.aggregate).?.data;
31490 for (aggregate) |elem_val| {
31491 try sema.resolveLazyValue(elem_val);
31492 }
31493 },
31494 .slice => {
31495 const slice = val.castTag(.slice).?.data;
31496 try sema.resolveLazyValue(slice.ptr);
31497 return sema.resolveLazyValue(slice.len);
31256 .none => {},
31257 else => switch (sema.mod.intern_pool.indexToKey(val.ip_index)) {
31258 .int => |int| switch (int.storage) {
31259 .u64, .i64, .big_int => {},
31260 .lazy_align, .lazy_size => |lazy_ty| try sema.resolveTypeLayout(lazy_ty.toType()),
31261 },
31262 .ptr => |ptr| {
31263 switch (ptr.addr) {
31264 .decl, .mut_decl => {},
31265 .int => |int| try sema.resolveLazyValue(int.toValue()),
31266 .eu_payload, .opt_payload => |base| try sema.resolveLazyValue(base.toValue()),
31267 .comptime_field => |comptime_field| try sema.resolveLazyValue(comptime_field.toValue()),
31268 .elem, .field => |base_index| try sema.resolveLazyValue(base_index.base.toValue()),
31269 }
31270 if (ptr.len != .none) try sema.resolveLazyValue(ptr.len.toValue());
31271 },
31272 .aggregate => |aggregate| switch (aggregate.storage) {
31273 .bytes => {},
31274 .elems => |elems| for (elems) |elem| try sema.resolveLazyValue(elem.toValue()),
31275 .repeated_elem => |elem| try sema.resolveLazyValue(elem.toValue()),
31276 },
31277 .un => |un| {
31278 try sema.resolveLazyValue(un.tag.toValue());
31279 try sema.resolveLazyValue(un.val.toValue());
3149831280 },
31499 else => return,
31281 else => {},
3150031282 },
31501 else => return,
3150231283 }
3150331284}
3150431285
......@@ -31597,7 +31378,7 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3159731378 else blk: {
3159831379 const decl = mod.declPtr(struct_obj.owner_decl);
3159931380 var decl_arena: std.heap.ArenaAllocator = undefined;
31600 const decl_arena_allocator = decl.value_arena.?.acquire(mod.gpa, &decl_arena);
31381 const decl_arena_allocator = decl.value_arena.?.acquire(sema.gpa, &decl_arena);
3160131382 defer decl.value_arena.?.release(&decl_arena);
3160231383 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
3160331384 };
......@@ -31662,18 +31443,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3166231443 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3166331444 defer analysis_arena.deinit();
3166431445
31665 var sema: Sema = .{
31666 .mod = mod,
31667 .gpa = gpa,
31668 .arena = analysis_arena.allocator(),
31669 .perm_arena = decl_arena_allocator,
31670 .code = zir,
31671 .owner_decl = decl,
31672 .owner_decl_index = decl_index,
31673 .func = null,
31674 .fn_ret_ty = Type.void,
31675 .owner_func = null,
31676 };
31446 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 };
3167731447 defer sema.deinit();
3167831448
3167931449 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
3172031490 .owner_decl = decl,
3172131491 .owner_decl_index = decl_index,
3172231492 .func = null,
31493 .func_index = .none,
3172331494 .fn_ret_ty = Type.void,
3172431495 .owner_func = null,
31496 .owner_func_index = .none,
3172531497 };
3172631498 defer sema.deinit();
3172731499
......@@ -31974,16 +31746,23 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3197431746 .enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),
3197531747
3197631748 // values, not types
31977 .undef => unreachable,
31978 .un => unreachable,
31979 .simple_value => unreachable,
31980 .extern_func => unreachable,
31981 .int => unreachable,
31982 .float => unreachable,
31983 .ptr => unreachable,
31984 .opt => unreachable,
31985 .enum_tag => unreachable,
31986 .aggregate => unreachable,
31749 .undef,
31750 .runtime_value,
31751 .simple_value,
31752 .variable,
31753 .extern_func,
31754 .func,
31755 .int,
31756 .err,
31757 .error_union,
31758 .enum_literal,
31759 .enum_tag,
31760 .float,
31761 .ptr,
31762 .opt,
31763 .aggregate,
31764 .un,
31765 => unreachable,
3198731766 },
3198831767 };
3198931768}
......@@ -32141,8 +31920,8 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
3214131920 .manyptr_const_u8_type,
3214231921 .manyptr_const_u8_sentinel_0_type,
3214331922 .single_const_pointer_to_comptime_int_type,
32144 .const_slice_u8_type,
32145 .const_slice_u8_sentinel_0_type,
31923 .slice_const_u8_type,
31924 .slice_const_u8_sentinel_0_type,
3214631925 .anyerror_void_error_union_type,
3214731926 .generic_poison_type,
3214831927 .empty_struct_type,
......@@ -32288,18 +32067,19 @@ fn resolveInferredErrorSet(
3228832067
3228932068 if (ies.is_resolved) return;
3229032069
32291 if (ies.func.state == .in_progress) {
32070 const func = mod.funcPtr(ies.func);
32071 if (func.state == .in_progress) {
3229232072 return sema.fail(block, src, "unable to resolve inferred error set", .{});
3229332073 }
3229432074
3229532075 // In order to ensure that all dependencies are properly added to the set, we
3229632076 // need to ensure the function body is analyzed of the inferred error set.
3229732077 // However, in the case of comptime/inline function calls with inferred error sets,
32298 // each call gets a new InferredErrorSet object, which points to the same
32299 // `*Module.Fn`. Not only is the function not relevant to the inferred error set
32078 // each call gets a new InferredErrorSet object, which contains the same
32079 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
3230032080 // in this case, it may be a generic function which would cause an assertion failure
3230132081 // if we called `ensureFuncBodyAnalyzed` on it here.
32302 const ies_func_owner_decl = mod.declPtr(ies.func.owner_decl);
32082 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
3230332083 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
3230432084 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
3230532085 // 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
3241432194 .owner_decl = decl,
3241532195 .owner_decl_index = decl_index,
3241632196 .func = null,
32197 .func_index = .none,
3241732198 .fn_ret_ty = Type.void,
3241832199 .owner_func = null,
32200 .owner_func_index = .none,
3241932201 };
3242032202 defer sema.deinit();
3242132203
......@@ -32754,8 +32536,10 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3275432536 .owner_decl = decl,
3275532537 .owner_decl_index = decl_index,
3275632538 .func = null,
32539 .func_index = .none,
3275732540 .fn_ret_ty = Type.void,
3275832541 .owner_func = null,
32542 .owner_func_index = .none,
3275932543 };
3276032544 defer sema.deinit();
3276132545
......@@ -33111,7 +32895,7 @@ fn generateUnionTagTypeNumbered(
3311132895 const name = name: {
3311232896 const fqn = try union_obj.getFullyQualifiedName(mod);
3311332897 defer sema.gpa.free(fqn);
33114 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32898 break :name try std.fmt.allocPrintZ(sema.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
3311532899 };
3311632900 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
3311732901 .ty = Type.type,
......@@ -33160,7 +32944,7 @@ fn generateUnionTagTypeSimple(
3316032944 const name = name: {
3316132945 const fqn = try union_obj.getFullyQualifiedName(mod);
3316232946 defer sema.gpa.free(fqn);
33163 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32947 break :name try std.fmt.allocPrintZ(sema.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
3316432948 };
3316532949 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
3316632950 .ty = Type.type,
......@@ -33288,19 +33072,19 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3328833072 .inferred_error_set_type,
3328933073 => null,
3329033074
33291 .array_type => |array_type| {
33292 if (array_type.len == 0)
33293 return Value.initTag(.empty_array);
33294 if ((try sema.typeHasOnePossibleValue(array_type.child.toType())) != null) {
33295 return Value.initTag(.the_only_possible_value);
33075 inline .array_type, .vector_type => |seq_type| {
33076 if (seq_type.len == 0) return (try mod.intern(.{ .aggregate = .{
33077 .ty = ty.ip_index,
33078 .storage = .{ .elems = &.{} },
33079 } })).toValue();
33080 if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {
33081 return (try mod.intern(.{ .aggregate = .{
33082 .ty = ty.ip_index,
33083 .storage = .{ .repeated_elem = opv.ip_index },
33084 } })).toValue();
3329633085 }
3329733086 return null;
3329833087 },
33299 .vector_type => |vector_type| {
33300 if (vector_type.len == 0) return Value.initTag(.empty_array);
33301 if (try sema.typeHasOnePossibleValue(vector_type.child.toType())) |v| return v;
33302 return null;
33303 },
3330433088 .opt_type => |child| {
3330533089 if (child == .noreturn_type) {
3330633090 return try mod.nullValue(ty);
......@@ -33466,16 +33250,23 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3346633250 },
3346733251
3346833252 // values, not types
33469 .undef => unreachable,
33470 .un => unreachable,
33471 .simple_value => unreachable,
33472 .extern_func => unreachable,
33473 .int => unreachable,
33474 .float => unreachable,
33475 .ptr => unreachable,
33476 .opt => unreachable,
33477 .enum_tag => unreachable,
33478 .aggregate => unreachable,
33253 .undef,
33254 .runtime_value,
33255 .simple_value,
33256 .variable,
33257 .extern_func,
33258 .func,
33259 .int,
33260 .err,
33261 .error_union,
33262 .enum_literal,
33263 .enum_tag,
33264 .float,
33265 .ptr,
33266 .opt,
33267 .aggregate,
33268 .un,
33269 => unreachable,
3347933270 },
3348033271 };
3348133272}
......@@ -33625,10 +33416,13 @@ fn analyzeComptimeAlloc(
3362533416 decl.@"align" = alignment;
3362633417
3362733418 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
33628 return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
33629 .runtime_index = block.runtime_index,
33630 .decl_index = decl_index,
33631 }));
33419 return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
33420 .ty = ptr_type.ip_index,
33421 .addr = .{ .mut_decl = .{
33422 .decl = decl_index,
33423 .runtime_index = block.runtime_index,
33424 } },
33425 } })).toValue());
3363233426}
3363333427
3363433428/// The places where a user can specify an address space attribute
......@@ -33969,16 +33763,23 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3396933763 .enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),
3397033764
3397133765 // values, not types
33972 .undef => unreachable,
33973 .un => unreachable,
33974 .simple_value => unreachable,
33975 .extern_func => unreachable,
33976 .int => unreachable,
33977 .float => unreachable,
33978 .ptr => unreachable,
33979 .opt => unreachable,
33980 .enum_tag => unreachable,
33981 .aggregate => unreachable,
33766 .undef,
33767 .runtime_value,
33768 .simple_value,
33769 .variable,
33770 .extern_func,
33771 .func,
33772 .int,
33773 .err,
33774 .error_union,
33775 .enum_literal,
33776 .enum_tag,
33777 .float,
33778 .ptr,
33779 .opt,
33780 .aggregate,
33781 .un,
33782 => unreachable,
3398233783 },
3398333784 };
3398433785}
......@@ -34337,8 +34138,9 @@ fn intFitsInType(
3433734138 ty: Type,
3433834139 vector_index: ?*usize,
3433934140) CompileError!bool {
34340 if (ty.ip_index == .comptime_int_type) return true;
3434134141 const mod = sema.mod;
34142 if (ty.ip_index == .comptime_int_type) return true;
34143 const info = ty.intInfo(mod);
3434234144 switch (val.ip_index) {
3434334145 .undef,
3434434146 .zero,
......@@ -34346,40 +34148,8 @@ fn intFitsInType(
3434634148 .zero_u8,
3434734149 => return true,
3434834150
34349 .none => switch (val.tag()) {
34350 .lazy_align => {
34351 const info = ty.intInfo(mod);
34352 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34353 // If it is u16 or bigger we know the alignment fits without resolving it.
34354 if (info.bits >= max_needed_bits) return true;
34355 const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data);
34356 if (x == 0) return true;
34357 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34358 return info.bits >= actual_needed_bits;
34359 },
34360 .lazy_size => {
34361 const info = ty.intInfo(mod);
34362 const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
34363 // If it is u64 or bigger we know the size fits without resolving it.
34364 if (info.bits >= max_needed_bits) return true;
34365 const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data);
34366 if (x == 0) return true;
34367 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34368 return info.bits >= actual_needed_bits;
34369 },
34370
34371 .the_only_possible_value => {
34372 assert(ty.intInfo(mod).bits == 0);
34373 return true;
34374 },
34375
34376 .decl_ref_mut,
34377 .extern_fn,
34378 .decl_ref,
34379 .function,
34380 .variable,
34381 => {
34382 const info = ty.intInfo(mod);
34151 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
34152 .variable, .extern_func, .func, .ptr => {
3438334153 const target = mod.getTarget();
3438434154 const ptr_bits = target.ptrBitWidth();
3438534155 return switch (info.signedness) {
......@@ -34387,27 +34157,51 @@ fn intFitsInType(
3438734157 .unsigned => info.bits >= ptr_bits,
3438834158 };
3438934159 },
34390
34391 .aggregate => {
34392 assert(ty.zigTypeTag(mod) == .Vector);
34393 for (val.castTag(.aggregate).?.data, 0..) |elem, i| {
34394 if (!(try sema.intFitsInType(elem, ty.scalarType(mod), null))) {
34395 if (vector_index) |some| some.* = i;
34396 return false;
34397 }
34398 }
34399 return true;
34160 .int => |int| switch (int.storage) {
34161 .u64, .i64, .big_int => {
34162 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
34163 const big_int = int.storage.toBigInt(&buffer);
34164 return big_int.fitsInTwosComp(info.signedness, info.bits);
34165 },
34166 .lazy_align => |lazy_ty| {
34167 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34168 // If it is u16 or bigger we know the alignment fits without resolving it.
34169 if (info.bits >= max_needed_bits) return true;
34170 const x = try sema.typeAbiAlignment(lazy_ty.toType());
34171 if (x == 0) return true;
34172 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34173 return info.bits >= actual_needed_bits;
34174 },
34175 .lazy_size => |lazy_ty| {
34176 const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
34177 // If it is u64 or bigger we know the size fits without resolving it.
34178 if (info.bits >= max_needed_bits) return true;
34179 const x = try sema.typeAbiSize(lazy_ty.toType());
34180 if (x == 0) return true;
34181 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34182 return info.bits >= actual_needed_bits;
34183 },
3440034184 },
34401
34402 else => unreachable,
34403 },
34404
34405 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
34406 .int => |int| {
34407 const info = ty.intInfo(mod);
34408 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
34409 const big_int = int.storage.toBigInt(&buffer);
34410 return big_int.fitsInTwosComp(info.signedness, info.bits);
34185 .aggregate => |aggregate| {
34186 assert(ty.zigTypeTag(mod) == .Vector);
34187 return switch (aggregate.storage) {
34188 .bytes => |bytes| for (bytes, 0..) |byte, i| {
34189 if (byte == 0) continue;
34190 const actual_needed_bits = std.math.log2(byte) + 1 + @boolToInt(info.signedness == .signed);
34191 if (info.bits >= actual_needed_bits) continue;
34192 if (vector_index) |vi| vi.* = i;
34193 break false;
34194 } else true,
34195 .elems, .repeated_elem => for (switch (aggregate.storage) {
34196 .bytes => unreachable,
34197 .elems => |elems| elems,
34198 .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem),
34199 }, 0..) |elem, i| {
34200 if (try sema.intFitsInType(elem.toValue(), ty.scalarType(mod), null)) continue;
34201 if (vector_index) |vi| vi.* = i;
34202 break false;
34203 } else true,
34204 };
3441134205 },
3441234206 else => unreachable,
3441334207 },
src/TypedValue.zig+9-236
......@@ -102,248 +102,15 @@ pub fn print(
102102
103103 return writer.writeAll(" }");
104104 },
105 .the_only_possible_value => return writer.writeAll("0"),
106 .lazy_align => {
107 const sub_ty = val.castTag(.lazy_align).?.data;
108 const x = sub_ty.abiAlignment(mod);
109 return writer.print("{d}", .{x});
110 },
111 .lazy_size => {
112 const sub_ty = val.castTag(.lazy_size).?.data;
113 const x = sub_ty.abiSize(mod);
114 return writer.print("{d}", .{x});
115 },
116 .function => return writer.print("(function '{s}')", .{
117 mod.declPtr(val.castTag(.function).?.data.owner_decl).name,
118 }),
119 .extern_fn => return writer.writeAll("(extern function)"),
120 .variable => unreachable,
121 .decl_ref_mut => {
122 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
123 const decl = mod.declPtr(decl_index);
124 if (level == 0) {
125 return writer.print("(decl ref mut '{s}')", .{decl.name});
126 }
127 return print(.{
128 .ty = decl.ty,
129 .val = decl.val,
130 }, writer, level - 1, mod);
131 },
132 .decl_ref => {
133 const decl_index = val.castTag(.decl_ref).?.data;
134 const decl = mod.declPtr(decl_index);
135 if (level == 0) {
136 return writer.print("(decl ref '{s}')", .{decl.name});
137 }
138 return print(.{
139 .ty = decl.ty,
140 .val = decl.val,
141 }, writer, level - 1, mod);
142 },
143 .comptime_field_ptr => {
144 const payload = val.castTag(.comptime_field_ptr).?.data;
145 if (level == 0) {
146 return writer.writeAll("(comptime field ptr)");
147 }
148 return print(.{
149 .ty = payload.field_ty,
150 .val = payload.field_val,
151 }, writer, level - 1, mod);
152 },
153 .elem_ptr => {
154 const elem_ptr = val.castTag(.elem_ptr).?.data;
155 try writer.writeAll("&");
156 if (level == 0) {
157 try writer.writeAll("(ptr)");
158 } else {
159 try print(.{
160 .ty = elem_ptr.elem_ty,
161 .val = elem_ptr.array_ptr,
162 }, writer, level - 1, mod);
163 }
164 return writer.print("[{}]", .{elem_ptr.index});
165 },
166 .field_ptr => {
167 const field_ptr = val.castTag(.field_ptr).?.data;
168 try writer.writeAll("&");
169 if (level == 0) {
170 try writer.writeAll("(ptr)");
171 } else {
172 try print(.{
173 .ty = field_ptr.container_ty,
174 .val = field_ptr.container_ptr,
175 }, writer, level - 1, mod);
176 }
177
178 if (field_ptr.container_ty.zigTypeTag(mod) == .Struct) {
179 switch (mod.intern_pool.indexToKey(field_ptr.container_ty.ip_index)) {
180 .anon_struct_type => |anon_struct| {
181 if (anon_struct.names.len == 0) {
182 return writer.print(".@\"{d}\"", .{field_ptr.field_index});
183 }
184 },
185 else => {},
186 }
187 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index, mod);
188 return writer.print(".{s}", .{field_name});
189 } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) {
190 const field_name = field_ptr.container_ty.unionFields(mod).keys()[field_ptr.field_index];
191 return writer.print(".{s}", .{field_name});
192 } else if (field_ptr.container_ty.isSlice(mod)) {
193 switch (field_ptr.field_index) {
194 Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"),
195 Value.Payload.Slice.len_index => return writer.writeAll(".len"),
196 else => unreachable,
197 }
198 }
199 },
200 .empty_array => return writer.writeAll(".{}"),
201 .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}),
202105 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
203106 .str_lit => {
204107 const str_lit = val.castTag(.str_lit).?.data;
205108 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
206109 return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)});
207110 },
208 .repeated => {
209 if (level == 0) {
210 return writer.writeAll(".{ ... }");
211 }
212 var i: u32 = 0;
213 try writer.writeAll(".{ ");
214 const elem_tv = TypedValue{
215 .ty = ty.elemType2(mod),
216 .val = val.castTag(.repeated).?.data,
217 };
218 const len = ty.arrayLen(mod);
219 const max_len = std.math.min(len, max_aggregate_items);
220 while (i < max_len) : (i += 1) {
221 if (i != 0) try writer.writeAll(", ");
222 try print(elem_tv, writer, level - 1, mod);
223 }
224 if (len > max_aggregate_items) {
225 try writer.writeAll(", ...");
226 }
227 return writer.writeAll(" }");
228 },
229 .empty_array_sentinel => {
230 if (level == 0) {
231 return writer.writeAll(".{ (sentinel) }");
232 }
233 try writer.writeAll(".{ ");
234 try print(.{
235 .ty = ty.elemType2(mod),
236 .val = ty.sentinel(mod).?,
237 }, writer, level - 1, mod);
238 return writer.writeAll(" }");
239 },
240 .slice => {
241 if (level == 0) {
242 return writer.writeAll(".{ ... }");
243 }
244 const payload = val.castTag(.slice).?.data;
245 const elem_ty = ty.elemType2(mod);
246 const len = payload.len.toUnsignedInt(mod);
247
248 if (elem_ty.eql(Type.u8, mod)) str: {
249 const max_len = @intCast(usize, std.math.min(len, max_string_len));
250 var buf: [max_string_len]u8 = undefined;
251
252 var i: u32 = 0;
253 while (i < max_len) : (i += 1) {
254 const elem_val = payload.ptr.elemValue(mod, i) catch |err| switch (err) {
255 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
256 };
257 if (elem_val.isUndef(mod)) break :str;
258 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str;
259 }
260
261 // TODO would be nice if this had a bit of unicode awareness.
262 const truncated = if (len > max_string_len) " (truncated)" else "";
263 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
264 }
265
266 try writer.writeAll(".{ ");
267
268 const max_len = std.math.min(len, max_aggregate_items);
269 var i: u32 = 0;
270 while (i < max_len) : (i += 1) {
271 if (i != 0) try writer.writeAll(", ");
272 const elem_val = payload.ptr.elemValue(mod, i) catch |err| switch (err) {
273 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
274 };
275 try print(.{
276 .ty = elem_ty,
277 .val = elem_val,
278 }, writer, level - 1, mod);
279 }
280 if (len > max_aggregate_items) {
281 try writer.writeAll(", ...");
282 }
283 return writer.writeAll(" }");
284 },
285 .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
286 .eu_payload => {
287 val = val.castTag(.eu_payload).?.data;
288 ty = ty.errorUnionPayload(mod);
289 },
290 .opt_payload => {
291 val = val.castTag(.opt_payload).?.data;
292 ty = ty.optionalChild(mod);
293 return print(.{ .ty = ty, .val = val }, writer, level, mod);
294 },
295 .eu_payload_ptr => {
296 try writer.writeAll("&");
297 if (level == 0) {
298 return writer.writeAll("(ptr)");
299 }
300
301 const data = val.castTag(.eu_payload_ptr).?.data;
302
303 try writer.writeAll("@as(");
304 try print(.{
305 .ty = Type.type,
306 .val = ty.toValue(),
307 }, writer, level - 1, mod);
308
309 try writer.writeAll(", &(payload of ");
310
311 try print(.{
312 .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"),
313 .val = data.container_ptr,
314 }, writer, level - 1, mod);
315
316 try writer.writeAll("))");
317 return;
318 },
319 .opt_payload_ptr => {
320 if (level == 0) {
321 return writer.writeAll("&(ptr)");
322 }
323
324 const data = val.castTag(.opt_payload_ptr).?.data;
325
326 try writer.writeAll("@as(");
327 try print(.{
328 .ty = Type.type,
329 .val = ty.toValue(),
330 }, writer, level - 1, mod);
331
332 try writer.writeAll(", &(payload of ");
333
334 try print(.{
335 .ty = mod.singleMutPtrType(data.container_ty) catch @panic("OOM"),
336 .val = data.container_ptr,
337 }, writer, level - 1, mod);
338
339 try writer.writeAll("))");
340 return;
341 },
342
343111 // TODO these should not appear in this function
344112 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),
345113 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),
346 .runtime_value => return writer.writeAll("[runtime value]"),
347114 },
348115 else => {
349116 const key = mod.intern_pool.indexToKey(val.ip_index);
......@@ -353,6 +120,12 @@ pub fn print(
353120 switch (key) {
354121 .int => |int| switch (int.storage) {
355122 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
123 .lazy_align => |lazy_ty| return writer.print("{d}", .{
124 lazy_ty.toType().abiAlignment(mod),
125 }),
126 .lazy_size => |lazy_ty| return writer.print("{d}", .{
127 lazy_ty.toType().abiSize(mod),
128 }),
356129 },
357130 .enum_tag => |enum_tag| {
358131 if (level == 0) {
......@@ -407,7 +180,7 @@ fn printAggregate(
407180 }
408181 try print(.{
409182 .ty = ty.structFieldType(i, mod),
410 .val = try val.fieldValue(ty, mod, i),
183 .val = try val.fieldValue(mod, i),
411184 }, writer, level - 1, mod);
412185 }
413186 if (ty.structFieldCount(mod) > max_aggregate_items) {
......@@ -424,7 +197,7 @@ fn printAggregate(
424197
425198 var i: u32 = 0;
426199 while (i < max_len) : (i += 1) {
427 const elem = try val.fieldValue(ty, mod, i);
200 const elem = try val.fieldValue(mod, i);
428201 if (elem.isUndef(mod)) break :str;
429202 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
430203 }
......@@ -441,7 +214,7 @@ fn printAggregate(
441214 if (i != 0) try writer.writeAll(", ");
442215 try print(.{
443216 .ty = elem_ty,
444 .val = try val.fieldValue(ty, mod, i),
217 .val = try val.fieldValue(mod, i),
445218 }, writer, level - 1, mod);
446219 }
447220 if (len > max_aggregate_items) {
src/Zir.zig+2-2
......@@ -2108,8 +2108,8 @@ pub const Inst = struct {
21082108 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
21092109 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
21102110 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),
2111 const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type),
2112 const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type),
2111 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
2112 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
21132113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
21142114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
21152115 inferred_alloc_const_type = @enumToInt(InternPool.Index.inferred_alloc_const_type),
src/arch/aarch64/CodeGen.zig+8-9
......@@ -328,7 +328,7 @@ const Self = @This();
328328pub fn generate(
329329 bin_file: *link.File,
330330 src_loc: Module.SrcLoc,
331 module_fn: *Module.Fn,
331 module_fn_index: Module.Fn.Index,
332332 air: Air,
333333 liveness: Liveness,
334334 code: *std.ArrayList(u8),
......@@ -339,6 +339,7 @@ pub fn generate(
339339 }
340340
341341 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
342343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
343344 assert(fn_owner_decl.has_tv);
344345 const fn_type = fn_owner_decl.ty;
......@@ -4311,9 +4312,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43114312 // Due to incremental compilation, how function calls are generated depends
43124313 // on linking.
43134314 if (try self.air.value(callee, mod)) |func_value| {
4314 if (func_value.castTag(.function)) |func_payload| {
4315 const func = func_payload.data;
4316
4315 if (func_value.getFunction(mod)) |func| {
43174316 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
43184317 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
43194318 const atom = elf_file.getAtom(atom_index);
......@@ -4353,10 +4352,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43534352 .tag = .blr,
43544353 .data = .{ .reg = .x30 },
43554354 });
4356 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4357 const extern_fn = func_payload.data;
4358 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
4359 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
4355 } else if (func_value.getExternFunc(mod)) |extern_func| {
4356 const decl_name = mem.sliceTo(mod.declPtr(extern_func.decl).name, 0);
4357 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
43604358 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43614359 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
43624360 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -4627,7 +4625,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
46274625
46284626fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
46294627 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4630 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
4628 const mod = self.bin_file.options.module.?;
4629 const function = self.air.values[ty_pl.payload].getFunction(mod).?;
46314630 // TODO emit debug info for function change
46324631 _ = function;
46334632 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/arm/CodeGen.zig+6-6
......@@ -334,7 +334,7 @@ const Self = @This();
334334pub fn generate(
335335 bin_file: *link.File,
336336 src_loc: Module.SrcLoc,
337 module_fn: *Module.Fn,
337 module_fn_index: Module.Fn.Index,
338338 air: Air,
339339 liveness: Liveness,
340340 code: *std.ArrayList(u8),
......@@ -345,6 +345,7 @@ pub fn generate(
345345 }
346346
347347 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
348349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
349350 assert(fn_owner_decl.has_tv);
350351 const fn_type = fn_owner_decl.ty;
......@@ -4291,9 +4292,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42914292 // Due to incremental compilation, how function calls are generated depends
42924293 // on linking.
42934294 if (try self.air.value(callee, mod)) |func_value| {
4294 if (func_value.castTag(.function)) |func_payload| {
4295 const func = func_payload.data;
4296
4295 if (func_value.getFunction(mod)) |func| {
42974296 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
42984297 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
42994298 const atom = elf_file.getAtom(atom_index);
......@@ -4308,7 +4307,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43084307 @tagName(self.target.cpu.arch),
43094308 });
43104309 }
4311 } else if (func_value.castTag(.extern_fn)) |_| {
4310 } else if (func_value.getExternFunc(mod)) |_| {
43124311 return self.fail("TODO implement calling extern functions", .{});
43134312 } else {
43144313 return self.fail("TODO implement calling bitcasted functions", .{});
......@@ -4573,7 +4572,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
45734572
45744573fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
45754574 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4576 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
4575 const mod = self.bin_file.options.module.?;
4576 const function = self.air.values[ty_pl.payload].getFunction(mod).?;
45774577 // TODO emit debug info for function change
45784578 _ = function;
45794579 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/riscv64/CodeGen.zig+6-5
......@@ -217,7 +217,7 @@ const Self = @This();
217217pub fn generate(
218218 bin_file: *link.File,
219219 src_loc: Module.SrcLoc,
220 module_fn: *Module.Fn,
220 module_fn_index: Module.Fn.Index,
221221 air: Air,
222222 liveness: Liveness,
223223 code: *std.ArrayList(u8),
......@@ -228,6 +228,7 @@ pub fn generate(
228228 }
229229
230230 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
231232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232233 assert(fn_owner_decl.has_tv);
233234 const fn_type = fn_owner_decl.ty;
......@@ -1745,8 +1746,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17451746 }
17461747
17471748 if (try self.air.value(callee, mod)) |func_value| {
1748 if (func_value.castTag(.function)) |func_payload| {
1749 const func = func_payload.data;
1749 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
17501750 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
17511751 const atom = elf_file.getAtom(atom_index);
17521752 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
......@@ -1760,7 +1760,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17601760 .imm12 = 0,
17611761 } },
17621762 });
1763 } else if (func_value.castTag(.extern_fn)) |_| {
1763 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
17641764 return self.fail("TODO implement calling extern functions", .{});
17651765 } else {
17661766 return self.fail("TODO implement calling bitcasted functions", .{});
......@@ -1879,7 +1879,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
18791879
18801880fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
18811881 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1882 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
1882 const mod = self.bin_file.options.module.?;
1883 const function = self.air.values[ty_pl.payload].getFunction(mod).?;
18831884 // TODO emit debug info for function change
18841885 _ = function;
18851886 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/sparc64/CodeGen.zig+6-5
......@@ -260,7 +260,7 @@ const BigTomb = struct {
260260pub fn generate(
261261 bin_file: *link.File,
262262 src_loc: Module.SrcLoc,
263 module_fn: *Module.Fn,
263 module_fn_index: Module.Fn.Index,
264264 air: Air,
265265 liveness: Liveness,
266266 code: *std.ArrayList(u8),
......@@ -271,6 +271,7 @@ pub fn generate(
271271 }
272272
273273 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
274275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275276 assert(fn_owner_decl.has_tv);
276277 const fn_type = fn_owner_decl.ty;
......@@ -1346,8 +1347,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13461347 // on linking.
13471348 if (try self.air.value(callee, mod)) |func_value| {
13481349 if (self.bin_file.tag == link.File.Elf.base_tag) {
1349 if (func_value.castTag(.function)) |func_payload| {
1350 const func = func_payload.data;
1350 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
13511351 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
13521352 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
13531353 const atom = elf_file.getAtom(atom_index);
......@@ -1374,7 +1374,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13741374 .tag = .nop,
13751375 .data = .{ .nop = {} },
13761376 });
1377 } else if (func_value.castTag(.extern_fn)) |_| {
1377 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
13781378 return self.fail("TODO implement calling extern functions", .{});
13791379 } else {
13801380 return self.fail("TODO implement calling bitcasted functions", .{});
......@@ -1663,7 +1663,8 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
16631663
16641664fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
16651665 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1666 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
1666 const mod = self.bin_file.options.module.?;
1667 const function = self.air.values[ty_pl.payload].getFunction(mod).?;
16671668 // TODO emit debug info for function change
16681669 _ = function;
16691670 return self.finishAir(inst, .dead, .{ .none, .none, .none });
src/arch/wasm/CodeGen.zig+219-132
......@@ -1203,20 +1203,22 @@ fn genFunctype(
12031203pub fn generate(
12041204 bin_file: *link.File,
12051205 src_loc: Module.SrcLoc,
1206 func: *Module.Fn,
1206 func_index: Module.Fn.Index,
12071207 air: Air,
12081208 liveness: Liveness,
12091209 code: *std.ArrayList(u8),
12101210 debug_output: codegen.DebugInfoOutput,
12111211) codegen.CodeGenError!codegen.Result {
12121212 _ = src_loc;
1213 const mod = bin_file.options.module.?;
1214 const func = mod.funcPtr(func_index);
12131215 var code_gen: CodeGen = .{
12141216 .gpa = bin_file.allocator,
12151217 .air = air,
12161218 .liveness = liveness,
12171219 .code = code,
12181220 .decl_index = func.owner_decl,
1219 .decl = bin_file.options.module.?.declPtr(func.owner_decl),
1221 .decl = mod.declPtr(func.owner_decl),
12201222 .err_msg = undefined,
12211223 .locals = .{},
12221224 .target = bin_file.options.target,
......@@ -2196,27 +2198,33 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
21962198 const callee: ?Decl.Index = blk: {
21972199 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
21982200
2199 if (func_val.castTag(.function)) |function| {
2200 _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);
2201 break :blk function.data.owner_decl;
2202 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
2203 const ext_decl = mod.declPtr(extern_fn.data.owner_decl);
2201 if (func_val.getFunction(mod)) |function| {
2202 _ = try func.bin_file.getOrCreateAtomForDecl(function.owner_decl);
2203 break :blk function.owner_decl;
2204 } else if (func_val.getExternFunc(mod)) |extern_func| {
2205 const ext_decl = mod.declPtr(extern_func.decl);
22042206 const ext_info = mod.typeToFunc(ext_decl.ty).?;
22052207 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
22062208 defer func_type.deinit(func.gpa);
2207 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);
2209 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
22082210 const atom = func.bin_file.getAtomPtr(atom_index);
2209 const type_index = try func.bin_file.storeDeclType(extern_fn.data.owner_decl, func_type);
2211 const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);
22102212 try func.bin_file.addOrUpdateImport(
22112213 mem.sliceTo(ext_decl.name, 0),
22122214 atom.getSymbolIndex().?,
2213 ext_decl.getExternFn().?.lib_name,
2215 mod.intern_pool.stringToSliceUnwrap(ext_decl.getExternFunc(mod).?.lib_name),
22142216 type_index,
22152217 );
2216 break :blk extern_fn.data.owner_decl;
2217 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
2218 _ = try func.bin_file.getOrCreateAtomForDecl(decl_ref.data);
2219 break :blk decl_ref.data;
2218 break :blk extern_func.decl;
2219 } else switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
2220 .ptr => |ptr| switch (ptr.addr) {
2221 .decl => |decl| {
2222 _ = try func.bin_file.getOrCreateAtomForDecl(decl);
2223 break :blk decl;
2224 },
2225 else => {},
2226 },
2227 else => {},
22202228 }
22212229 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});
22222230 };
......@@ -2932,29 +2940,41 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
29322940 return WValue{ .stack = {} };
29332941}
29342942
2935fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue {
2943fn lowerParentPtr(func: *CodeGen, ptr_val: Value) InnerError!WValue {
29362944 const mod = func.bin_file.base.options.module.?;
2937 switch (ptr_val.tag()) {
2938 .decl_ref_mut => {
2939 const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;
2940 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2945 const ptr = mod.intern_pool.indexToKey(ptr_val.ip_index).ptr;
2946 switch (ptr.addr) {
2947 .decl => |decl_index| {
2948 return func.lowerParentPtrDecl(ptr_val, decl_index, 0);
2949 },
2950 .mut_decl => |mut_decl| {
2951 const decl_index = mut_decl.decl;
2952 return func.lowerParentPtrDecl(ptr_val, decl_index, 0);
29412953 },
2942 .decl_ref => {
2943 const decl_index = ptr_val.castTag(.decl_ref).?.data;
2944 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2954 .int, .eu_payload => |tag| return func.fail("TODO: Implement lowerParentPtr for {}", .{tag}),
2955 .opt_payload => |base_ptr| {
2956 return func.lowerParentPtr(base_ptr.toValue());
29452957 },
2946 .variable => {
2947 const decl_index = ptr_val.castTag(.variable).?.data.owner_decl;
2948 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2958 .comptime_field => unreachable,
2959 .elem => |elem| {
2960 const index = elem.index;
2961 const elem_type = mod.intern_pool.typeOf(elem.base).toType().elemType2(mod);
2962 const offset = index * elem_type.abiSize(mod);
2963 const array_ptr = try func.lowerParentPtr(elem.base.toValue());
2964
2965 return WValue{ .memory_offset = .{
2966 .pointer = array_ptr.memory,
2967 .offset = @intCast(u32, offset),
2968 } };
29492969 },
2950 .field_ptr => {
2951 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
2952 const parent_ty = field_ptr.container_ty;
2970 .field => |field| {
2971 const parent_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
2972 const parent_ptr = try func.lowerParentPtr(field.base.toValue());
29532973
2954 const field_offset = switch (parent_ty.zigTypeTag(mod)) {
2974 const offset = switch (parent_ty.zigTypeTag(mod)) {
29552975 .Struct => switch (parent_ty.containerLayout(mod)) {
2956 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, mod),
2957 else => parent_ty.structFieldOffset(field_ptr.field_index, mod),
2976 .Packed => parent_ty.packedStructFieldByteOffset(field.index, mod),
2977 else => parent_ty.structFieldOffset(field.index, mod),
29582978 },
29592979 .Union => switch (parent_ty.containerLayout(mod)) {
29602980 .Packed => 0,
......@@ -2964,12 +2984,12 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
29642984 if (layout.payload_align > layout.tag_align) break :blk 0;
29652985
29662986 // tag is stored first so calculate offset from where payload starts
2967 const field_offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2968 break :blk field_offset;
2987 const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2988 break :blk offset;
29692989 },
29702990 },
29712991 .Pointer => switch (parent_ty.ptrSize(mod)) {
2972 .Slice => switch (field_ptr.field_index) {
2992 .Slice => switch (field.index) {
29732993 0 => 0,
29742994 1 => func.ptrSize(),
29752995 else => unreachable,
......@@ -2978,19 +2998,23 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
29782998 },
29792999 else => unreachable,
29803000 };
2981 return func.lowerParentPtr(field_ptr.container_ptr, offset + @intCast(u32, field_offset));
2982 },
2983 .elem_ptr => {
2984 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2985 const index = elem_ptr.index;
2986 const elem_offset = index * elem_ptr.elem_ty.abiSize(mod);
2987 return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset));
2988 },
2989 .opt_payload_ptr => {
2990 const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
2991 return func.lowerParentPtr(payload_ptr.container_ptr, offset);
3001
3002 return switch (parent_ptr) {
3003 .memory => |ptr_| WValue{
3004 .memory_offset = .{
3005 .pointer = ptr_,
3006 .offset = @intCast(u32, offset),
3007 },
3008 },
3009 .memory_offset => |mem_off| WValue{
3010 .memory_offset = .{
3011 .pointer = mem_off.pointer,
3012 .offset = @intCast(u32, offset) + mem_off.offset,
3013 },
3014 },
3015 else => unreachable,
3016 };
29923017 },
2993 else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}),
29943018 }
29953019}
29963020
......@@ -3045,21 +3069,97 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
30453069fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
30463070 const mod = func.bin_file.base.options.module.?;
30473071 var val = arg_val;
3048 if (val.castTag(.runtime_value)) |rt| {
3049 val = rt.data;
3072 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3073 .runtime_value => |rt| val = rt.val.toValue(),
3074 else => {},
30503075 }
30513076 if (val.isUndefDeep(mod)) return func.emitUndefined(ty);
3052 if (val.castTag(.decl_ref)) |decl_ref| {
3053 const decl_index = decl_ref.data;
3054 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);
3055 }
3056 if (val.castTag(.decl_ref_mut)) |decl_ref_mut| {
3057 const decl_index = decl_ref_mut.data.decl_index;
3058 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);
3059 }
3060 switch (ty.zigTypeTag(mod)) {
3061 .Void => return WValue{ .none = {} },
3062 .Int => {
3077
3078 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
3079 .Array => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3080 .Struct => {
3081 const struct_obj = mod.typeToStruct(ty).?;
3082 assert(struct_obj.layout == .Packed);
3083 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3084 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3085 const int_val = try mod.intValue(
3086 struct_obj.backing_int_ty,
3087 std.mem.readIntLittle(u64, &buf),
3088 );
3089 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3090 },
3091 .Vector => {
3092 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3093 var buf: [16]u8 = undefined;
3094 val.writeToMemory(ty, mod, &buf) catch unreachable;
3095 return func.storeSimdImmd(buf);
3096 },
3097 .Frame,
3098 .AnyFrame,
3099 => return func.fail("Wasm TODO: LowerConstant for type {}", .{ty.fmt(mod)}),
3100 .Float,
3101 .Union,
3102 .Optional,
3103 .ErrorUnion,
3104 .ErrorSet,
3105 .Int,
3106 .Enum,
3107 .Bool,
3108 .Pointer,
3109 => unreachable, // handled below
3110 .Type,
3111 .Void,
3112 .NoReturn,
3113 .ComptimeFloat,
3114 .ComptimeInt,
3115 .Undefined,
3116 .Null,
3117 .Opaque,
3118 .EnumLiteral,
3119 .Fn,
3120 => unreachable, // comptime-only types
3121 };
3122
3123 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3124 .int_type,
3125 .ptr_type,
3126 .array_type,
3127 .vector_type,
3128 .opt_type,
3129 .anyframe_type,
3130 .error_union_type,
3131 .simple_type,
3132 .struct_type,
3133 .anon_struct_type,
3134 .union_type,
3135 .opaque_type,
3136 .enum_type,
3137 .func_type,
3138 .error_set_type,
3139 .inferred_error_set_type,
3140 => unreachable, // types, not values
3141
3142 .undef, .runtime_value => unreachable, // handled above
3143 .simple_value => |simple_value| switch (simple_value) {
3144 .undefined,
3145 .void,
3146 .null,
3147 .empty_struct,
3148 .@"unreachable",
3149 .generic_poison,
3150 => unreachable, // non-runtime values
3151 .false, .true => return WValue{ .imm32 = switch (simple_value) {
3152 .false => 0,
3153 .true => 1,
3154 else => unreachable,
3155 } },
3156 },
3157 .variable,
3158 .extern_func,
3159 .func,
3160 .enum_literal,
3161 => unreachable, // non-runtime values
3162 .int => {
30633163 const int_info = ty.intInfo(mod);
30643164 switch (int_info.signedness) {
30653165 .signed => switch (int_info.bits) {
......@@ -3080,86 +3180,71 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
30803180 },
30813181 }
30823182 },
3083 .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) },
3084 .Float => switch (ty.floatBits(func.target)) {
3085 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16, mod)) },
3086 32 => return WValue{ .float32 = val.toFloat(f32, mod) },
3087 64 => return WValue{ .float64 = val.toFloat(f64, mod) },
3088 else => unreachable,
3089 },
3090 .Pointer => return switch (val.ip_index) {
3091 .null_value => WValue{ .imm32 = 0 },
3092 .none => switch (val.tag()) {
3093 .field_ptr, .elem_ptr, .opt_payload_ptr => func.lowerParentPtr(val, 0),
3094 else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}),
3095 },
3096 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
3097 .int => |int| WValue{ .imm32 = @intCast(u32, int.storage.u64) },
3098 else => unreachable,
3099 },
3100 },
3101 .Enum => {
3102 const enum_tag = mod.intern_pool.indexToKey(val.ip_index).enum_tag;
3103 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
3104 return func.lowerConstant(enum_tag.int.toValue(), int_tag_ty.toType());
3105 },
3106 .ErrorSet => switch (val.tag()) {
3107 .@"error" => {
3108 const kv = try func.bin_file.base.options.module.?.getErrorValue(val.getError().?);
3109 return WValue{ .imm32 = kv.value };
3110 },
3111 else => return WValue{ .imm32 = 0 },
3183 .err => |err| {
3184 const name = mod.intern_pool.stringToSlice(err.name);
3185 const kv = try mod.getErrorValue(name);
3186 return WValue{ .imm32 = kv.value };
31123187 },
3113 .ErrorUnion => {
3188 .error_union => {
31143189 const error_type = ty.errorUnionSet(mod);
31153190 const payload_type = ty.errorUnionPayload(mod);
31163191 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
31173192 // We use the error type directly as the type.
3118 const is_pl = val.errorUnionIsPayload();
3193 const is_pl = val.errorUnionIsPayload(mod);
31193194 const err_val = if (!is_pl) val else try mod.intValue(error_type, 0);
31203195 return func.lowerConstant(err_val, error_type);
31213196 }
31223197 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
31233198 },
3124 .Optional => if (ty.optionalReprIsPayload(mod)) {
3199 .enum_tag => |enum_tag| {
3200 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
3201 return func.lowerConstant(enum_tag.int.toValue(), int_tag_ty.toType());
3202 },
3203 .float => |float| switch (float.storage) {
3204 .f16 => |f16_val| return WValue{ .imm32 = @bitCast(u16, f16_val) },
3205 .f32 => |f32_val| return WValue{ .float32 = f32_val },
3206 .f64 => |f64_val| return WValue{ .float64 = f64_val },
3207 else => unreachable,
3208 },
3209 .ptr => |ptr| switch (ptr.addr) {
3210 .decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0),
3211 .mut_decl => |mut_decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, mut_decl.decl, 0),
3212 .int => |int| return func.lowerConstant(int.toValue(), mod.intern_pool.typeOf(int).toType()),
3213 .opt_payload, .elem, .field => return func.lowerParentPtr(val),
3214 else => return func.fail("Wasm TODO: lowerConstant for other const addr tag {}", .{ptr.addr}),
3215 },
3216 .opt => if (ty.optionalReprIsPayload(mod)) {
31253217 const pl_ty = ty.optionalChild(mod);
3126 if (val.castTag(.opt_payload)) |payload| {
3127 return func.lowerConstant(payload.data, pl_ty);
3128 } else if (val.isNull(mod)) {
3129 return WValue{ .imm32 = 0 };
3218 if (val.optionalValue(mod)) |payload| {
3219 return func.lowerConstant(payload, pl_ty);
31303220 } else {
3131 return func.lowerConstant(val, pl_ty);
3221 return WValue{ .imm32 = 0 };
31323222 }
31333223 } else {
3134 const is_pl = val.tag() == .opt_payload;
3135 return WValue{ .imm32 = @boolToInt(is_pl) };
3136 },
3137 .Struct => {
3138 const struct_obj = mod.typeToStruct(ty).?;
3139 assert(struct_obj.layout == .Packed);
3140 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3141 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3142 const int_val = try mod.intValue(
3143 struct_obj.backing_int_ty,
3144 std.mem.readIntLittle(u64, &buf),
3145 );
3146 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3224 return WValue{ .imm32 = @boolToInt(!val.isNull(mod)) };
31473225 },
3148 .Vector => {
3149 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3150 var buf: [16]u8 = undefined;
3151 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable;
3152 return func.storeSimdImmd(buf);
3153 },
3154 .Union => {
3155 // in this case we have a packed union which will not be passed by reference.
3156 const union_ty = mod.typeToUnion(ty).?;
3157 const union_obj = val.castTag(.@"union").?.data;
3158 const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?;
3159 const field_ty = union_ty.fields.values()[field_index].ty;
3160 return func.lowerConstant(union_obj.val, field_ty);
3226 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3227 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
3228 .vector_type => {
3229 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3230 var buf: [16]u8 = undefined;
3231 val.writeToMemory(ty, mod, &buf) catch unreachable;
3232 return func.storeSimdImmd(buf);
3233 },
3234 .struct_type, .anon_struct_type => {
3235 const struct_obj = mod.typeToStruct(ty).?;
3236 assert(struct_obj.layout == .Packed);
3237 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3238 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3239 const int_val = try mod.intValue(
3240 struct_obj.backing_int_ty,
3241 std.mem.readIntLittle(u64, &buf),
3242 );
3243 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3244 },
3245 else => unreachable,
31613246 },
3162 else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3247 .un => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
31633248 }
31643249}
31653250
......@@ -3221,31 +3306,33 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
32213306 .bool_true => return 1,
32223307 .bool_false => return 0,
32233308 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
3224 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int),
3225 .int => |int| intStorageAsI32(int.storage),
3226 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int),
3309 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, mod),
3310 .int => |int| intStorageAsI32(int.storage, mod),
3311 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int, mod),
32273312 else => unreachable,
32283313 },
32293314 }
32303315
32313316 switch (ty.zigTypeTag(mod)) {
32323317 .ErrorSet => {
3233 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
3318 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError(mod).?) catch unreachable; // passed invalid `Value` to function
32343319 return @bitCast(i32, kv.value);
32353320 },
32363321 else => unreachable, // Programmer called this function for an illegal type
32373322 }
32383323}
32393324
3240fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index) i32 {
3241 return intStorageAsI32(ip.indexToKey(int).int.storage);
3325fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, mod: *Module) i32 {
3326 return intStorageAsI32(ip.indexToKey(int).int.storage, mod);
32423327}
32433328
3244fn intStorageAsI32(storage: InternPool.Key.Int.Storage) i32 {
3329fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 {
32453330 return switch (storage) {
32463331 .i64 => |x| @intCast(i32, x),
32473332 .u64 => |x| @bitCast(i32, @intCast(u32, x)),
32483333 .big_int => unreachable,
3334 .lazy_align => |ty| @bitCast(i32, ty.toType().abiAlignment(mod)),
3335 .lazy_size => |ty| @bitCast(i32, @intCast(u32, ty.toType().abiSize(mod))),
32493336 };
32503337}
32513338
......@@ -5514,7 +5601,7 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55145601 // As the names are global and the slice elements are constant, we do not have
55155602 // to make a copy of the ptr+value but can point towards them directly.
55165603 const error_table_symbol = try func.bin_file.getErrorTableSymbol();
5517 const name_ty = Type.const_slice_u8_sentinel_0;
5604 const name_ty = Type.slice_const_u8_sentinel_0;
55185605 const mod = func.bin_file.base.options.module.?;
55195606 const abi_size = name_ty.abiSize(mod);
55205607
......@@ -6935,7 +7022,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
69357022 // finish function body
69367023 try writer.writeByte(std.wasm.opcode(.end));
69377024
6938 const slice_ty = Type.const_slice_u8_sentinel_0;
7025 const slice_ty = Type.slice_const_u8_sentinel_0;
69397026 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
69407027 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
69417028}
src/arch/x86_64/CodeGen.zig+29-36
......@@ -632,7 +632,7 @@ const Self = @This();
632632pub fn generate(
633633 bin_file: *link.File,
634634 src_loc: Module.SrcLoc,
635 module_fn: *Module.Fn,
635 module_fn_index: Module.Fn.Index,
636636 air: Air,
637637 liveness: Liveness,
638638 code: *std.ArrayList(u8),
......@@ -643,6 +643,7 @@ pub fn generate(
643643 }
644644
645645 const mod = bin_file.options.module.?;
646 const module_fn = mod.funcPtr(module_fn_index);
646647 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
647648 assert(fn_owner_decl.has_tv);
648649 const fn_type = fn_owner_decl.ty;
......@@ -687,7 +688,7 @@ pub fn generate(
687688 @enumToInt(FrameIndex.stack_frame),
688689 FrameAlloc.init(.{
689690 .size = 0,
690 .alignment = if (mod.align_stack_fns.get(module_fn)) |set_align_stack|
691 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
691692 set_align_stack.alignment
692693 else
693694 1,
......@@ -2760,19 +2761,18 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27602761 const elem_ty = src_ty.childType(mod);
27612762 const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits));
27622763
2763 var splat_pl = Value.Payload.SubValue{
2764 .base = .{ .tag = .repeated },
2765 .data = mask_val,
2766 };
2767 const splat_val = Value.initPayload(&splat_pl.base);
2768
2769 const full_ty = try mod.vectorType(.{
2764 const splat_ty = try mod.vectorType(.{
27702765 .len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
27712766 .child = elem_ty.ip_index,
27722767 });
2773 const full_abi_size = @intCast(u32, full_ty.abiSize(mod));
2768 const splat_abi_size = @intCast(u32, splat_ty.abiSize(mod));
2769
2770 const splat_val = try mod.intern(.{ .aggregate = .{
2771 .ty = splat_ty.ip_index,
2772 .storage = .{ .repeated_elem = mask_val.ip_index },
2773 } });
27742774
2775 const splat_mcv = try self.genTypedValue(.{ .ty = full_ty, .val = splat_val });
2775 const splat_mcv = try self.genTypedValue(.{ .ty = splat_ty, .val = splat_val.toValue() });
27762776 const splat_addr_mcv: MCValue = switch (splat_mcv) {
27772777 .memory, .indirect, .load_frame => splat_mcv.address(),
27782778 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },
......@@ -2784,14 +2784,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27842784 .{ .vp_, .@"and" },
27852785 dst_reg,
27862786 dst_reg,
2787 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(full_abi_size)),
2787 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(splat_abi_size)),
27882788 );
27892789 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
27902790 } else {
27912791 try self.asmRegisterMemory(
27922792 .{ .p_, .@"and" },
27932793 dst_reg,
2794 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(full_abi_size)),
2794 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(splat_abi_size)),
27952795 );
27962796 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
27972797 }
......@@ -4893,23 +4893,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
48934893 const dst_lock = self.register_manager.lockReg(dst_reg);
48944894 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
48954895
4896 var arena = std.heap.ArenaAllocator.init(self.gpa);
4897 defer arena.deinit();
4898
4899 const ExpectedContents = struct {
4900 repeated: Value.Payload.SubValue,
4901 };
4902 var stack align(@alignOf(ExpectedContents)) =
4903 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
4904
49054896 const vec_ty = try mod.vectorType(.{
49064897 .len = @divExact(abi_size * 8, scalar_bits),
49074898 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
49084899 });
49094900
49104901 const sign_val = switch (tag) {
4911 .neg => try vec_ty.minInt(stack.get(), mod),
4912 .fabs => try vec_ty.maxInt(stack.get(), mod, vec_ty),
4902 .neg => try vec_ty.minInt(mod),
4903 .fabs => try vec_ty.maxInt(mod, vec_ty),
49134904 else => unreachable,
49144905 };
49154906
......@@ -8106,13 +8097,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81068097 // Due to incremental compilation, how function calls are generated depends
81078098 // on linking.
81088099 if (try self.air.value(callee, mod)) |func_value| {
8109 if (if (func_value.castTag(.function)) |func_payload|
8110 func_payload.data.owner_decl
8111 else if (func_value.castTag(.decl_ref)) |decl_ref_payload|
8112 decl_ref_payload.data
8113 else
8114 null) |owner_decl|
8115 {
8100 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8101 if (switch (func_key) {
8102 .func => |func| mod.funcPtr(func.index).owner_decl,
8103 .ptr => |ptr| switch (ptr.addr) {
8104 .decl => |decl| decl,
8105 else => null,
8106 },
8107 else => null,
8108 }) |owner_decl| {
81168109 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
81178110 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);
81188111 const atom = elf_file.getAtom(atom_index);
......@@ -8145,10 +8138,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81458138 .disp = @intCast(i32, fn_got_addr),
81468139 }));
81478140 } else unreachable;
8148 } else if (func_value.castTag(.extern_fn)) |func_payload| {
8149 const extern_fn = func_payload.data;
8150 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
8151 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
8141 } else if (func_value.getExternFunc(mod)) |extern_func| {
8142 const decl_name = mem.sliceTo(mod.declPtr(extern_func.decl).name, 0);
8143 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
81528144 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
81538145 const atom_index = try self.owner.getSymbolIndex(self);
81548146 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
......@@ -8554,7 +8546,8 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
85548546
85558547fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
85568548 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
8557 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
8549 const mod = self.bin_file.options.module.?;
8550 const function = self.air.values[ty_pl.payload].getFunction(mod).?;
85588551 // TODO emit debug info for function change
85598552 _ = function;
85608553 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
src/codegen.zig+430-605
......@@ -14,6 +14,7 @@ const Air = @import("Air.zig");
1414const Allocator = mem.Allocator;
1515const Compilation = @import("Compilation.zig");
1616const ErrorMsg = Module.ErrorMsg;
17const InternPool = @import("InternPool.zig");
1718const Liveness = @import("Liveness.zig");
1819const Module = @import("Module.zig");
1920const Target = std.Target;
......@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
6667pub fn generateFunction(
6768 bin_file: *link.File,
6869 src_loc: Module.SrcLoc,
69 func: *Module.Fn,
70 func_index: Module.Fn.Index,
7071 air: Air,
7172 liveness: Liveness,
7273 code: *std.ArrayList(u8),
......@@ -75,17 +76,17 @@ pub fn generateFunction(
7576 switch (bin_file.options.target.cpu.arch) {
7677 .arm,
7778 .armeb,
78 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
79 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
7980 .aarch64,
8081 .aarch64_be,
8182 .aarch64_32,
82 => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
83 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
84 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
85 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
83 => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
84 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
85 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
86 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
8687 .wasm32,
8788 .wasm64,
88 => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
89 => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
8990 else => unreachable,
9091 }
9192}
......@@ -182,12 +183,13 @@ pub fn generateSymbol(
182183 const tracy = trace(@src());
183184 defer tracy.end();
184185
186 const mod = bin_file.options.module.?;
185187 var typed_value = arg_tv;
186 if (arg_tv.val.castTag(.runtime_value)) |rt| {
187 typed_value.val = rt.data;
188 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
189 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
190 else => {},
188191 }
189192
190 const mod = bin_file.options.module.?;
191193 const target = mod.getTarget();
192194 const endian = target.cpu.arch.endian();
193195
......@@ -199,35 +201,10 @@ pub fn generateSymbol(
199201 if (typed_value.val.isUndefDeep(mod)) {
200202 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
201203 try code.appendNTimes(0xaa, abi_size);
202 return Result.ok;
204 return .ok;
203205 }
204206
205 switch (typed_value.ty.zigTypeTag(mod)) {
206 .Fn => {
207 return Result{
208 .fail = try ErrorMsg.create(
209 bin_file.allocator,
210 src_loc,
211 "TODO implement generateSymbol function pointers",
212 .{},
213 ),
214 };
215 },
216 .Float => {
217 switch (typed_value.ty.floatBits(target)) {
218 16 => writeFloat(f16, typed_value.val.toFloat(f16, mod), target, endian, try code.addManyAsArray(2)),
219 32 => writeFloat(f32, typed_value.val.toFloat(f32, mod), target, endian, try code.addManyAsArray(4)),
220 64 => writeFloat(f64, typed_value.val.toFloat(f64, mod), target, endian, try code.addManyAsArray(8)),
221 80 => {
222 writeFloat(f80, typed_value.val.toFloat(f80, mod), target, endian, try code.addManyAsArray(10));
223 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
224 try code.appendNTimes(0, abi_size - 10);
225 },
226 128 => writeFloat(f128, typed_value.val.toFloat(f128, mod), target, endian, try code.addManyAsArray(16)),
227 else => unreachable,
228 }
229 return Result.ok;
230 },
207 if (typed_value.val.ip_index == .none) switch (typed_value.ty.zigTypeTag(mod)) {
231208 .Array => switch (typed_value.val.tag()) {
232209 .bytes => {
233210 const bytes = typed_value.val.castTag(.bytes).?.data;
......@@ -248,62 +225,6 @@ pub fn generateSymbol(
248225 }
249226 return Result.ok;
250227 },
251 .aggregate => {
252 const elem_vals = typed_value.val.castTag(.aggregate).?.data;
253 const elem_ty = typed_value.ty.childType(mod);
254 const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel(mod));
255 for (elem_vals[0..len]) |elem_val| {
256 switch (try generateSymbol(bin_file, src_loc, .{
257 .ty = elem_ty,
258 .val = elem_val,
259 }, code, debug_output, reloc_info)) {
260 .ok => {},
261 .fail => |em| return Result{ .fail = em },
262 }
263 }
264 return Result.ok;
265 },
266 .repeated => {
267 const array = typed_value.val.castTag(.repeated).?.data;
268 const elem_ty = typed_value.ty.childType(mod);
269 const sentinel = typed_value.ty.sentinel(mod);
270 const len = typed_value.ty.arrayLen(mod);
271
272 var index: u64 = 0;
273 while (index < len) : (index += 1) {
274 switch (try generateSymbol(bin_file, src_loc, .{
275 .ty = elem_ty,
276 .val = array,
277 }, code, debug_output, reloc_info)) {
278 .ok => {},
279 .fail => |em| return Result{ .fail = em },
280 }
281 }
282
283 if (sentinel) |sentinel_val| {
284 switch (try generateSymbol(bin_file, src_loc, .{
285 .ty = elem_ty,
286 .val = sentinel_val,
287 }, code, debug_output, reloc_info)) {
288 .ok => {},
289 .fail => |em| return Result{ .fail = em },
290 }
291 }
292
293 return Result.ok;
294 },
295 .empty_array_sentinel => {
296 const elem_ty = typed_value.ty.childType(mod);
297 const sentinel_val = typed_value.ty.sentinel(mod).?;
298 switch (try generateSymbol(bin_file, src_loc, .{
299 .ty = elem_ty,
300 .val = sentinel_val,
301 }, code, debug_output, reloc_info)) {
302 .ok => {},
303 .fail => |em| return Result{ .fail = em },
304 }
305 return Result.ok;
306 },
307228 else => return Result{
308229 .fail = try ErrorMsg.create(
309230 bin_file.allocator,
......@@ -313,195 +234,6 @@ pub fn generateSymbol(
313234 ),
314235 },
315236 },
316 .Pointer => switch (typed_value.val.ip_index) {
317 .null_value => {
318 switch (target.ptrBitWidth()) {
319 32 => {
320 mem.writeInt(u32, try code.addManyAsArray(4), 0, endian);
321 if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 4);
322 },
323 64 => {
324 mem.writeInt(u64, try code.addManyAsArray(8), 0, endian);
325 if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 8);
326 },
327 else => unreachable,
328 }
329 return Result.ok;
330 },
331 .none => switch (typed_value.val.tag()) {
332 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
333 bin_file,
334 src_loc,
335 typed_value,
336 switch (tag) {
337 .variable => typed_value.val.castTag(.variable).?.data.owner_decl,
338 .decl_ref => typed_value.val.castTag(.decl_ref).?.data,
339 .decl_ref_mut => typed_value.val.castTag(.decl_ref_mut).?.data.decl_index,
340 else => unreachable,
341 },
342 code,
343 debug_output,
344 reloc_info,
345 ),
346 .slice => {
347 const slice = typed_value.val.castTag(.slice).?.data;
348
349 // generate ptr
350 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(mod);
351 switch (try generateSymbol(bin_file, src_loc, .{
352 .ty = slice_ptr_field_type,
353 .val = slice.ptr,
354 }, code, debug_output, reloc_info)) {
355 .ok => {},
356 .fail => |em| return Result{ .fail = em },
357 }
358
359 // generate length
360 switch (try generateSymbol(bin_file, src_loc, .{
361 .ty = Type.usize,
362 .val = slice.len,
363 }, code, debug_output, reloc_info)) {
364 .ok => {},
365 .fail => |em| return Result{ .fail = em },
366 }
367
368 return Result.ok;
369 },
370 .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
371 bin_file,
372 src_loc,
373 typed_value,
374 typed_value.val,
375 code,
376 debug_output,
377 reloc_info,
378 ),
379 else => return Result{
380 .fail = try ErrorMsg.create(
381 bin_file.allocator,
382 src_loc,
383 "TODO implement generateSymbol for pointer type value: '{s}'",
384 .{@tagName(typed_value.val.tag())},
385 ),
386 },
387 },
388 else => switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
389 .int => {
390 switch (target.ptrBitWidth()) {
391 32 => {
392 const x = typed_value.val.toUnsignedInt(mod);
393 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian);
394 },
395 64 => {
396 const x = typed_value.val.toUnsignedInt(mod);
397 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
398 },
399 else => unreachable,
400 }
401 return Result.ok;
402 },
403 else => unreachable,
404 },
405 },
406 .Int => {
407 const info = typed_value.ty.intInfo(mod);
408 if (info.bits <= 8) {
409 const x: u8 = switch (info.signedness) {
410 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(mod)),
411 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(mod))),
412 };
413 try code.append(x);
414 return Result.ok;
415 }
416 if (info.bits > 64) {
417 var bigint_buffer: Value.BigIntSpace = undefined;
418 const bigint = typed_value.val.toBigInt(&bigint_buffer, mod);
419 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
420 const start = code.items.len;
421 try code.resize(start + abi_size);
422 bigint.writeTwosComplement(code.items[start..][0..abi_size], endian);
423 return Result.ok;
424 }
425 switch (info.signedness) {
426 .unsigned => {
427 if (info.bits <= 16) {
428 const x = @intCast(u16, typed_value.val.toUnsignedInt(mod));
429 mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
430 } else if (info.bits <= 32) {
431 const x = @intCast(u32, typed_value.val.toUnsignedInt(mod));
432 mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
433 } else {
434 const x = typed_value.val.toUnsignedInt(mod);
435 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
436 }
437 },
438 .signed => {
439 if (info.bits <= 16) {
440 const x = @intCast(i16, typed_value.val.toSignedInt(mod));
441 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
442 } else if (info.bits <= 32) {
443 const x = @intCast(i32, typed_value.val.toSignedInt(mod));
444 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
445 } else {
446 const x = typed_value.val.toSignedInt(mod);
447 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
448 }
449 },
450 }
451 return Result.ok;
452 },
453 .Enum => {
454 const int_val = try typed_value.enumToInt(mod);
455
456 const info = typed_value.ty.intInfo(mod);
457 if (info.bits <= 8) {
458 const x = @intCast(u8, int_val.toUnsignedInt(mod));
459 try code.append(x);
460 return Result.ok;
461 }
462 if (info.bits > 64) {
463 return Result{
464 .fail = try ErrorMsg.create(
465 bin_file.allocator,
466 src_loc,
467 "TODO implement generateSymbol for big int enums ('{}')",
468 .{typed_value.ty.fmt(mod)},
469 ),
470 };
471 }
472 switch (info.signedness) {
473 .unsigned => {
474 if (info.bits <= 16) {
475 const x = @intCast(u16, int_val.toUnsignedInt(mod));
476 mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
477 } else if (info.bits <= 32) {
478 const x = @intCast(u32, int_val.toUnsignedInt(mod));
479 mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
480 } else {
481 const x = int_val.toUnsignedInt(mod);
482 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
483 }
484 },
485 .signed => {
486 if (info.bits <= 16) {
487 const x = @intCast(i16, int_val.toSignedInt(mod));
488 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
489 } else if (info.bits <= 32) {
490 const x = @intCast(i32, int_val.toSignedInt(mod));
491 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
492 } else {
493 const x = int_val.toSignedInt(mod);
494 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
495 }
496 },
497 }
498 return Result.ok;
499 },
500 .Bool => {
501 const x: u8 = @boolToInt(typed_value.val.toBool(mod));
502 try code.append(x);
503 return Result.ok;
504 },
505237 .Struct => {
506238 if (typed_value.ty.containerLayout(mod) == .Packed) {
507239 const struct_obj = mod.typeToStruct(typed_value.ty).?;
......@@ -562,370 +294,497 @@ pub fn generateSymbol(
562294
563295 return Result.ok;
564296 },
565 .Union => {
566 const union_obj = typed_value.val.castTag(.@"union").?.data;
567 const layout = typed_value.ty.unionGetLayout(mod);
297 .Vector => switch (typed_value.val.tag()) {
298 .bytes => {
299 const bytes = typed_value.val.castTag(.bytes).?.data;
300 const len = math.cast(usize, typed_value.ty.arrayLen(mod)) orelse return error.Overflow;
301 const padding = math.cast(usize, typed_value.ty.abiSize(mod) - len) orelse
302 return error.Overflow;
303 try code.ensureUnusedCapacity(len + padding);
304 code.appendSliceAssumeCapacity(bytes[0..len]);
305 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
306 return Result.ok;
307 },
308 .str_lit => {
309 const str_lit = typed_value.val.castTag(.str_lit).?.data;
310 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
311 const padding = math.cast(usize, typed_value.ty.abiSize(mod) - str_lit.len) orelse
312 return error.Overflow;
313 try code.ensureUnusedCapacity(str_lit.len + padding);
314 code.appendSliceAssumeCapacity(bytes);
315 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
316 return Result.ok;
317 },
318 else => unreachable,
319 },
320 .Frame,
321 .AnyFrame,
322 => return .{ .fail = try ErrorMsg.create(
323 bin_file.allocator,
324 src_loc,
325 "TODO generateSymbol for type {}",
326 .{typed_value.ty.fmt(mod)},
327 ) },
328 .Float,
329 .Union,
330 .Optional,
331 .ErrorUnion,
332 .ErrorSet,
333 .Int,
334 .Enum,
335 .Bool,
336 .Pointer,
337 => unreachable, // handled below
338 .Type,
339 .Void,
340 .NoReturn,
341 .ComptimeFloat,
342 .ComptimeInt,
343 .Undefined,
344 .Null,
345 .Opaque,
346 .EnumLiteral,
347 .Fn,
348 => unreachable, // comptime-only types
349 };
568350
569 if (layout.payload_size == 0) {
570 return generateSymbol(bin_file, src_loc, .{
571 .ty = typed_value.ty.unionTagType(mod).?,
572 .val = union_obj.tag,
573 }, code, debug_output, reloc_info);
351 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
352 .int_type,
353 .ptr_type,
354 .array_type,
355 .vector_type,
356 .opt_type,
357 .anyframe_type,
358 .error_union_type,
359 .simple_type,
360 .struct_type,
361 .anon_struct_type,
362 .union_type,
363 .opaque_type,
364 .enum_type,
365 .func_type,
366 .error_set_type,
367 .inferred_error_set_type,
368 => unreachable, // types, not values
369
370 .undef, .runtime_value => unreachable, // handled above
371 .simple_value => |simple_value| switch (simple_value) {
372 .undefined,
373 .void,
374 .null,
375 .empty_struct,
376 .@"unreachable",
377 .generic_poison,
378 => unreachable, // non-runtime values
379 .false, .true => try code.append(switch (simple_value) {
380 .false => 0,
381 .true => 1,
382 else => unreachable,
383 }),
384 },
385 .variable,
386 .extern_func,
387 .func,
388 .enum_literal,
389 => unreachable, // non-runtime values
390 .int => {
391 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
392 var space: Value.BigIntSpace = undefined;
393 const val = typed_value.val.toBigInt(&space, mod);
394 val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
395 },
396 .err => |err| {
397 const name = mod.intern_pool.stringToSlice(err.name);
398 const kv = try mod.getErrorValue(name);
399 try code.writer().writeInt(u16, @intCast(u16, kv.value), endian);
400 },
401 .error_union => |error_union| {
402 const payload_ty = typed_value.ty.errorUnionPayload(mod);
403
404 const err_val = switch (error_union.val) {
405 .err_name => |err_name| @intCast(u16, (try mod.getErrorValue(mod.intern_pool.stringToSlice(err_name))).value),
406 .payload => @as(u16, 0),
407 };
408
409 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
410 try code.writer().writeInt(u16, err_val, endian);
411 return .ok;
574412 }
575413
576 // Check if we should store the tag first.
577 if (layout.tag_align >= layout.payload_align) {
578 switch (try generateSymbol(bin_file, src_loc, .{
579 .ty = typed_value.ty.unionTagType(mod).?,
580 .val = union_obj.tag,
581 }, code, debug_output, reloc_info)) {
582 .ok => {},
583 .fail => |em| return Result{ .fail = em },
584 }
414 const payload_align = payload_ty.abiAlignment(mod);
415 const error_align = Type.anyerror.abiAlignment(mod);
416 const abi_align = typed_value.ty.abiAlignment(mod);
417
418 // error value first when its type is larger than the error union's payload
419 if (error_align > payload_align) {
420 try code.writer().writeInt(u16, err_val, endian);
585421 }
586422
587 const union_ty = mod.typeToUnion(typed_value.ty).?;
588 const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?;
589 assert(union_ty.haveFieldTypes());
590 const field_ty = union_ty.fields.values()[field_index].ty;
591 if (!field_ty.hasRuntimeBits(mod)) {
592 try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
593 } else {
423 // emit payload part of the error union
424 {
425 const begin = code.items.len;
594426 switch (try generateSymbol(bin_file, src_loc, .{
595 .ty = field_ty,
596 .val = union_obj.val,
427 .ty = payload_ty,
428 .val = switch (error_union.val) {
429 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
430 .payload => |payload| payload,
431 }.toValue(),
597432 }, code, debug_output, reloc_info)) {
598433 .ok => {},
599 .fail => |em| return Result{ .fail = em },
434 .fail => |em| return .{ .fail = em },
600435 }
436 const unpadded_end = code.items.len - begin;
437 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
438 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
601439
602 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow;
603440 if (padding > 0) {
604441 try code.writer().writeByteNTimes(0, padding);
605442 }
606443 }
607444
608 if (layout.tag_size > 0) {
445 // Payload size is larger than error set, so emit our error set last
446 if (error_align <= payload_align) {
447 const begin = code.items.len;
448 try code.writer().writeInt(u16, err_val, endian);
449 const unpadded_end = code.items.len - begin;
450 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
451 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
452
453 if (padding > 0) {
454 try code.writer().writeByteNTimes(0, padding);
455 }
456 }
457 },
458 .enum_tag => |enum_tag| {
459 const int_tag_ty = try typed_value.ty.intTagType(mod);
460 switch (try generateSymbol(bin_file, src_loc, .{
461 .ty = int_tag_ty,
462 .val = (try mod.intern_pool.getCoerced(mod.gpa, enum_tag.int, int_tag_ty.ip_index)).toValue(),
463 }, code, debug_output, reloc_info)) {
464 .ok => {},
465 .fail => |em| return .{ .fail = em },
466 }
467 },
468 .float => |float| switch (float.storage) {
469 .f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(2)),
470 .f32 => |f32_val| writeFloat(f32, f32_val, target, endian, try code.addManyAsArray(4)),
471 .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)),
472 .f80 => |f80_val| {
473 writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(10));
474 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
475 try code.appendNTimes(0, abi_size - 10);
476 },
477 .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)),
478 },
479 .ptr => |ptr| {
480 // generate ptr
481 switch (try lowerParentPtr(bin_file, src_loc, switch (ptr.len) {
482 .none => typed_value.val,
483 else => typed_value.val.slicePtr(mod),
484 }.ip_index, code, debug_output, reloc_info)) {
485 .ok => {},
486 .fail => |em| return .{ .fail = em },
487 }
488 if (ptr.len != .none) {
489 // generate len
609490 switch (try generateSymbol(bin_file, src_loc, .{
610 .ty = union_ty.tag_ty,
611 .val = union_obj.tag,
491 .ty = Type.usize,
492 .val = ptr.len.toValue(),
612493 }, code, debug_output, reloc_info)) {
613494 .ok => {},
614495 .fail => |em| return Result{ .fail = em },
615496 }
616497 }
617
618 if (layout.padding > 0) {
619 try code.writer().writeByteNTimes(0, layout.padding);
620 }
621
622 return Result.ok;
623498 },
624 .Optional => {
499 .opt => {
625500 const payload_type = typed_value.ty.optionalChild(mod);
626 const is_pl = !typed_value.val.isNull(mod);
501 const payload_val = typed_value.val.optionalValue(mod);
627502 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
628503
629 if (!payload_type.hasRuntimeBits(mod)) {
630 try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size);
631 return Result.ok;
632 }
633
634504 if (typed_value.ty.optionalReprIsPayload(mod)) {
635 if (typed_value.val.castTag(.opt_payload)) |payload| {
505 if (payload_val) |value| {
636506 switch (try generateSymbol(bin_file, src_loc, .{
637507 .ty = payload_type,
638 .val = payload.data,
508 .val = value,
639509 }, code, debug_output, reloc_info)) {
640510 .ok => {},
641511 .fail => |em| return Result{ .fail = em },
642512 }
643 } else if (!typed_value.val.isNull(mod)) {
513 } else {
514 try code.writer().writeByteNTimes(0, abi_size);
515 }
516 } else {
517 const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1;
518 if (payload_type.hasRuntimeBits(mod)) {
519 const value = payload_val orelse (try mod.intern(.{ .undef = payload_type.ip_index })).toValue();
644520 switch (try generateSymbol(bin_file, src_loc, .{
645521 .ty = payload_type,
646 .val = typed_value.val,
522 .val = value,
647523 }, code, debug_output, reloc_info)) {
648524 .ok => {},
649525 .fail => |em| return Result{ .fail = em },
650526 }
651 } else {
652 try code.writer().writeByteNTimes(0, abi_size);
653527 }
654
655 return Result.ok;
528 try code.writer().writeByte(@boolToInt(payload_val != null));
529 try code.writer().writeByteNTimes(0, padding);
656530 }
531 },
532 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(typed_value.ty.ip_index)) {
533 .array_type => |array_type| {
534 var index: u64 = 0;
535 while (index < array_type.len) : (index += 1) {
536 switch (aggregate.storage) {
537 .bytes => |bytes| try code.appendSlice(bytes),
538 .elems, .repeated_elem => switch (try generateSymbol(bin_file, src_loc, .{
539 .ty = array_type.child.toType(),
540 .val = switch (aggregate.storage) {
541 .bytes => unreachable,
542 .elems => |elems| elems[@intCast(usize, index)],
543 .repeated_elem => |elem| elem,
544 }.toValue(),
545 }, code, debug_output, reloc_info)) {
546 .ok => {},
547 .fail => |em| return .{ .fail = em },
548 },
549 }
550 }
657551
658 const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1;
659 const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.undef;
660 switch (try generateSymbol(bin_file, src_loc, .{
661 .ty = payload_type,
662 .val = value,
663 }, code, debug_output, reloc_info)) {
664 .ok => {},
665 .fail => |em| return Result{ .fail = em },
666 }
667 try code.writer().writeByte(@boolToInt(is_pl));
668 try code.writer().writeByteNTimes(0, padding);
552 if (array_type.sentinel != .none) {
553 switch (try generateSymbol(bin_file, src_loc, .{
554 .ty = array_type.child.toType(),
555 .val = array_type.sentinel.toValue(),
556 }, code, debug_output, reloc_info)) {
557 .ok => {},
558 .fail => |em| return .{ .fail = em },
559 }
560 }
561 },
562 .vector_type => |vector_type| {
563 var index: u32 = 0;
564 while (index < vector_type.len) : (index += 1) {
565 switch (aggregate.storage) {
566 .bytes => |bytes| try code.appendSlice(bytes),
567 .elems, .repeated_elem => switch (try generateSymbol(bin_file, src_loc, .{
568 .ty = vector_type.child.toType(),
569 .val = switch (aggregate.storage) {
570 .bytes => unreachable,
571 .elems => |elems| elems[@intCast(usize, index)],
572 .repeated_elem => |elem| elem,
573 }.toValue(),
574 }, code, debug_output, reloc_info)) {
575 .ok => {},
576 .fail => |em| return .{ .fail = em },
577 },
578 }
579 }
669580
670 return Result.ok;
581 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
582 (math.divCeil(u64, vector_type.child.toType().bitSize(mod) * vector_type.len, 8) catch |err| switch (err) {
583 error.DivisionByZero => unreachable,
584 else => |e| return e,
585 })) orelse return error.Overflow;
586 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
587 },
588 .struct_type, .anon_struct_type => {
589 if (typed_value.ty.containerLayout(mod) == .Packed) {
590 const struct_obj = mod.typeToStruct(typed_value.ty).?;
591 const fields = struct_obj.fields.values();
592 const field_vals = typed_value.val.castTag(.aggregate).?.data;
593 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
594 const current_pos = code.items.len;
595 try code.resize(current_pos + abi_size);
596 var bits: u16 = 0;
597
598 for (field_vals, 0..) |field_val, index| {
599 const field_ty = fields[index].ty;
600 // pointer may point to a decl which must be marked used
601 // but can also result in a relocation. Therefore we handle those seperately.
602 if (field_ty.zigTypeTag(mod) == .Pointer) {
603 const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse return error.Overflow;
604 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
605 defer tmp_list.deinit();
606 switch (try generateSymbol(bin_file, src_loc, .{
607 .ty = field_ty,
608 .val = field_val,
609 }, &tmp_list, debug_output, reloc_info)) {
610 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
611 .fail => |em| return Result{ .fail = em },
612 }
613 } else {
614 field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable;
615 }
616 bits += @intCast(u16, field_ty.bitSize(mod));
617 }
618 } else {
619 const struct_begin = code.items.len;
620 const field_vals = typed_value.val.castTag(.aggregate).?.data;
621 for (field_vals, 0..) |field_val, index| {
622 const field_ty = typed_value.ty.structFieldType(index, mod);
623 if (!field_ty.hasRuntimeBits(mod)) continue;
624
625 switch (try generateSymbol(bin_file, src_loc, .{
626 .ty = field_ty,
627 .val = field_val,
628 }, code, debug_output, reloc_info)) {
629 .ok => {},
630 .fail => |em| return Result{ .fail = em },
631 }
632 const unpadded_field_end = code.items.len - struct_begin;
633
634 // Pad struct members if required
635 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);
636 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow;
637
638 if (padding > 0) {
639 try code.writer().writeByteNTimes(0, padding);
640 }
641 }
642 }
643 },
644 else => unreachable,
671645 },
672 .ErrorUnion => {
673 const error_ty = typed_value.ty.errorUnionSet(mod);
674 const payload_ty = typed_value.ty.errorUnionPayload(mod);
675 const is_payload = typed_value.val.errorUnionIsPayload();
646 .un => |un| {
647 const layout = typed_value.ty.unionGetLayout(mod);
676648
677 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
678 const err_val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val;
649 if (layout.payload_size == 0) {
679650 return generateSymbol(bin_file, src_loc, .{
680 .ty = error_ty,
681 .val = err_val,
651 .ty = typed_value.ty.unionTagType(mod).?,
652 .val = un.tag.toValue(),
682653 }, code, debug_output, reloc_info);
683654 }
684655
685 const payload_align = payload_ty.abiAlignment(mod);
686 const error_align = Type.anyerror.abiAlignment(mod);
687 const abi_align = typed_value.ty.abiAlignment(mod);
688
689 // error value first when its type is larger than the error union's payload
690 if (error_align > payload_align) {
656 // Check if we should store the tag first.
657 if (layout.tag_align >= layout.payload_align) {
691658 switch (try generateSymbol(bin_file, src_loc, .{
692 .ty = error_ty,
693 .val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,
659 .ty = typed_value.ty.unionTagType(mod).?,
660 .val = un.tag.toValue(),
694661 }, code, debug_output, reloc_info)) {
695662 .ok => {},
696663 .fail => |em| return Result{ .fail = em },
697664 }
698665 }
699666
700 // emit payload part of the error union
701 {
702 const begin = code.items.len;
703 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.undef;
667 const union_ty = mod.typeToUnion(typed_value.ty).?;
668 const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
669 assert(union_ty.haveFieldTypes());
670 const field_ty = union_ty.fields.values()[field_index].ty;
671 if (!field_ty.hasRuntimeBits(mod)) {
672 try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
673 } else {
704674 switch (try generateSymbol(bin_file, src_loc, .{
705 .ty = payload_ty,
706 .val = payload_val,
675 .ty = field_ty,
676 .val = un.val.toValue(),
707677 }, code, debug_output, reloc_info)) {
708678 .ok => {},
709679 .fail => |em| return Result{ .fail = em },
710680 }
711 const unpadded_end = code.items.len - begin;
712 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
713 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
714681
682 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow;
715683 if (padding > 0) {
716684 try code.writer().writeByteNTimes(0, padding);
717685 }
718686 }
719687
720 // Payload size is larger than error set, so emit our error set last
721 if (error_align <= payload_align) {
722 const begin = code.items.len;
688 if (layout.tag_size > 0) {
723689 switch (try generateSymbol(bin_file, src_loc, .{
724 .ty = error_ty,
725 .val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,
690 .ty = union_ty.tag_ty,
691 .val = un.tag.toValue(),
726692 }, code, debug_output, reloc_info)) {
727693 .ok => {},
728694 .fail => |em| return Result{ .fail = em },
729695 }
730 const unpadded_end = code.items.len - begin;
731 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
732 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
733
734 if (padding > 0) {
735 try code.writer().writeByteNTimes(0, padding);
736 }
737 }
738
739 return Result.ok;
740 },
741 .ErrorSet => {
742 switch (typed_value.val.tag()) {
743 .@"error" => {
744 const name = typed_value.val.getError().?;
745 const kv = try bin_file.options.module.?.getErrorValue(name);
746 try code.writer().writeInt(u32, kv.value, endian);
747 },
748 else => {
749 try code.writer().writeByteNTimes(0, @intCast(usize, Type.anyerror.abiSize(mod)));
750 },
751696 }
752 return Result.ok;
753697 },
754 .Vector => switch (typed_value.val.tag()) {
755 .bytes => {
756 const bytes = typed_value.val.castTag(.bytes).?.data;
757 const len = math.cast(usize, typed_value.ty.arrayLen(mod)) orelse return error.Overflow;
758 const padding = math.cast(usize, typed_value.ty.abiSize(mod) - len) orelse
759 return error.Overflow;
760 try code.ensureUnusedCapacity(len + padding);
761 code.appendSliceAssumeCapacity(bytes[0..len]);
762 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
763 return Result.ok;
764 },
765 .aggregate => {
766 const elem_vals = typed_value.val.castTag(.aggregate).?.data;
767 const elem_ty = typed_value.ty.childType(mod);
768 const len = math.cast(usize, typed_value.ty.arrayLen(mod)) orelse return error.Overflow;
769 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
770 (math.divCeil(u64, elem_ty.bitSize(mod) * len, 8) catch |err| switch (err) {
771 error.DivisionByZero => unreachable,
772 else => |e| return e,
773 })) orelse return error.Overflow;
774 for (elem_vals[0..len]) |elem_val| {
775 switch (try generateSymbol(bin_file, src_loc, .{
776 .ty = elem_ty,
777 .val = elem_val,
778 }, code, debug_output, reloc_info)) {
779 .ok => {},
780 .fail => |em| return Result{ .fail = em },
781 }
782 }
783 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
784 return Result.ok;
785 },
786 .repeated => {
787 const array = typed_value.val.castTag(.repeated).?.data;
788 const elem_ty = typed_value.ty.childType(mod);
789 const len = typed_value.ty.arrayLen(mod);
790 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
791 (math.divCeil(u64, elem_ty.bitSize(mod) * len, 8) catch |err| switch (err) {
792 error.DivisionByZero => unreachable,
793 else => |e| return e,
794 })) orelse return error.Overflow;
795 var index: u64 = 0;
796 while (index < len) : (index += 1) {
797 switch (try generateSymbol(bin_file, src_loc, .{
798 .ty = elem_ty,
799 .val = array,
800 }, code, debug_output, reloc_info)) {
801 .ok => {},
802 .fail => |em| return Result{ .fail = em },
803 }
804 }
805 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
806 return Result.ok;
807 },
808 .str_lit => {
809 const str_lit = typed_value.val.castTag(.str_lit).?.data;
810 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
811 const padding = math.cast(usize, typed_value.ty.abiSize(mod) - str_lit.len) orelse
812 return error.Overflow;
813 try code.ensureUnusedCapacity(str_lit.len + padding);
814 code.appendSliceAssumeCapacity(bytes);
815 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
816 return Result.ok;
817 },
818 else => unreachable,
819 },
820 else => |tag| return Result{ .fail = try ErrorMsg.create(
821 bin_file.allocator,
822 src_loc,
823 "TODO implement generateSymbol for type '{s}'",
824 .{@tagName(tag)},
825 ) },
826698 }
699 return .ok;
827700}
828701
829702fn lowerParentPtr(
830703 bin_file: *link.File,
831704 src_loc: Module.SrcLoc,
832 typed_value: TypedValue,
833 parent_ptr: Value,
705 parent_ptr: InternPool.Index,
834706 code: *std.ArrayList(u8),
835707 debug_output: DebugInfoOutput,
836708 reloc_info: RelocInfo,
837709) CodeGenError!Result {
838710 const mod = bin_file.options.module.?;
839 switch (parent_ptr.tag()) {
840 .field_ptr => {
841 const field_ptr = parent_ptr.castTag(.field_ptr).?.data;
711 const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
712 assert(ptr.len == .none);
713 return switch (ptr.addr) {
714 .decl, .mut_decl => try lowerDeclRef(
715 bin_file,
716 src_loc,
717 switch (ptr.addr) {
718 .decl => |decl| decl,
719 .mut_decl => |mut_decl| mut_decl.decl,
720 else => unreachable,
721 },
722 code,
723 debug_output,
724 reloc_info,
725 ),
726 .int => |int| try generateSymbol(bin_file, src_loc, .{
727 .ty = Type.usize,
728 .val = int.toValue(),
729 }, code, debug_output, reloc_info),
730 .eu_payload => |eu_payload| try lowerParentPtr(
731 bin_file,
732 src_loc,
733 eu_payload,
734 code,
735 debug_output,
736 reloc_info.offset(@intCast(u32, errUnionPayloadOffset(
737 mod.intern_pool.typeOf(eu_payload).toType(),
738 mod,
739 ))),
740 ),
741 .opt_payload => |opt_payload| try lowerParentPtr(
742 bin_file,
743 src_loc,
744 opt_payload,
745 code,
746 debug_output,
747 reloc_info,
748 ),
749 .elem => |elem| try lowerParentPtr(
750 bin_file,
751 src_loc,
752 elem.base,
753 code,
754 debug_output,
755 reloc_info.offset(@intCast(u32, elem.index *
756 mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).abiSize(mod))),
757 ),
758 .field => |field| {
759 const base_type = mod.intern_pool.typeOf(field.base);
842760 return lowerParentPtr(
843761 bin_file,
844762 src_loc,
845 typed_value,
846 field_ptr.container_ptr,
763 field.base,
847764 code,
848765 debug_output,
849 reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag(mod)) {
850 .Pointer => offset: {
851 assert(field_ptr.container_ty.isSlice(mod));
852 break :offset switch (field_ptr.field_index) {
766 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {
767 .ptr_type => |ptr_type| switch (ptr_type.size) {
768 .One, .Many, .C => unreachable,
769 .Slice => switch (field.index) {
853770 0 => 0,
854 1 => field_ptr.container_ty.slicePtrFieldType(mod).abiSize(mod),
771 1 => @divExact(mod.getTarget().ptrBitWidth(), 8),
855772 else => unreachable,
856 };
773 },
857774 },
858 .Struct, .Union => field_ptr.container_ty.structFieldOffset(
859 field_ptr.field_index,
775 .struct_type,
776 .anon_struct_type,
777 .union_type,
778 => @intCast(u32, base_type.toType().childType(mod).structFieldOffset(
779 @intCast(u32, field.index),
860780 mod,
861 ),
862 else => return Result{ .fail = try ErrorMsg.create(
863 bin_file.allocator,
864 src_loc,
865 "TODO implement lowerParentPtr for field_ptr with a container of type {}",
866 .{field_ptr.container_ty.fmt(bin_file.options.module.?)},
867 ) },
868 })),
869 );
870 },
871 .elem_ptr => {
872 const elem_ptr = parent_ptr.castTag(.elem_ptr).?.data;
873 return lowerParentPtr(
874 bin_file,
875 src_loc,
876 typed_value,
877 elem_ptr.array_ptr,
878 code,
879 debug_output,
880 reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(mod))),
881 );
882 },
883 .opt_payload_ptr => {
884 const opt_payload_ptr = parent_ptr.castTag(.opt_payload_ptr).?.data;
885 return lowerParentPtr(
886 bin_file,
887 src_loc,
888 typed_value,
889 opt_payload_ptr.container_ptr,
890 code,
891 debug_output,
892 reloc_info,
893 );
894 },
895 .eu_payload_ptr => {
896 const eu_payload_ptr = parent_ptr.castTag(.eu_payload_ptr).?.data;
897 const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload(mod);
898 return lowerParentPtr(
899 bin_file,
900 src_loc,
901 typed_value,
902 eu_payload_ptr.container_ptr,
903 code,
904 debug_output,
905 reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, mod))),
781 )),
782 else => unreachable,
783 }),
906784 );
907785 },
908 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
909 bin_file,
910 src_loc,
911 typed_value,
912 switch (tag) {
913 .variable => parent_ptr.castTag(.variable).?.data.owner_decl,
914 .decl_ref => parent_ptr.castTag(.decl_ref).?.data,
915 .decl_ref_mut => parent_ptr.castTag(.decl_ref_mut).?.data.decl_index,
916 else => unreachable,
917 },
918 code,
919 debug_output,
920 reloc_info,
921 ),
922 else => |tag| return Result{ .fail = try ErrorMsg.create(
923 bin_file.allocator,
924 src_loc,
925 "TODO implement lowerParentPtr for type '{s}'",
926 .{@tagName(tag)},
927 ) },
928 }
786 .comptime_field => unreachable,
787 };
929788}
930789
931790const RelocInfo = struct {
......@@ -940,36 +799,15 @@ const RelocInfo = struct {
940799fn lowerDeclRef(
941800 bin_file: *link.File,
942801 src_loc: Module.SrcLoc,
943 typed_value: TypedValue,
944802 decl_index: Module.Decl.Index,
945803 code: *std.ArrayList(u8),
946804 debug_output: DebugInfoOutput,
947805 reloc_info: RelocInfo,
948806) CodeGenError!Result {
807 _ = src_loc;
808 _ = debug_output;
949809 const target = bin_file.options.target;
950810 const mod = bin_file.options.module.?;
951 if (typed_value.ty.isSlice(mod)) {
952 // generate ptr
953 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(mod);
954 switch (try generateSymbol(bin_file, src_loc, .{
955 .ty = slice_ptr_field_type,
956 .val = typed_value.val,
957 }, code, debug_output, reloc_info)) {
958 .ok => {},
959 .fail => |em| return Result{ .fail = em },
960 }
961
962 // generate length
963 switch (try generateSymbol(bin_file, src_loc, .{
964 .ty = Type.usize,
965 .val = try mod.intValue(Type.usize, typed_value.val.sliceLen(mod)),
966 }, code, debug_output, reloc_info)) {
967 .ok => {},
968 .fail => |em| return Result{ .fail = em },
969 }
970
971 return Result.ok;
972 }
973811
974812 const ptr_width = target.ptrBitWidth();
975813 const decl = mod.declPtr(decl_index);
......@@ -1154,12 +992,13 @@ pub fn genTypedValue(
1154992 arg_tv: TypedValue,
1155993 owner_decl_index: Module.Decl.Index,
1156994) CodeGenError!GenResult {
995 const mod = bin_file.options.module.?;
1157996 var typed_value = arg_tv;
1158 if (typed_value.val.castTag(.runtime_value)) |rt| {
1159 typed_value.val = rt.data;
997 switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
998 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
999 else => {},
11601000 }
11611001
1162 const mod = bin_file.options.module.?;
11631002 log.debug("genTypedValue: ty = {}, val = {}", .{
11641003 typed_value.ty.fmt(mod),
11651004 typed_value.val.fmtValue(typed_value.ty, mod),
......@@ -1171,17 +1010,14 @@ pub fn genTypedValue(
11711010 const target = bin_file.options.target;
11721011 const ptr_bits = target.ptrBitWidth();
11731012
1174 if (!typed_value.ty.isSlice(mod)) {
1175 if (typed_value.val.castTag(.variable)) |payload| {
1176 return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl);
1177 }
1178 if (typed_value.val.castTag(.decl_ref)) |payload| {
1179 return genDeclRef(bin_file, src_loc, typed_value, payload.data);
1180 }
1181 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
1182 return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
1183 }
1184 }
1013 if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.ip_index)) {
1014 .ptr => |ptr| switch (ptr.addr) {
1015 .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl),
1016 .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl),
1017 else => {},
1018 },
1019 else => {},
1020 };
11851021
11861022 switch (typed_value.ty.zigTypeTag(mod)) {
11871023 .Void => return GenResult.mcv(.none),
......@@ -1215,11 +1051,9 @@ pub fn genTypedValue(
12151051 },
12161052 .Optional => {
12171053 if (typed_value.ty.isPtrLikeOptional(mod)) {
1218 if (typed_value.val.ip_index == .null_value) return GenResult.mcv(.{ .immediate = 0 });
1219
12201054 return genTypedValue(bin_file, src_loc, .{
12211055 .ty = typed_value.ty.optionalChild(mod),
1222 .val = if (typed_value.val.castTag(.opt_payload)) |pl| pl.data else typed_value.val,
1056 .val = typed_value.val.optionalValue(mod) orelse return GenResult.mcv(.{ .immediate = 0 }),
12231057 }, owner_decl_index);
12241058 } else if (typed_value.ty.abiSize(mod) == 1) {
12251059 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) });
......@@ -1234,24 +1068,15 @@ pub fn genTypedValue(
12341068 }, owner_decl_index);
12351069 },
12361070 .ErrorSet => {
1237 switch (typed_value.val.tag()) {
1238 .@"error" => {
1239 const err_name = typed_value.val.castTag(.@"error").?.data.name;
1240 const module = bin_file.options.module.?;
1241 const global_error_set = module.global_error_set;
1242 const error_index = global_error_set.get(err_name).?;
1243 return GenResult.mcv(.{ .immediate = error_index });
1244 },
1245 else => {
1246 // In this case we are rendering an error union which has a 0 bits payload.
1247 return GenResult.mcv(.{ .immediate = 0 });
1248 },
1249 }
1071 const err_name = mod.intern_pool.stringToSlice(mod.intern_pool.indexToKey(typed_value.val.ip_index).err.name);
1072 const global_error_set = mod.global_error_set;
1073 const error_index = global_error_set.get(err_name).?;
1074 return GenResult.mcv(.{ .immediate = error_index });
12501075 },
12511076 .ErrorUnion => {
12521077 const error_type = typed_value.ty.errorUnionSet(mod);
12531078 const payload_type = typed_value.ty.errorUnionPayload(mod);
1254 const is_pl = typed_value.val.errorUnionIsPayload();
1079 const is_pl = typed_value.val.errorUnionIsPayload(mod);
12551080
12561081 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
12571082 // We use the error type directly as the type.
src/codegen/c.zig+523-434
......@@ -257,7 +257,7 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
257257 return .{ .data = ident };
258258}
259259
260/// This data is available when outputting .c code for a `*Module.Fn`.
260/// This data is available when outputting .c code for a `Module.Fn.Index`.
261261/// It is not available when generating .h file.
262262pub const Function = struct {
263263 air: Air,
......@@ -268,7 +268,7 @@ pub const Function = struct {
268268 next_block_index: usize = 0,
269269 object: Object,
270270 lazy_fns: LazyFnMap,
271 func: *Module.Fn,
271 func_index: Module.Fn.Index,
272272 /// All the locals, to be emitted at the top of the function.
273273 locals: std.ArrayListUnmanaged(Local) = .{},
274274 /// Which locals are available for reuse, based on Type.
......@@ -549,33 +549,12 @@ pub const DeclGen = struct {
549549 }
550550
551551 // Chase function values in order to be able to reference the original function.
552 inline for (.{ .function, .extern_fn }) |tag|
553 if (decl.val.castTag(tag)) |func|
554 if (func.data.owner_decl != decl_index)
555 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);
552 if (decl.getFunction(mod)) |func| if (func.owner_decl != decl_index)
553 return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
554 if (decl.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
555 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
556556
557 if (decl.val.castTag(.variable)) |var_payload|
558 try dg.renderFwdDecl(decl_index, var_payload.data);
559
560 if (ty.isSlice(mod)) {
561 if (location == .StaticInitializer) {
562 try writer.writeByte('{');
563 } else {
564 try writer.writeByte('(');
565 try dg.renderType(writer, ty);
566 try writer.writeAll("){ .ptr = ");
567 }
568
569 try dg.renderValue(writer, ty.slicePtrFieldType(mod), val.slicePtr(mod), .Initializer);
570
571 const len_val = try mod.intValue(Type.usize, val.sliceLen(mod));
572
573 if (location == .StaticInitializer) {
574 return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
575 } else {
576 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
577 }
578 }
557 if (decl.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable);
579558
580559 // We shouldn't cast C function pointers as this is UB (when you call
581560 // them). The analysis until now should ensure that the C function
......@@ -594,125 +573,77 @@ pub const DeclGen = struct {
594573
595574 /// Renders a "parent" pointer by recursing to the root decl/variable
596575 /// that its contents are defined with respect to.
597 ///
598 /// Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
599576 fn renderParentPtr(
600577 dg: *DeclGen,
601578 writer: anytype,
602 ptr_val: Value,
603 ptr_ty: Type,
579 ptr_val: InternPool.Index,
604580 location: ValueRenderLocation,
605581 ) error{ OutOfMemory, AnalysisFail }!void {
606582 const mod = dg.module;
607
608 if (!ptr_ty.isSlice(mod)) {
609 try writer.writeByte('(');
610 try dg.renderType(writer, ptr_ty);
611 try writer.writeByte(')');
612 }
613 if (ptr_val.ip_index != .none) switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
614 .int => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),
615 else => unreachable,
616 };
617 switch (ptr_val.tag()) {
618 .decl_ref_mut, .decl_ref, .variable => {
619 const decl_index = switch (ptr_val.tag()) {
620 .decl_ref => ptr_val.castTag(.decl_ref).?.data,
621 .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
622 .variable => ptr_val.castTag(.variable).?.data.owner_decl,
583 const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType();
584 const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
585 switch (ptr.addr) {
586 .decl, .mut_decl => try dg.renderDeclValue(
587 writer,
588 ptr_ty,
589 ptr_val.toValue(),
590 switch (ptr.addr) {
591 .decl => |decl| decl,
592 .mut_decl => |mut_decl| mut_decl.decl,
623593 else => unreachable,
624 };
625 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);
594 },
595 location,
596 ),
597 .int => |int| try writer.print("{x}", .{
598 try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other),
599 }),
600 .eu_payload, .opt_payload => |base| {
601 const base_ty = mod.intern_pool.typeOf(base).toType().childType(mod);
602 // Ensure complete type definition is visible before accessing fields.
603 _ = try dg.typeToIndex(base_ty, .complete);
604 try writer.writeAll("&(");
605 try dg.renderParentPtr(writer, base, location);
606 try writer.writeAll(")->payload");
626607 },
627 .field_ptr => {
628 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
629
608 .elem => |elem| {
609 try writer.writeAll("&(");
610 try dg.renderParentPtr(writer, elem.base, location);
611 try writer.print(")[{d}]", .{elem.index});
612 },
613 .field => |field| {
614 const base_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
630615 // Ensure complete type definition is visible before accessing fields.
631 _ = try dg.typeToIndex(field_ptr.container_ty, .complete);
632
633 const container_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, field_ptr.container_ty);
634
635 switch (fieldLocation(
636 field_ptr.container_ty,
637 ptr_ty,
638 @intCast(u32, field_ptr.field_index),
639 mod,
640 )) {
641 .begin => try dg.renderParentPtr(
642 writer,
643 field_ptr.container_ptr,
644 container_ptr_ty,
645 location,
646 ),
647 .field => |field| {
616 _ = try dg.typeToIndex(base_ty, .complete);
617 switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) {
618 .begin => try dg.renderParentPtr(writer, field.base, location),
619 .field => |name| {
648620 try writer.writeAll("&(");
649 try dg.renderParentPtr(
650 writer,
651 field_ptr.container_ptr,
652 container_ptr_ty,
653 location,
654 );
621 try dg.renderParentPtr(writer, field.base, location);
655622 try writer.writeAll(")->");
656 try dg.writeCValue(writer, field);
623 try dg.writeCValue(writer, name);
657624 },
658625 .byte_offset => |byte_offset| {
659626 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
660
661627 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
662628
663629 try writer.writeAll("((");
664630 try dg.renderType(writer, u8_ptr_ty);
665631 try writer.writeByte(')');
666 try dg.renderParentPtr(
667 writer,
668 field_ptr.container_ptr,
669 container_ptr_ty,
670 location,
671 );
632 try dg.renderParentPtr(writer, field.base, location);
672633 try writer.print(" + {})", .{
673634 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
674635 });
675636 },
676637 .end => {
677638 try writer.writeAll("((");
678 try dg.renderParentPtr(
679 writer,
680 field_ptr.container_ptr,
681 container_ptr_ty,
682 location,
683 );
639 try dg.renderParentPtr(writer, field.base, location);
684640 try writer.print(") + {})", .{
685641 try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),
686642 });
687643 },
688644 }
689645 },
690 .elem_ptr => {
691 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
692 const elem_ptr_ty = try mod.ptrType(.{
693 .size = .C,
694 .elem_type = elem_ptr.elem_ty.ip_index,
695 });
696
697 try writer.writeAll("&(");
698 try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty, location);
699 try writer.print(")[{d}]", .{elem_ptr.index});
700 },
701 .opt_payload_ptr, .eu_payload_ptr => {
702 const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
703 const container_ptr_ty = try mod.ptrType(.{
704 .elem_type = payload_ptr.container_ty.ip_index,
705 .size = .C,
706 });
707
708 // Ensure complete type definition is visible before accessing fields.
709 _ = try dg.typeToIndex(payload_ptr.container_ty, .complete);
710
711 try writer.writeAll("&(");
712 try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location);
713 try writer.writeAll(")->payload");
714 },
715 else => unreachable,
646 .comptime_field => unreachable,
716647 }
717648 }
718649
......@@ -723,11 +654,12 @@ pub const DeclGen = struct {
723654 arg_val: Value,
724655 location: ValueRenderLocation,
725656 ) error{ OutOfMemory, AnalysisFail }!void {
657 const mod = dg.module;
726658 var val = arg_val;
727 if (val.castTag(.runtime_value)) |rt| {
728 val = rt.data;
659 switch (mod.intern_pool.indexToKey(val.ip_index)) {
660 .runtime_value => |rt| val = rt.val.toValue(),
661 else => {},
729662 }
730 const mod = dg.module;
731663 const target = mod.getTarget();
732664 const initializer_type: ValueRenderLocation = switch (location) {
733665 .StaticInitializer => .StaticInitializer,
......@@ -928,175 +860,8 @@ pub const DeclGen = struct {
928860 }
929861 unreachable;
930862 }
931 switch (ty.zigTypeTag(mod)) {
932 .Int => switch (val.tag()) {
933 .field_ptr,
934 .elem_ptr,
935 .opt_payload_ptr,
936 .eu_payload_ptr,
937 .decl_ref_mut,
938 .decl_ref,
939 => try dg.renderParentPtr(writer, val, ty, location),
940 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
941 },
942 .Float => {
943 const bits = ty.floatBits(target);
944 const f128_val = val.toFloat(f128, mod);
945
946 // All unsigned ints matching float types are pre-allocated.
947 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
948
949 assert(bits <= 128);
950 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
951 var repr_val_big = BigInt.Mutable{
952 .limbs = &repr_val_limbs,
953 .len = undefined,
954 .positive = undefined,
955 };
956863
957 switch (bits) {
958 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16, mod))),
959 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32, mod))),
960 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64, mod))),
961 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80, mod))),
962 128 => repr_val_big.set(@bitCast(u128, f128_val)),
963 else => unreachable,
964 }
965
966 const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
967
968 try writer.writeAll("zig_cast_");
969 try dg.renderTypeForBuiltinFnName(writer, ty);
970 try writer.writeByte(' ');
971 var empty = true;
972 if (std.math.isFinite(f128_val)) {
973 try writer.writeAll("zig_make_");
974 try dg.renderTypeForBuiltinFnName(writer, ty);
975 try writer.writeByte('(');
976 switch (bits) {
977 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
978 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
979 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
980 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
981 128 => try writer.print("{x}", .{f128_val}),
982 else => unreachable,
983 }
984 try writer.writeAll(", ");
985 empty = false;
986 } else {
987 // isSignalNan is equivalent to isNan currently, and MSVC doens't have nans, so prefer nan
988 const operation = if (std.math.isNan(f128_val))
989 "nan"
990 else if (std.math.isSignalNan(f128_val))
991 "nans"
992 else if (std.math.isInf(f128_val))
993 "inf"
994 else
995 unreachable;
996
997 if (location == .StaticInitializer) {
998 if (!std.math.isNan(f128_val) and std.math.isSignalNan(f128_val))
999 return dg.fail("TODO: C backend: implement nans rendering in static initializers", .{});
1000
1001 // MSVC doesn't have a way to define a custom or signaling NaN value in a constant expression
1002
1003 // TODO: Re-enable this check, otherwise we're writing qnan bit patterns on msvc incorrectly
1004 // if (std.math.isNan(f128_val) and f128_val != std.math.qnan_f128)
1005 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
1006 }
1007
1008 try writer.writeAll("zig_");
1009 try writer.writeAll(if (location == .StaticInitializer) "init" else "make");
1010 try writer.writeAll("_special_");
1011 try dg.renderTypeForBuiltinFnName(writer, ty);
1012 try writer.writeByte('(');
1013 if (std.math.signbit(f128_val)) try writer.writeByte('-');
1014 try writer.writeAll(", ");
1015 try writer.writeAll(operation);
1016 try writer.writeAll(", ");
1017 if (std.math.isNan(f128_val)) switch (bits) {
1018 // We only actually need to pass the significand, but it will get
1019 // properly masked anyway, so just pass the whole value.
1020 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16, mod))}),
1021 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32, mod))}),
1022 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64, mod))}),
1023 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80, mod))}),
1024 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
1025 else => unreachable,
1026 };
1027 try writer.writeAll(", ");
1028 empty = false;
1029 }
1030 try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});
1031 if (!empty) try writer.writeByte(')');
1032 return;
1033 },
1034 .Pointer => switch (val.ip_index) {
1035 .null_value => if (ty.isSlice(mod)) {
1036 var slice_pl = Value.Payload.Slice{
1037 .base = .{ .tag = .slice },
1038 .data = .{ .ptr = val, .len = Value.undef },
1039 };
1040 const slice_val = Value.initPayload(&slice_pl.base);
1041
1042 return dg.renderValue(writer, ty, slice_val, location);
1043 } else {
1044 try writer.writeAll("((");
1045 try dg.renderType(writer, ty);
1046 try writer.writeAll(")NULL)");
1047 },
1048 .none => switch (val.tag()) {
1049 .variable => {
1050 const decl = val.castTag(.variable).?.data.owner_decl;
1051 return dg.renderDeclValue(writer, ty, val, decl, location);
1052 },
1053 .slice => {
1054 if (!location.isInitializer()) {
1055 try writer.writeByte('(');
1056 try dg.renderType(writer, ty);
1057 try writer.writeByte(')');
1058 }
1059
1060 const slice = val.castTag(.slice).?.data;
1061
1062 try writer.writeByte('{');
1063 try dg.renderValue(writer, ty.slicePtrFieldType(mod), slice.ptr, initializer_type);
1064 try writer.writeAll(", ");
1065 try dg.renderValue(writer, Type.usize, slice.len, initializer_type);
1066 try writer.writeByte('}');
1067 },
1068 .function => {
1069 const func = val.castTag(.function).?.data;
1070 try dg.renderDeclName(writer, func.owner_decl, 0);
1071 },
1072 .extern_fn => {
1073 const extern_fn = val.castTag(.extern_fn).?.data;
1074 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
1075 },
1076 .lazy_align, .lazy_size => {
1077 try writer.writeAll("((");
1078 try dg.renderType(writer, ty);
1079 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
1080 },
1081 .field_ptr,
1082 .elem_ptr,
1083 .opt_payload_ptr,
1084 .eu_payload_ptr,
1085 .decl_ref_mut,
1086 .decl_ref,
1087 => try dg.renderParentPtr(writer, val, ty, location),
1088
1089 else => unreachable,
1090 },
1091 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1092 .int => {
1093 try writer.writeAll("((");
1094 try dg.renderType(writer, ty);
1095 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
1096 },
1097 else => unreachable,
1098 },
1099 },
864 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
1100865 .Array, .Vector => {
1101866 if (location == .FunctionArgument) {
1102867 try writer.writeByte('(');
......@@ -1129,17 +894,6 @@ pub const DeclGen = struct {
1129894 return;
1130895 },
1131896 .none => switch (val.tag()) {
1132 .empty_array => {
1133 const ai = ty.arrayInfo(mod);
1134 try writer.writeByte('{');
1135 if (ai.sentinel) |s| {
1136 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1137 } else {
1138 try writer.writeByte('0');
1139 }
1140 try writer.writeByte('}');
1141 return;
1142 },
1143897 .bytes, .str_lit => |t| {
1144898 const bytes = switch (t) {
1145899 .bytes => val.castTag(.bytes).?.data,
......@@ -1210,91 +964,6 @@ pub const DeclGen = struct {
1210964 try writer.writeByte('}');
1211965 }
1212966 },
1213 .Bool => {
1214 if (val.toBool(mod)) {
1215 return writer.writeAll("true");
1216 } else {
1217 return writer.writeAll("false");
1218 }
1219 },
1220 .Optional => {
1221 const payload_ty = ty.optionalChild(mod);
1222
1223 const is_null_val = Value.makeBool(val.ip_index == .null_value);
1224 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
1225 return dg.renderValue(writer, Type.bool, is_null_val, location);
1226
1227 if (ty.optionalReprIsPayload(mod)) {
1228 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;
1229 return dg.renderValue(writer, payload_ty, payload_val, location);
1230 }
1231
1232 if (!location.isInitializer()) {
1233 try writer.writeByte('(');
1234 try dg.renderType(writer, ty);
1235 try writer.writeByte(')');
1236 }
1237
1238 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef;
1239
1240 try writer.writeAll("{ .payload = ");
1241 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
1242 try writer.writeAll(", .is_null = ");
1243 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
1244 try writer.writeAll(" }");
1245 },
1246 .ErrorSet => {
1247 if (val.castTag(.@"error")) |error_pl| {
1248 // Error values are already defined by genErrDecls.
1249 try writer.print("zig_error_{}", .{fmtIdent(error_pl.data.name)});
1250 } else {
1251 try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, .Other)});
1252 }
1253 },
1254 .ErrorUnion => {
1255 const payload_ty = ty.errorUnionPayload(mod);
1256 const error_ty = ty.errorUnionSet(mod);
1257 const error_val = if (val.errorUnionIsPayload()) try mod.intValue(Type.anyerror, 0) else val;
1258
1259 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1260 return dg.renderValue(writer, error_ty, error_val, location);
1261 }
1262
1263 if (!location.isInitializer()) {
1264 try writer.writeByte('(');
1265 try dg.renderType(writer, ty);
1266 try writer.writeByte(')');
1267 }
1268
1269 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
1270 try writer.writeAll("{ .payload = ");
1271 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
1272 try writer.writeAll(", .error = ");
1273 try dg.renderValue(writer, error_ty, error_val, initializer_type);
1274 try writer.writeAll(" }");
1275 },
1276 .Enum => switch (val.ip_index) {
1277 .none => {
1278 const int_tag_ty = try ty.intTagType(mod);
1279 return dg.renderValue(writer, int_tag_ty, val, location);
1280 },
1281 else => {
1282 const enum_tag = mod.intern_pool.indexToKey(val.ip_index).enum_tag;
1283 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
1284 return dg.renderValue(writer, int_tag_ty.toType(), enum_tag.int.toValue(), location);
1285 },
1286 },
1287 .Fn => switch (val.tag()) {
1288 .function => {
1289 const decl = val.castTag(.function).?.data.owner_decl;
1290 return dg.renderDeclValue(writer, ty, val, decl, location);
1291 },
1292 .extern_fn => {
1293 const decl = val.castTag(.extern_fn).?.data.owner_decl;
1294 return dg.renderDeclValue(writer, ty, val, decl, location);
1295 },
1296 else => unreachable,
1297 },
1298967 .Struct => switch (ty.containerLayout(mod)) {
1299968 .Auto, .Extern => {
1300969 const field_vals = val.castTag(.aggregate).?.data;
......@@ -1408,7 +1077,448 @@ pub const DeclGen = struct {
14081077 }
14091078 },
14101079 },
1411 .Union => {
1080
1081 .Frame,
1082 .AnyFrame,
1083 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
1084 @tagName(tag),
1085 }),
1086
1087 .Float,
1088 .Union,
1089 .Optional,
1090 .ErrorUnion,
1091 .ErrorSet,
1092 .Int,
1093 .Enum,
1094 .Bool,
1095 .Pointer,
1096 => unreachable, // handled below
1097 .Type,
1098 .Void,
1099 .NoReturn,
1100 .ComptimeFloat,
1101 .ComptimeInt,
1102 .Undefined,
1103 .Null,
1104 .Opaque,
1105 .EnumLiteral,
1106 .Fn,
1107 => unreachable, // comptime-only types
1108 };
1109
1110 switch (mod.intern_pool.indexToKey(val.ip_index)) {
1111 .int_type,
1112 .ptr_type,
1113 .array_type,
1114 .vector_type,
1115 .opt_type,
1116 .anyframe_type,
1117 .error_union_type,
1118 .simple_type,
1119 .struct_type,
1120 .anon_struct_type,
1121 .union_type,
1122 .opaque_type,
1123 .enum_type,
1124 .func_type,
1125 .error_set_type,
1126 .inferred_error_set_type,
1127 => unreachable, // types, not values
1128
1129 .undef, .runtime_value => unreachable, // handled above
1130 .simple_value => |simple_value| switch (simple_value) {
1131 .undefined,
1132 .void,
1133 .null,
1134 .empty_struct,
1135 .@"unreachable",
1136 .generic_poison,
1137 => unreachable, // non-runtime values
1138 .false, .true => try writer.writeAll(@tagName(simple_value)),
1139 },
1140 .variable,
1141 .extern_func,
1142 .func,
1143 .enum_literal,
1144 => unreachable, // non-runtime values
1145 .int => |int| switch (int.storage) {
1146 .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
1147 .lazy_align, .lazy_size => {
1148 try writer.writeAll("((");
1149 try dg.renderType(writer, ty);
1150 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
1151 },
1152 },
1153 .err => |err| try writer.print("zig_error_{}", .{
1154 fmtIdent(mod.intern_pool.stringToSlice(err.name)),
1155 }),
1156 .error_union => |error_union| {
1157 const payload_ty = ty.errorUnionPayload(mod);
1158 const error_ty = ty.errorUnionSet(mod);
1159 const error_val = if (val.errorUnionIsPayload(mod)) try mod.intValue(Type.anyerror, 0) else val;
1160
1161 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1162 return dg.renderValue(writer, error_ty, error_val, location);
1163 }
1164
1165 if (!location.isInitializer()) {
1166 try writer.writeByte('(');
1167 try dg.renderType(writer, ty);
1168 try writer.writeByte(')');
1169 }
1170
1171 const payload_val = switch (error_union.val) {
1172 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
1173 .payload => |payload| payload,
1174 }.toValue();
1175
1176 try writer.writeAll("{ .payload = ");
1177 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
1178 try writer.writeAll(", .error = ");
1179 try dg.renderValue(writer, error_ty, error_val, initializer_type);
1180 try writer.writeAll(" }");
1181 },
1182 .enum_tag => {
1183 const enum_tag = mod.intern_pool.indexToKey(val.ip_index).enum_tag;
1184 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
1185 try dg.renderValue(writer, int_tag_ty.toType(), enum_tag.int.toValue(), location);
1186 },
1187 .float => {
1188 const bits = ty.floatBits(target);
1189 const f128_val = val.toFloat(f128, mod);
1190
1191 // All unsigned ints matching float types are pre-allocated.
1192 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
1193
1194 assert(bits <= 128);
1195 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
1196 var repr_val_big = BigInt.Mutable{
1197 .limbs = &repr_val_limbs,
1198 .len = undefined,
1199 .positive = undefined,
1200 };
1201
1202 switch (bits) {
1203 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16, mod))),
1204 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32, mod))),
1205 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64, mod))),
1206 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80, mod))),
1207 128 => repr_val_big.set(@bitCast(u128, f128_val)),
1208 else => unreachable,
1209 }
1210
1211 const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
1212
1213 try writer.writeAll("zig_cast_");
1214 try dg.renderTypeForBuiltinFnName(writer, ty);
1215 try writer.writeByte(' ');
1216 var empty = true;
1217 if (std.math.isFinite(f128_val)) {
1218 try writer.writeAll("zig_make_");
1219 try dg.renderTypeForBuiltinFnName(writer, ty);
1220 try writer.writeByte('(');
1221 switch (bits) {
1222 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
1223 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
1224 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
1225 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
1226 128 => try writer.print("{x}", .{f128_val}),
1227 else => unreachable,
1228 }
1229 try writer.writeAll(", ");
1230 empty = false;
1231 } else {
1232 // isSignalNan is equivalent to isNan currently, and MSVC doens't have nans, so prefer nan
1233 const operation = if (std.math.isNan(f128_val))
1234 "nan"
1235 else if (std.math.isSignalNan(f128_val))
1236 "nans"
1237 else if (std.math.isInf(f128_val))
1238 "inf"
1239 else
1240 unreachable;
1241
1242 if (location == .StaticInitializer) {
1243 if (!std.math.isNan(f128_val) and std.math.isSignalNan(f128_val))
1244 return dg.fail("TODO: C backend: implement nans rendering in static initializers", .{});
1245
1246 // MSVC doesn't have a way to define a custom or signaling NaN value in a constant expression
1247
1248 // TODO: Re-enable this check, otherwise we're writing qnan bit patterns on msvc incorrectly
1249 // if (std.math.isNan(f128_val) and f128_val != std.math.qnan_f128)
1250 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
1251 }
1252
1253 try writer.writeAll("zig_");
1254 try writer.writeAll(if (location == .StaticInitializer) "init" else "make");
1255 try writer.writeAll("_special_");
1256 try dg.renderTypeForBuiltinFnName(writer, ty);
1257 try writer.writeByte('(');
1258 if (std.math.signbit(f128_val)) try writer.writeByte('-');
1259 try writer.writeAll(", ");
1260 try writer.writeAll(operation);
1261 try writer.writeAll(", ");
1262 if (std.math.isNan(f128_val)) switch (bits) {
1263 // We only actually need to pass the significand, but it will get
1264 // properly masked anyway, so just pass the whole value.
1265 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16, mod))}),
1266 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32, mod))}),
1267 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64, mod))}),
1268 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80, mod))}),
1269 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
1270 else => unreachable,
1271 };
1272 try writer.writeAll(", ");
1273 empty = false;
1274 }
1275 try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});
1276 if (!empty) try writer.writeByte(')');
1277 },
1278 .ptr => |ptr| {
1279 if (ptr.len != .none) {
1280 if (!location.isInitializer()) {
1281 try writer.writeByte('(');
1282 try dg.renderType(writer, ty);
1283 try writer.writeByte(')');
1284 }
1285 try writer.writeByte('{');
1286 }
1287 switch (ptr.addr) {
1288 .decl, .mut_decl => try dg.renderDeclValue(
1289 writer,
1290 ty,
1291 val,
1292 switch (ptr.addr) {
1293 .decl => |decl| decl,
1294 .mut_decl => |mut_decl| mut_decl.decl,
1295 else => unreachable,
1296 },
1297 location,
1298 ),
1299 .int => |int| {
1300 try writer.writeAll("((");
1301 try dg.renderType(writer, ty);
1302 try writer.print("){x})", .{
1303 try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other),
1304 });
1305 },
1306 .eu_payload,
1307 .opt_payload,
1308 .elem,
1309 .field,
1310 => try dg.renderParentPtr(writer, val.ip_index, location),
1311 .comptime_field => unreachable,
1312 }
1313 if (ptr.len != .none) {
1314 try writer.writeAll(", ");
1315 try dg.renderValue(writer, Type.usize, ptr.len.toValue(), initializer_type);
1316 try writer.writeByte('}');
1317 }
1318 },
1319 .opt => |opt| {
1320 const payload_ty = ty.optionalChild(mod);
1321
1322 const is_null_val = Value.makeBool(opt.val == .none);
1323 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
1324 return dg.renderValue(writer, Type.bool, is_null_val, location);
1325
1326 if (ty.optionalReprIsPayload(mod)) {
1327 return dg.renderValue(writer, payload_ty, switch (opt.val) {
1328 .none => try mod.intValue(payload_ty, 0),
1329 else => opt.val.toValue(),
1330 }, location);
1331 }
1332
1333 if (!location.isInitializer()) {
1334 try writer.writeByte('(');
1335 try dg.renderType(writer, ty);
1336 try writer.writeByte(')');
1337 }
1338
1339 try writer.writeAll("{ .payload = ");
1340 try dg.renderValue(writer, payload_ty, switch (opt.val) {
1341 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
1342 else => opt.val,
1343 }.toValue(), initializer_type);
1344 try writer.writeAll(", .is_null = ");
1345 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
1346 try writer.writeAll(" }");
1347 },
1348 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1349 .array_type, .vector_type => {
1350 if (location == .FunctionArgument) {
1351 try writer.writeByte('(');
1352 try dg.renderType(writer, ty);
1353 try writer.writeByte(')');
1354 }
1355 // Fall back to generic implementation.
1356
1357 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal
1358 const max_string_initializer_len = 65535;
1359
1360 const ai = ty.arrayInfo(mod);
1361 if (ai.elem_type.eql(Type.u8, mod)) {
1362 if (ai.len <= max_string_initializer_len) {
1363 var literal = stringLiteral(writer);
1364 try literal.start();
1365 var index: usize = 0;
1366 while (index < ai.len) : (index += 1) {
1367 const elem_val = try val.elemValue(mod, index);
1368 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1369 try literal.writeChar(elem_val_u8);
1370 }
1371 if (ai.sentinel) |s| {
1372 const s_u8 = @intCast(u8, s.toUnsignedInt(mod));
1373 if (s_u8 != 0) try literal.writeChar(s_u8);
1374 }
1375 try literal.end();
1376 } else {
1377 try writer.writeByte('{');
1378 var index: usize = 0;
1379 while (index < ai.len) : (index += 1) {
1380 if (index != 0) try writer.writeByte(',');
1381 const elem_val = try val.elemValue(mod, index);
1382 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1383 try writer.print("'\\x{x}'", .{elem_val_u8});
1384 }
1385 if (ai.sentinel) |s| {
1386 if (index != 0) try writer.writeByte(',');
1387 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1388 }
1389 try writer.writeByte('}');
1390 }
1391 } else {
1392 try writer.writeByte('{');
1393 var index: usize = 0;
1394 while (index < ai.len) : (index += 1) {
1395 if (index != 0) try writer.writeByte(',');
1396 const elem_val = try val.elemValue(mod, index);
1397 try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
1398 }
1399 if (ai.sentinel) |s| {
1400 if (index != 0) try writer.writeByte(',');
1401 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1402 }
1403 try writer.writeByte('}');
1404 }
1405 },
1406 .struct_type, .anon_struct_type => switch (ty.containerLayout(mod)) {
1407 .Auto, .Extern => {
1408 const field_vals = val.castTag(.aggregate).?.data;
1409
1410 if (!location.isInitializer()) {
1411 try writer.writeByte('(');
1412 try dg.renderType(writer, ty);
1413 try writer.writeByte(')');
1414 }
1415
1416 try writer.writeByte('{');
1417 var empty = true;
1418 for (field_vals, 0..) |field_val, field_i| {
1419 if (ty.structFieldIsComptime(field_i, mod)) continue;
1420 const field_ty = ty.structFieldType(field_i, mod);
1421 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1422
1423 if (!empty) try writer.writeByte(',');
1424 try dg.renderValue(writer, field_ty, field_val, initializer_type);
1425
1426 empty = false;
1427 }
1428 try writer.writeByte('}');
1429 },
1430 .Packed => {
1431 const field_vals = val.castTag(.aggregate).?.data;
1432 const int_info = ty.intInfo(mod);
1433
1434 const bits = Type.smallestUnsignedBits(int_info.bits - 1);
1435 const bit_offset_ty = try mod.intType(.unsigned, bits);
1436
1437 var bit_offset: u64 = 0;
1438
1439 var eff_num_fields: usize = 0;
1440 for (0..field_vals.len) |field_i| {
1441 if (ty.structFieldIsComptime(field_i, mod)) continue;
1442 const field_ty = ty.structFieldType(field_i, mod);
1443 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1444
1445 eff_num_fields += 1;
1446 }
1447
1448 if (eff_num_fields == 0) {
1449 try writer.writeByte('(');
1450 try dg.renderValue(writer, ty, Value.undef, initializer_type);
1451 try writer.writeByte(')');
1452 } else if (ty.bitSize(mod) > 64) {
1453 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1454 var num_or = eff_num_fields - 1;
1455 while (num_or > 0) : (num_or -= 1) {
1456 try writer.writeAll("zig_or_");
1457 try dg.renderTypeForBuiltinFnName(writer, ty);
1458 try writer.writeByte('(');
1459 }
1460
1461 var eff_index: usize = 0;
1462 var needs_closing_paren = false;
1463 for (field_vals, 0..) |field_val, field_i| {
1464 if (ty.structFieldIsComptime(field_i, mod)) continue;
1465 const field_ty = ty.structFieldType(field_i, mod);
1466 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1467
1468 const cast_context = IntCastContext{ .value = .{ .value = field_val } };
1469 if (bit_offset != 0) {
1470 try writer.writeAll("zig_shl_");
1471 try dg.renderTypeForBuiltinFnName(writer, ty);
1472 try writer.writeByte('(');
1473 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1474 try writer.writeAll(", ");
1475 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1476 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1477 try writer.writeByte(')');
1478 } else {
1479 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1480 }
1481
1482 if (needs_closing_paren) try writer.writeByte(')');
1483 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
1484
1485 bit_offset += field_ty.bitSize(mod);
1486 needs_closing_paren = true;
1487 eff_index += 1;
1488 }
1489 } else {
1490 try writer.writeByte('(');
1491 // a << a_off | b << b_off | c << c_off
1492 var empty = true;
1493 for (field_vals, 0..) |field_val, field_i| {
1494 if (ty.structFieldIsComptime(field_i, mod)) continue;
1495 const field_ty = ty.structFieldType(field_i, mod);
1496 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1497
1498 if (!empty) try writer.writeAll(" | ");
1499 try writer.writeByte('(');
1500 try dg.renderType(writer, ty);
1501 try writer.writeByte(')');
1502
1503 if (bit_offset != 0) {
1504 try dg.renderValue(writer, field_ty, field_val, .Other);
1505 try writer.writeAll(" << ");
1506 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1507 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1508 } else {
1509 try dg.renderValue(writer, field_ty, field_val, .Other);
1510 }
1511
1512 bit_offset += field_ty.bitSize(mod);
1513 empty = false;
1514 }
1515 try writer.writeByte(')');
1516 }
1517 },
1518 },
1519 else => unreachable,
1520 },
1521 .un => {
14121522 const union_obj = val.castTag(.@"union").?.data;
14131523
14141524 if (!location.isInitializer()) {
......@@ -1461,22 +1571,6 @@ pub const DeclGen = struct {
14611571 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
14621572 try writer.writeByte('}');
14631573 },
1464
1465 .ComptimeInt => unreachable,
1466 .ComptimeFloat => unreachable,
1467 .Type => unreachable,
1468 .EnumLiteral => unreachable,
1469 .Void => unreachable,
1470 .NoReturn => unreachable,
1471 .Undefined => unreachable,
1472 .Null => unreachable,
1473 .Opaque => unreachable,
1474
1475 .Frame,
1476 .AnyFrame,
1477 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
1478 @tagName(tag),
1479 }),
14801574 }
14811575 }
14821576
......@@ -1504,8 +1598,7 @@ pub const DeclGen = struct {
15041598 else => unreachable,
15051599 }
15061600 }
1507 if (fn_decl.val.castTag(.function)) |func_payload|
1508 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1601 if (fn_decl.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
15091602 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
15101603
15111604 const trailing = try renderTypePrefix(
......@@ -1747,18 +1840,12 @@ pub const DeclGen = struct {
17471840
17481841 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
17491842 const mod = dg.module;
1750 switch (tv.val.tag()) {
1751 .extern_fn => return true,
1752 .function => {
1753 const func = tv.val.castTag(.function).?.data;
1754 return mod.decl_exports.contains(func.owner_decl);
1755 },
1756 .variable => {
1757 const variable = tv.val.castTag(.variable).?.data;
1758 return mod.decl_exports.contains(variable.owner_decl);
1759 },
1843 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1844 .variable => |variable| mod.decl_exports.contains(variable.decl),
1845 .extern_func => true,
1846 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
17601847 else => unreachable,
1761 }
1848 };
17621849 }
17631850
17641851 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
......@@ -1833,7 +1920,7 @@ pub const DeclGen = struct {
18331920 try dg.writeCValue(writer, member);
18341921 }
18351922
1836 fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: *Module.Var) !void {
1923 fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: InternPool.Key.Variable) !void {
18371924 const decl = dg.module.declPtr(decl_index);
18381925 const fwd_decl_writer = dg.fwd_decl.writer();
18391926 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
......@@ -1844,7 +1931,7 @@ pub const DeclGen = struct {
18441931 fwd_decl_writer,
18451932 decl.ty,
18461933 .{ .decl = decl_index },
1847 CQualifiers.init(.{ .@"const" = !variable.is_mutable }),
1934 CQualifiers.init(.{ .@"const" = variable.is_const }),
18481935 decl.@"align",
18491936 .complete,
18501937 );
......@@ -1858,7 +1945,7 @@ pub const DeclGen = struct {
18581945
18591946 if (mod.decl_exports.get(decl_index)) |exports| {
18601947 try writer.writeAll(exports.items[export_index].options.name);
1861 } else if (decl.isExtern()) {
1948 } else if (decl.isExtern(mod)) {
18621949 try writer.writeAll(mem.span(decl.name));
18631950 } else {
18641951 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
......@@ -2416,8 +2503,11 @@ pub fn genErrDecls(o: *Object) !void {
24162503 var max_name_len: usize = 0;
24172504 for (mod.error_name_list.items, 0..) |name, value| {
24182505 max_name_len = std.math.max(name.len, max_name_len);
2419 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };
2420 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);
2506 const err_val = try mod.intern(.{ .err = .{
2507 .ty = .anyerror_type,
2508 .name = mod.intern_pool.getString(name).unwrap().?,
2509 } });
2510 try o.dg.renderValue(writer, Type.anyerror, err_val.toValue(), .Other);
24212511 try writer.print(" = {d}u,\n", .{value});
24222512 }
24232513 o.indent_writer.popIndent();
......@@ -2451,7 +2541,7 @@ pub fn genErrDecls(o: *Object) !void {
24512541
24522542 const name_array_ty = try mod.arrayType(.{
24532543 .len = mod.error_name_list.items.len,
2454 .child = .const_slice_u8_sentinel_0_type,
2544 .child = .slice_const_u8_sentinel_0_type,
24552545 .sentinel = .zero_u8,
24562546 });
24572547
......@@ -2497,7 +2587,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
24972587 .tag_name => {
24982588 const enum_ty = val.data.tag_name;
24992589
2500 const name_slice_ty = Type.const_slice_u8_sentinel_0;
2590 const name_slice_ty = Type.slice_const_u8_sentinel_0;
25012591
25022592 try w.writeAll("static ");
25032593 try o.dg.renderType(w, name_slice_ty);
......@@ -2668,14 +2758,13 @@ pub fn genDecl(o: *Object) !void {
26682758 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };
26692759
26702760 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2671 if (tv.val.tag() == .extern_fn) {
2761 if (decl.getExternFunc(mod)) |_| {
26722762 const fwd_decl_writer = o.dg.fwd_decl.writer();
26732763 try fwd_decl_writer.writeAll("zig_extern ");
26742764 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });
26752765 try fwd_decl_writer.writeAll(";\n");
26762766 try genExports(o);
2677 } else if (tv.val.castTag(.variable)) |var_payload| {
2678 const variable: *Module.Var = var_payload.data;
2767 } else if (decl.getVariable(mod)) |variable| {
26792768 try o.dg.renderFwdDecl(decl_c_value.decl, variable);
26802769 try genExports(o);
26812770
......@@ -2690,7 +2779,7 @@ pub fn genDecl(o: *Object) !void {
26902779 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);
26912780 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
26922781 try w.writeAll(" = ");
2693 try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer);
2782 try o.dg.renderValue(w, tv.ty, variable.init.toValue(), .StaticInitializer);
26942783 try w.writeByte(';');
26952784 try o.indent_writer.insertNewline();
26962785 } else {
......@@ -4157,10 +4246,13 @@ fn airCall(
41574246 known: {
41584247 const fn_decl = fn_decl: {
41594248 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4160 break :fn_decl switch (callee_val.tag()) {
4161 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
4162 .function => callee_val.castTag(.function).?.data.owner_decl,
4163 .decl_ref => callee_val.castTag(.decl_ref).?.data,
4249 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4250 .extern_func => |extern_func| extern_func.decl,
4251 .func => |func| mod.funcPtr(func.index).owner_decl,
4252 .ptr => |ptr| switch (ptr.addr) {
4253 .decl => |decl| decl,
4254 else => break :known,
4255 },
41644256 else => break :known,
41654257 };
41664258 };
......@@ -4231,9 +4323,9 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
42314323
42324324fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
42334325 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4234 const writer = f.object.writer();
4235 const function = f.air.values[ty_pl.payload].castTag(.function).?.data;
42364326 const mod = f.object.dg.module;
4327 const writer = f.object.writer();
4328 const function = f.air.values[ty_pl.payload].getFunction(mod).?;
42374329 try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name});
42384330 return .none;
42394331}
......@@ -6634,9 +6726,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66346726 try f.writeCValue(writer, accum, .Other);
66356727 try writer.writeAll(" = ");
66366728
6637 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
6638 defer arena.deinit();
6639
66406729 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
66416730 .Or, .Xor, .Add => try mod.intValue(scalar_ty, 0),
66426731 .And => switch (scalar_ty.zigTypeTag(mod)) {
......@@ -6654,7 +6743,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66546743 },
66556744 .Max => switch (scalar_ty.zigTypeTag(mod)) {
66566745 .Bool => try mod.intValue(scalar_ty, 0),
6657 .Int => try scalar_ty.minInt(arena.allocator(), mod),
6746 .Int => try scalar_ty.minInt(mod),
66586747 .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
66596748 else => unreachable,
66606749 },
src/codegen/llvm.zig+732-876
......@@ -582,7 +582,7 @@ pub const Object = struct {
582582 llvm_usize_ty,
583583 };
584584 const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False);
585 const slice_ty = Type.const_slice_u8_sentinel_0;
585 const slice_ty = Type.slice_const_u8_sentinel_0;
586586 const slice_alignment = slice_ty.abiAlignment(mod);
587587
588588 const error_name_list = mod.error_name_list.items;
......@@ -866,10 +866,11 @@ pub const Object = struct {
866866 pub fn updateFunc(
867867 o: *Object,
868868 mod: *Module,
869 func: *Module.Fn,
869 func_index: Module.Fn.Index,
870870 air: Air,
871871 liveness: Liveness,
872872 ) !void {
873 const func = mod.funcPtr(func_index);
873874 const decl_index = func.owner_decl;
874875 const decl = mod.declPtr(decl_index);
875876 const target = mod.getTarget();
......@@ -886,7 +887,7 @@ pub const Object = struct {
886887
887888 const llvm_func = try dg.resolveLlvmFunction(decl_index);
888889
889 if (mod.align_stack_fns.get(func)) |align_info| {
890 if (mod.align_stack_fns.get(func_index)) |align_info| {
890891 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);
891892 dg.addFnAttr(llvm_func, "noinline");
892893 } else {
......@@ -1164,7 +1165,7 @@ pub const Object = struct {
11641165 di_file = try dg.object.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope);
11651166
11661167 const line_number = decl.src_line + 1;
1167 const is_internal_linkage = decl.val.tag() != .extern_fn and
1168 const is_internal_linkage = decl.getExternFunc(mod) == null and
11681169 !mod.decl_exports.contains(decl_index);
11691170 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
11701171 llvm.DIFlags.NoReturn
......@@ -1269,18 +1270,20 @@ pub const Object = struct {
12691270 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
12701271 const llvm_global = self.decl_map.get(decl_index) orelse return;
12711272 const decl = mod.declPtr(decl_index);
1272 if (decl.isExtern()) {
1273 const is_wasm_fn = mod.getTarget().isWasm() and try decl.isFunction(mod);
1274 const mangle_name = is_wasm_fn and
1275 decl.getExternFn().?.lib_name != null and
1276 !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");
1277 const decl_name = if (mangle_name) name: {
1278 const tmp = try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{
1279 decl.name, decl.getExternFn().?.lib_name.?,
1280 });
1281 break :name tmp.ptr;
1282 } else decl.name;
1283 defer if (mangle_name) gpa.free(std.mem.sliceTo(decl_name, 0));
1273 if (decl.isExtern(mod)) {
1274 var free_decl_name = false;
1275 const decl_name = decl_name: {
1276 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {
1277 if (mod.intern_pool.stringToSliceUnwrap(decl.getExternFunc(mod).?.lib_name)) |lib_name| {
1278 if (!std.mem.eql(u8, lib_name, "c")) {
1279 free_decl_name = true;
1280 break :decl_name try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{ decl.name, lib_name });
1281 }
1282 }
1283 }
1284 break :decl_name std.mem.span(decl.name);
1285 };
1286 defer if (free_decl_name) gpa.free(decl_name);
12841287
12851288 llvm_global.setValueName(decl_name);
12861289 if (self.getLlvmGlobal(decl_name)) |other_global| {
......@@ -1303,13 +1306,13 @@ pub const Object = struct {
13031306 di_global.replaceLinkageName(linkage_name);
13041307 }
13051308 }
1306 if (decl.val.castTag(.variable)) |variable| {
1307 if (variable.data.is_threadlocal) {
1309 if (decl.getVariable(mod)) |variable| {
1310 if (variable.is_threadlocal) {
13081311 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13091312 } else {
13101313 llvm_global.setThreadLocalMode(.NotThreadLocal);
13111314 }
1312 if (variable.data.is_weak_linkage) {
1315 if (variable.is_weak_linkage) {
13131316 llvm_global.setLinkage(.ExternalWeak);
13141317 }
13151318 }
......@@ -1345,8 +1348,8 @@ pub const Object = struct {
13451348 defer gpa.free(section_z);
13461349 llvm_global.setSection(section_z);
13471350 }
1348 if (decl.val.castTag(.variable)) |variable| {
1349 if (variable.data.is_threadlocal) {
1351 if (decl.getVariable(mod)) |variable| {
1352 if (variable.is_threadlocal) {
13501353 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13511354 }
13521355 }
......@@ -1379,9 +1382,9 @@ pub const Object = struct {
13791382 llvm_global.setLinkage(.Internal);
13801383 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
13811384 llvm_global.setUnnamedAddr(.True);
1382 if (decl.val.castTag(.variable)) |variable| {
1385 if (decl.getVariable(mod)) |variable| {
13831386 const single_threaded = mod.comp.bin_file.options.single_threaded;
1384 if (variable.data.is_threadlocal and !single_threaded) {
1387 if (variable.is_threadlocal and !single_threaded) {
13851388 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13861389 } else {
13871390 llvm_global.setThreadLocalMode(.NotThreadLocal);
......@@ -1510,12 +1513,11 @@ pub const Object = struct {
15101513 for (enum_type.names, 0..) |field_name_ip, i| {
15111514 const field_name_z = ip.stringToSlice(field_name_ip);
15121515
1513 var bigint_space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
1514 const storage = if (enum_type.values.len != 0)
1515 ip.indexToKey(enum_type.values[i]).int.storage
1516 var bigint_space: Value.BigIntSpace = undefined;
1517 const bigint = if (enum_type.values.len != 0)
1518 enum_type.values[i].toValue().toBigInt(&bigint_space, mod)
15161519 else
1517 InternPool.Key.Int.Storage{ .u64 = i };
1518 const bigint = storage.toBigInt(&bigint_space);
1520 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
15191521
15201522 if (bigint.limbs.len == 1) {
15211523 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
......@@ -2442,6 +2444,7 @@ pub const DeclGen = struct {
24422444 }
24432445
24442446 fn genDecl(dg: *DeclGen) !void {
2447 const mod = dg.module;
24452448 const decl = dg.decl;
24462449 const decl_index = dg.decl_index;
24472450 assert(decl.has_tv);
......@@ -2449,19 +2452,16 @@ pub const DeclGen = struct {
24492452 log.debug("gen: {s} type: {}, value: {}", .{
24502453 decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(),
24512454 });
2452 assert(decl.val.ip_index != .none or decl.val.tag() != .function);
2453 if (decl.val.castTag(.extern_fn)) |extern_fn| {
2454 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
2455 if (decl.getExternFunc(mod)) |extern_func| {
2456 _ = try dg.resolveLlvmFunction(extern_func.decl);
24552457 } else {
2456 const mod = dg.module;
24572458 const target = mod.getTarget();
24582459 var global = try dg.resolveGlobalDecl(decl_index);
24592460 global.setAlignment(decl.getAlignment(mod));
24602461 if (decl.@"linksection") |section| global.setSection(section);
24612462 assert(decl.has_tv);
2462 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
2463 const variable = payload.data;
2464 break :init_val variable.init;
2463 const init_val = if (decl.getVariable(mod)) |variable| init_val: {
2464 break :init_val variable.init.toValue();
24652465 } else init_val: {
24662466 global.setGlobalConstant(.True);
24672467 break :init_val decl.val;
......@@ -2519,7 +2519,7 @@ pub const DeclGen = struct {
25192519 );
25202520
25212521 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.getVariable().toNode());
2522 if (!is_internal_linkage or decl.isExtern()) global.attachMetaData(di_global);
2522 if (!is_internal_linkage or decl.isExtern(mod)) global.attachMetaData(di_global);
25232523 }
25242524 }
25252525 }
......@@ -2548,17 +2548,16 @@ pub const DeclGen = struct {
25482548 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);
25492549 gop.value_ptr.* = llvm_fn;
25502550
2551 const is_extern = decl.isExtern();
2551 const is_extern = decl.isExtern(mod);
25522552 if (!is_extern) {
25532553 llvm_fn.setLinkage(.Internal);
25542554 llvm_fn.setUnnamedAddr(.True);
25552555 } else {
25562556 if (target.isWasm()) {
25572557 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));
2558 if (decl.getExternFn().?.lib_name) |lib_name| {
2559 const module_name = std.mem.sliceTo(lib_name, 0);
2560 if (!std.mem.eql(u8, module_name, "c")) {
2561 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
2558 if (mod.intern_pool.stringToSliceUnwrap(decl.getExternFunc(mod).?.lib_name)) |lib_name| {
2559 if (!std.mem.eql(u8, lib_name, "c")) {
2560 dg.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
25622561 }
25632562 }
25642563 }
......@@ -2695,11 +2694,12 @@ pub const DeclGen = struct {
26952694 if (gop.found_existing) return gop.value_ptr.*;
26962695 errdefer assert(dg.object.decl_map.remove(decl_index));
26972696
2698 const decl = dg.module.declPtr(decl_index);
2699 const fqn = try decl.getFullyQualifiedName(dg.module);
2697 const mod = dg.module;
2698 const decl = mod.declPtr(decl_index);
2699 const fqn = try decl.getFullyQualifiedName(mod);
27002700 defer dg.gpa.free(fqn);
27012701
2702 const target = dg.module.getTarget();
2702 const target = mod.getTarget();
27032703
27042704 const llvm_type = try dg.lowerType(decl.ty);
27052705 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
......@@ -2712,18 +2712,18 @@ pub const DeclGen = struct {
27122712 gop.value_ptr.* = llvm_global;
27132713
27142714 // This is needed for declarations created by `@extern`.
2715 if (decl.isExtern()) {
2715 if (decl.isExtern(mod)) {
27162716 llvm_global.setValueName(decl.name);
27172717 llvm_global.setUnnamedAddr(.False);
27182718 llvm_global.setLinkage(.External);
2719 if (decl.val.castTag(.variable)) |variable| {
2720 const single_threaded = dg.module.comp.bin_file.options.single_threaded;
2721 if (variable.data.is_threadlocal and !single_threaded) {
2719 if (decl.getVariable(mod)) |variable| {
2720 const single_threaded = mod.comp.bin_file.options.single_threaded;
2721 if (variable.is_threadlocal and !single_threaded) {
27222722 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
27232723 } else {
27242724 llvm_global.setThreadLocalMode(.NotThreadLocal);
27252725 }
2726 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
2726 if (variable.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
27272727 }
27282728 } else {
27292729 llvm_global.setLinkage(.Internal);
......@@ -3199,468 +3199,344 @@ pub const DeclGen = struct {
31993199 const mod = dg.module;
32003200 const target = mod.getTarget();
32013201 var tv = arg_tv;
3202 if (tv.val.castTag(.runtime_value)) |rt| {
3203 tv.val = rt.data;
3202 switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3203 .runtime_value => |rt| tv.val = rt.val.toValue(),
3204 else => {},
32043205 }
3205 if (tv.val.isUndef(mod)) {
3206 if (tv.val.isUndefDeep(mod)) {
32063207 const llvm_type = try dg.lowerType(tv.ty);
32073208 return llvm_type.getUndef();
32083209 }
3209 switch (tv.ty.zigTypeTag(mod)) {
3210 .Bool => {
3211 const llvm_type = try dg.lowerType(tv.ty);
3212 return if (tv.val.toBool(mod)) llvm_type.constAllOnes() else llvm_type.constNull();
3213 },
3214 .Int => switch (tv.val.ip_index) {
3215 .none => switch (tv.val.tag()) {
3216 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
3217 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
3218 else => {
3219 var bigint_space: Value.BigIntSpace = undefined;
3220 const bigint = tv.val.toBigInt(&bigint_space, mod);
3221 return lowerBigInt(dg, tv.ty, bigint);
3222 },
3223 },
3224 else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3225 .int => |int| {
3226 var bigint_space: Value.BigIntSpace = undefined;
3227 const bigint = int.storage.toBigInt(&bigint_space);
3228 return lowerBigInt(dg, tv.ty, bigint);
3229 },
3230 else => unreachable,
3231 },
3232 },
3233 .Enum => {
3234 const int_val = try tv.enumToInt(mod);
32353210
3236 var bigint_space: Value.BigIntSpace = undefined;
3237 const bigint = int_val.toBigInt(&bigint_space, mod);
3238
3239 const int_info = tv.ty.intInfo(mod);
3240 const llvm_type = dg.context.intType(int_info.bits);
3241
3242 const unsigned_val = v: {
3243 if (bigint.limbs.len == 1) {
3244 break :v llvm_type.constInt(bigint.limbs[0], .False);
3245 }
3246 if (@sizeOf(usize) == @sizeOf(u64)) {
3247 break :v llvm_type.constIntOfArbitraryPrecision(
3248 @intCast(c_uint, bigint.limbs.len),
3249 bigint.limbs.ptr,
3250 );
3251 }
3252 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
3253 };
3254 if (!bigint.positive) {
3255 return llvm.constNeg(unsigned_val);
3256 }
3257 return unsigned_val;
3258 },
3259 .Float => {
3260 const llvm_ty = try dg.lowerType(tv.ty);
3261 switch (tv.ty.floatBits(target)) {
3262 16 => {
3263 const repr = @bitCast(u16, tv.val.toFloat(f16, mod));
3264 const llvm_i16 = dg.context.intType(16);
3265 const int = llvm_i16.constInt(repr, .False);
3266 return int.constBitCast(llvm_ty);
3267 },
3268 32 => {
3269 const repr = @bitCast(u32, tv.val.toFloat(f32, mod));
3270 const llvm_i32 = dg.context.intType(32);
3271 const int = llvm_i32.constInt(repr, .False);
3272 return int.constBitCast(llvm_ty);
3273 },
3274 64 => {
3275 const repr = @bitCast(u64, tv.val.toFloat(f64, mod));
3276 const llvm_i64 = dg.context.intType(64);
3277 const int = llvm_i64.constInt(repr, .False);
3278 return int.constBitCast(llvm_ty);
3279 },
3280 80 => {
3281 const float = tv.val.toFloat(f80, mod);
3282 const repr = std.math.break_f80(float);
3283 const llvm_i80 = dg.context.intType(80);
3284 var x = llvm_i80.constInt(repr.exp, .False);
3285 x = x.constShl(llvm_i80.constInt(64, .False));
3286 x = x.constOr(llvm_i80.constInt(repr.fraction, .False));
3287 if (backendSupportsF80(target)) {
3288 return x.constBitCast(llvm_ty);
3289 } else {
3290 return x;
3291 }
3292 },
3293 128 => {
3294 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128, mod));
3295 // LLVM seems to require that the lower half of the f128 be placed first
3296 // in the buffer.
3297 if (native_endian == .Big) {
3298 std.mem.swap(u64, &buf[0], &buf[1]);
3299 }
3300 const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf);
3301 return int.constBitCast(llvm_ty);
3302 },
3303 else => unreachable,
3304 }
3305 },
3306 .Pointer => switch (tv.val.ip_index) {
3307 .null_value => {
3308 const llvm_type = try dg.lowerType(tv.ty);
3309 return llvm_type.constNull();
3310 },
3311 .none => switch (tv.val.tag()) {
3312 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
3313 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
3314 .variable => {
3315 const decl_index = tv.val.castTag(.variable).?.data.owner_decl;
3316 const decl = dg.module.declPtr(decl_index);
3317 dg.module.markDeclAlive(decl);
3318
3319 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
3320 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
3321
3322 const val = try dg.resolveGlobalDecl(decl_index);
3323 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
3324 val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace))
3325 else
3326 val;
3327 return addrspace_casted_ptr;
3328 },
3329 .slice => {
3330 const slice = tv.val.castTag(.slice).?.data;
3331 const fields: [2]*llvm.Value = .{
3332 try dg.lowerValue(.{
3333 .ty = tv.ty.slicePtrFieldType(mod),
3334 .val = slice.ptr,
3335 }),
3336 try dg.lowerValue(.{
3337 .ty = Type.usize,
3338 .val = slice.len,
3339 }),
3340 };
3341 return dg.context.constStruct(&fields, fields.len, .False);
3342 },
3343 .lazy_align, .lazy_size => {
3344 const llvm_usize = try dg.lowerType(Type.usize);
3345 const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(mod), .False);
3346 return llvm_int.constIntToPtr(try dg.lowerType(tv.ty));
3347 },
3348 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
3349 return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo(mod).bit_offset % 8 == 0);
3350 },
3351 .opt_payload => {
3352 const payload = tv.val.castTag(.opt_payload).?.data;
3353 return dg.lowerParentPtr(payload, tv.ty.ptrInfo(mod).bit_offset % 8 == 0);
3354 },
3355 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
3356 tv.ty.fmtDebug(), tag,
3357 }),
3358 },
3359 else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3360 .int => |int| return dg.lowerIntAsPtr(int),
3361 .ptr => |ptr| {
3362 const ptr_tv: TypedValue = switch (ptr.len) {
3363 .none => tv,
3364 else => .{ .ty = tv.ty.slicePtrFieldType(mod), .val = tv.val.slicePtr(mod) },
3365 };
3366 const llvm_ptr_val = switch (ptr.addr) {
3367 .@"var" => |@"var"| ptr: {
3368 const decl = dg.module.declPtr(@"var".owner_decl);
3369 dg.module.markDeclAlive(decl);
3370
3371 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
3372 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
3373
3374 const val = try dg.resolveGlobalDecl(@"var".owner_decl);
3375 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
3376 val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace))
3377 else
3378 val;
3379 break :ptr addrspace_casted_ptr;
3380 },
3381 .decl => |decl| try dg.lowerDeclRefValue(ptr_tv, decl),
3382 .mut_decl => |mut_decl| try dg.lowerDeclRefValue(ptr_tv, mut_decl.decl),
3383 .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int),
3384 .eu_payload,
3385 .opt_payload,
3386 .elem,
3387 .field,
3388 => try dg.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).bit_offset % 8 == 0),
3389 .comptime_field => unreachable,
3390 };
3391 switch (ptr.len) {
3392 .none => return llvm_ptr_val,
3393 else => {
3394 const fields: [2]*llvm.Value = .{
3395 llvm_ptr_val,
3396 try dg.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }),
3397 };
3398 return dg.context.constStruct(&fields, fields.len, .False);
3399 },
3400 }
3401 },
3402 else => unreachable,
3211 if (tv.val.ip_index == .none) switch (tv.ty.zigTypeTag(mod)) {
3212 .Array => switch (tv.val.tag()) {
3213 .bytes => {
3214 const bytes = tv.val.castTag(.bytes).?.data;
3215 return dg.context.constString(
3216 bytes.ptr,
3217 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3218 .True, // Don't null terminate. Bytes has the sentinel, if any.
3219 );
34033220 },
3404 },
3405 .Array => switch (tv.val.ip_index) {
3406 .none => switch (tv.val.tag()) {
3407 .bytes => {
3408 const bytes = tv.val.castTag(.bytes).?.data;
3409 return dg.context.constString(
3410 bytes.ptr,
3411 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3412 .True, // Don't null terminate. Bytes has the sentinel, if any.
3413 );
3414 },
3415 .str_lit => {
3416 const str_lit = tv.val.castTag(.str_lit).?.data;
3417 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3418 if (tv.ty.sentinel(mod)) |sent_val| {
3419 const byte = @intCast(u8, sent_val.toUnsignedInt(mod));
3420 if (byte == 0 and bytes.len > 0) {
3421 return dg.context.constString(
3422 bytes.ptr,
3423 @intCast(c_uint, bytes.len),
3424 .False, // Yes, null terminate.
3425 );
3426 }
3427 var array = std.ArrayList(u8).init(dg.gpa);
3428 defer array.deinit();
3429 try array.ensureUnusedCapacity(bytes.len + 1);
3430 array.appendSliceAssumeCapacity(bytes);
3431 array.appendAssumeCapacity(byte);
3432 return dg.context.constString(
3433 array.items.ptr,
3434 @intCast(c_uint, array.items.len),
3435 .True, // Don't null terminate.
3436 );
3437 } else {
3221 .str_lit => {
3222 const str_lit = tv.val.castTag(.str_lit).?.data;
3223 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3224 if (tv.ty.sentinel(mod)) |sent_val| {
3225 const byte = @intCast(u8, sent_val.toUnsignedInt(mod));
3226 if (byte == 0 and bytes.len > 0) {
34383227 return dg.context.constString(
34393228 bytes.ptr,
34403229 @intCast(c_uint, bytes.len),
3441 .True, // Don't null terminate. `bytes` has the sentinel, if any.
3442 );
3443 }
3444 },
3445 .aggregate => {
3446 const elem_vals = tv.val.castTag(.aggregate).?.data;
3447 const elem_ty = tv.ty.childType(mod);
3448 const gpa = dg.gpa;
3449 const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel(mod));
3450 const llvm_elems = try gpa.alloc(*llvm.Value, len);
3451 defer gpa.free(llvm_elems);
3452 var need_unnamed = false;
3453 for (elem_vals[0..len], 0..) |elem_val, i| {
3454 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val });
3455 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3456 }
3457 if (need_unnamed) {
3458 return dg.context.constStruct(
3459 llvm_elems.ptr,
3460 @intCast(c_uint, llvm_elems.len),
3461 .True,
3462 );
3463 } else {
3464 const llvm_elem_ty = try dg.lowerType(elem_ty);
3465 return llvm_elem_ty.constArray(
3466 llvm_elems.ptr,
3467 @intCast(c_uint, llvm_elems.len),
3230 .False, // Yes, null terminate.
34683231 );
34693232 }
3470 },
3471 .repeated => {
3472 const val = tv.val.castTag(.repeated).?.data;
3473 const elem_ty = tv.ty.childType(mod);
3474 const sentinel = tv.ty.sentinel(mod);
3475 const len = @intCast(usize, tv.ty.arrayLen(mod));
3476 const len_including_sent = len + @boolToInt(sentinel != null);
3477 const gpa = dg.gpa;
3478 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3479 defer gpa.free(llvm_elems);
3233 var array = std.ArrayList(u8).init(dg.gpa);
3234 defer array.deinit();
3235 try array.ensureUnusedCapacity(bytes.len + 1);
3236 array.appendSliceAssumeCapacity(bytes);
3237 array.appendAssumeCapacity(byte);
3238 return dg.context.constString(
3239 array.items.ptr,
3240 @intCast(c_uint, array.items.len),
3241 .True, // Don't null terminate.
3242 );
3243 } else {
3244 return dg.context.constString(
3245 bytes.ptr,
3246 @intCast(c_uint, bytes.len),
3247 .True, // Don't null terminate. `bytes` has the sentinel, if any.
3248 );
3249 }
3250 },
3251 else => unreachable,
3252 },
3253 .Struct => {
3254 const llvm_struct_ty = try dg.lowerType(tv.ty);
3255 const gpa = dg.gpa;
3256
3257 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3258 .anon_struct_type => |tuple| {
3259 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3260 defer llvm_fields.deinit(gpa);
34803261
3262 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
3263
3264 comptime assert(struct_layout_version == 2);
3265 var offset: u64 = 0;
3266 var big_align: u32 = 0;
34813267 var need_unnamed = false;
3482 if (len != 0) {
3483 for (llvm_elems[0..len]) |*elem| {
3484 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val });
3268
3269 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3270 if (field_val != .none) continue;
3271 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
3272
3273 const field_align = field_ty.toType().abiAlignment(mod);
3274 big_align = @max(big_align, field_align);
3275 const prev_offset = offset;
3276 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3277
3278 const padding_len = offset - prev_offset;
3279 if (padding_len > 0) {
3280 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3281 // TODO make this and all other padding elsewhere in debug
3282 // builds be 0xaa not undef.
3283 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
34853284 }
3486 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3487 }
34883285
3489 if (sentinel) |sent| {
3490 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3491 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3286 const field_llvm_val = try dg.lowerValue(.{
3287 .ty = field_ty.toType(),
3288 .val = try tv.val.fieldValue(mod, i),
3289 });
3290
3291 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
3292
3293 llvm_fields.appendAssumeCapacity(field_llvm_val);
3294
3295 offset += field_ty.toType().abiSize(mod);
3296 }
3297 {
3298 const prev_offset = offset;
3299 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3300 const padding_len = offset - prev_offset;
3301 if (padding_len > 0) {
3302 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3303 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3304 }
34923305 }
34933306
34943307 if (need_unnamed) {
34953308 return dg.context.constStruct(
3496 llvm_elems.ptr,
3497 @intCast(c_uint, llvm_elems.len),
3498 .True,
3309 llvm_fields.items.ptr,
3310 @intCast(c_uint, llvm_fields.items.len),
3311 .False,
34993312 );
35003313 } else {
3501 const llvm_elem_ty = try dg.lowerType(elem_ty);
3502 return llvm_elem_ty.constArray(
3503 llvm_elems.ptr,
3504 @intCast(c_uint, llvm_elems.len),
3314 return llvm_struct_ty.constNamedStruct(
3315 llvm_fields.items.ptr,
3316 @intCast(c_uint, llvm_fields.items.len),
35053317 );
35063318 }
35073319 },
3508 .empty_array_sentinel => {
3509 const elem_ty = tv.ty.childType(mod);
3510 const sent_val = tv.ty.sentinel(mod).?;
3511 const sentinel = try dg.lowerValue(.{ .ty = elem_ty, .val = sent_val });
3512 const llvm_elems: [1]*llvm.Value = .{sentinel};
3513 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
3514 if (need_unnamed) {
3515 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
3516 } else {
3517 const llvm_elem_ty = try dg.lowerType(elem_ty);
3518 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
3519 }
3520 },
3320 .struct_type => |struct_type| struct_type,
35213321 else => unreachable,
3522 },
3523 else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3524 .aggregate => |aggregate| switch (aggregate.storage) {
3525 .elems => |elem_vals| {
3526 const elem_ty = tv.ty.childType(mod);
3527 const gpa = dg.gpa;
3528 const llvm_elems = try gpa.alloc(*llvm.Value, elem_vals.len);
3529 defer gpa.free(llvm_elems);
3530 var need_unnamed = false;
3531 for (elem_vals, 0..) |elem_val, i| {
3532 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() });
3533 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3534 }
3535 if (need_unnamed) {
3536 return dg.context.constStruct(
3537 llvm_elems.ptr,
3538 @intCast(c_uint, llvm_elems.len),
3539 .True,
3540 );
3541 } else {
3542 const llvm_elem_ty = try dg.lowerType(elem_ty);
3543 return llvm_elem_ty.constArray(
3544 llvm_elems.ptr,
3545 @intCast(c_uint, llvm_elems.len),
3546 );
3547 }
3548 },
3549 .repeated_elem => |val| {
3550 const elem_ty = tv.ty.childType(mod);
3551 const sentinel = tv.ty.sentinel(mod);
3552 const len = @intCast(usize, tv.ty.arrayLen(mod));
3553 const len_including_sent = len + @boolToInt(sentinel != null);
3554 const gpa = dg.gpa;
3555 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3556 defer gpa.free(llvm_elems);
3322 };
35573323
3558 var need_unnamed = false;
3559 if (len != 0) {
3560 for (llvm_elems[0..len]) |*elem| {
3561 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() });
3562 }
3563 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3564 }
3324 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
35653325
3566 if (sentinel) |sent| {
3567 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3568 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3569 }
3326 if (struct_obj.layout == .Packed) {
3327 assert(struct_obj.haveLayout());
3328 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3329 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3330 const fields = struct_obj.fields.values();
3331 comptime assert(Type.packed_struct_layout_version == 2);
3332 var running_int: *llvm.Value = int_llvm_ty.constNull();
3333 var running_bits: u16 = 0;
3334 for (fields, 0..) |field, i| {
3335 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
35703336
3571 if (need_unnamed) {
3572 return dg.context.constStruct(
3573 llvm_elems.ptr,
3574 @intCast(c_uint, llvm_elems.len),
3575 .True,
3576 );
3577 } else {
3578 const llvm_elem_ty = try dg.lowerType(elem_ty);
3579 return llvm_elem_ty.constArray(
3580 llvm_elems.ptr,
3581 @intCast(c_uint, llvm_elems.len),
3582 );
3583 }
3584 },
3585 },
3586 else => unreachable,
3587 },
3588 },
3589 .Optional => {
3590 comptime assert(optional_layout_version == 3);
3591 const payload_ty = tv.ty.optionalChild(mod);
3337 const non_int_val = try dg.lowerValue(.{
3338 .ty = field.ty,
3339 .val = try tv.val.fieldValue(mod, i),
3340 });
3341 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3342 const small_int_ty = dg.context.intType(ty_bit_size);
3343 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
3344 non_int_val.constPtrToInt(small_int_ty)
3345 else
3346 non_int_val.constBitCast(small_int_ty);
3347 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3348 // If the field is as large as the entire packed struct, this
3349 // zext would go from, e.g. i16 to i16. This is legal with
3350 // constZExtOrBitCast but not legal with constZExt.
3351 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3352 const shifted = extended_int_val.constShl(shift_rhs);
3353 running_int = running_int.constOr(shifted);
3354 running_bits += ty_bit_size;
3355 }
3356 return running_int;
3357 }
35923358
3593 const llvm_i8 = dg.context.intType(8);
3594 const is_pl = !tv.val.isNull(mod);
3595 const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull();
3596 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3597 return non_null_bit;
3359 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3360 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3361 defer llvm_fields.deinit(gpa);
3362
3363 comptime assert(struct_layout_version == 2);
3364 var offset: u64 = 0;
3365 var big_align: u32 = 0;
3366 var need_unnamed = false;
3367
3368 var it = struct_obj.runtimeFieldIterator(mod);
3369 while (it.next()) |field_and_index| {
3370 const field = field_and_index.field;
3371 const field_align = field.alignment(mod, struct_obj.layout);
3372 big_align = @max(big_align, field_align);
3373 const prev_offset = offset;
3374 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3375
3376 const padding_len = offset - prev_offset;
3377 if (padding_len > 0) {
3378 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3379 // TODO make this and all other padding elsewhere in debug
3380 // builds be 0xaa not undef.
3381 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3382 }
3383
3384 const field_llvm_val = try dg.lowerValue(.{
3385 .ty = field.ty,
3386 .val = try tv.val.fieldValue(mod, field_and_index.index),
3387 });
3388
3389 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
3390
3391 llvm_fields.appendAssumeCapacity(field_llvm_val);
3392
3393 offset += field.ty.abiSize(mod);
3394 }
3395 {
3396 const prev_offset = offset;
3397 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3398 const padding_len = offset - prev_offset;
3399 if (padding_len > 0) {
3400 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3401 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3402 }
35983403 }
3599 const llvm_ty = try dg.lowerType(tv.ty);
3600 if (tv.ty.optionalReprIsPayload(mod)) return switch (tv.val.ip_index) {
3601 .none => if (tv.val.castTag(.opt_payload)) |payload|
3602 try dg.lowerValue(.{ .ty = payload_ty, .val = payload.data })
3603 else if (is_pl)
3604 try dg.lowerValue(.{ .ty = payload_ty, .val = tv.val })
3605 else
3606 llvm_ty.constNull(),
3607 .null_value => llvm_ty.constNull(),
3608 else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3609 .opt => |opt| switch (opt.val) {
3610 .none => llvm_ty.constNull(),
3611 else => dg.lowerValue(.{ .ty = payload_ty, .val = opt.val.toValue() }),
3612 },
3613 else => unreachable,
3614 },
3615 };
3616 assert(payload_ty.zigTypeTag(mod) != .Fn);
36173404
3618 const llvm_field_count = llvm_ty.countStructElementTypes();
3619 var fields_buf: [3]*llvm.Value = undefined;
3620 fields_buf[0] = try dg.lowerValue(.{
3621 .ty = payload_ty,
3622 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.undef,
3623 });
3624 fields_buf[1] = non_null_bit;
3625 if (llvm_field_count > 2) {
3626 assert(llvm_field_count == 3);
3627 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3405 if (need_unnamed) {
3406 return dg.context.constStruct(
3407 llvm_fields.items.ptr,
3408 @intCast(c_uint, llvm_fields.items.len),
3409 .False,
3410 );
3411 } else {
3412 return llvm_struct_ty.constNamedStruct(
3413 llvm_fields.items.ptr,
3414 @intCast(c_uint, llvm_fields.items.len),
3415 );
36283416 }
3629 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
36303417 },
3631 .Fn => {
3632 const fn_decl_index = switch (tv.val.tag()) {
3633 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
3634 .function => tv.val.castTag(.function).?.data.owner_decl,
3635 else => unreachable,
3636 };
3637 const fn_decl = dg.module.declPtr(fn_decl_index);
3638 dg.module.markDeclAlive(fn_decl);
3639 return dg.resolveLlvmFunction(fn_decl_index);
3418 .Vector => switch (tv.val.tag()) {
3419 .bytes => {
3420 // Note, sentinel is not stored even if the type has a sentinel.
3421 const bytes = tv.val.castTag(.bytes).?.data;
3422 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
3423 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
3424
3425 const elem_ty = tv.ty.childType(mod);
3426 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3427 defer dg.gpa.free(llvm_elems);
3428 for (llvm_elems, 0..) |*elem, i| {
3429 elem.* = try dg.lowerValue(.{
3430 .ty = elem_ty,
3431 .val = try mod.intValue(elem_ty, bytes[i]),
3432 });
3433 }
3434 return llvm.constVector(
3435 llvm_elems.ptr,
3436 @intCast(c_uint, llvm_elems.len),
3437 );
3438 },
3439 .str_lit => {
3440 // Note, sentinel is not stored
3441 const str_lit = tv.val.castTag(.str_lit).?.data;
3442 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3443 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
3444 assert(vector_len == bytes.len);
3445
3446 const elem_ty = tv.ty.childType(mod);
3447 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3448 defer dg.gpa.free(llvm_elems);
3449 for (llvm_elems, 0..) |*elem, i| {
3450 elem.* = try dg.lowerValue(.{
3451 .ty = elem_ty,
3452 .val = try mod.intValue(elem_ty, bytes[i]),
3453 });
3454 }
3455 return llvm.constVector(
3456 llvm_elems.ptr,
3457 @intCast(c_uint, llvm_elems.len),
3458 );
3459 },
3460 else => unreachable,
36403461 },
3641 .ErrorSet => {
3462 .Float,
3463 .Union,
3464 .Optional,
3465 .ErrorUnion,
3466 .ErrorSet,
3467 .Int,
3468 .Enum,
3469 .Bool,
3470 .Pointer,
3471 => unreachable, // handled below
3472 .Frame,
3473 .AnyFrame,
3474 => return dg.todo("implement const of type '{}'", .{tv.ty.fmtDebug()}),
3475 .Type,
3476 .Void,
3477 .NoReturn,
3478 .ComptimeFloat,
3479 .ComptimeInt,
3480 .Undefined,
3481 .Null,
3482 .Opaque,
3483 .EnumLiteral,
3484 .Fn,
3485 => unreachable, // comptime-only types
3486 };
3487
3488 switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3489 .int_type,
3490 .ptr_type,
3491 .array_type,
3492 .vector_type,
3493 .opt_type,
3494 .anyframe_type,
3495 .error_union_type,
3496 .simple_type,
3497 .struct_type,
3498 .anon_struct_type,
3499 .union_type,
3500 .opaque_type,
3501 .enum_type,
3502 .func_type,
3503 .error_set_type,
3504 .inferred_error_set_type,
3505 => unreachable, // types, not values
3506
3507 .undef, .runtime_value => unreachable, // handled above
3508 .simple_value => |simple_value| switch (simple_value) {
3509 .undefined,
3510 .void,
3511 .null,
3512 .empty_struct,
3513 .@"unreachable",
3514 .generic_poison,
3515 => unreachable, // non-runtime values
3516 .false, .true => {
3517 const llvm_type = try dg.lowerType(tv.ty);
3518 return if (tv.val.toBool(mod)) llvm_type.constAllOnes() else llvm_type.constNull();
3519 },
3520 },
3521 .variable,
3522 .extern_func,
3523 .func,
3524 .enum_literal,
3525 => unreachable, // non-runtime values
3526 .int => |int| {
3527 var bigint_space: Value.BigIntSpace = undefined;
3528 const bigint = int.storage.toBigInt(&bigint_space);
3529 return lowerBigInt(dg, tv.ty, bigint);
3530 },
3531 .err => |err| {
36423532 const llvm_ty = try dg.lowerType(Type.anyerror);
3643 switch (tv.val.ip_index) {
3644 .none => switch (tv.val.tag()) {
3645 .@"error" => {
3646 const err_name = tv.val.castTag(.@"error").?.data.name;
3647 const kv = try dg.module.getErrorValue(err_name);
3648 return llvm_ty.constInt(kv.value, .False);
3649 },
3650 else => {
3651 // In this case we are rendering an error union which has a 0 bits payload.
3652 return llvm_ty.constNull();
3653 },
3654 },
3655 else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
3656 .int => |int| return llvm_ty.constInt(int.storage.u64, .False),
3657 else => unreachable,
3658 },
3659 }
3533 const name = mod.intern_pool.stringToSlice(err.name);
3534 const kv = try mod.getErrorValue(name);
3535 return llvm_ty.constInt(kv.value, .False);
36603536 },
3661 .ErrorUnion => {
3537 .error_union => |error_union| {
36623538 const payload_type = tv.ty.errorUnionPayload(mod);
3663 const is_pl = tv.val.errorUnionIsPayload();
3539 const is_pl = tv.val.errorUnionIsPayload(mod);
36643540
36653541 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
36663542 // We use the error type directly as the type.
......@@ -3676,7 +3552,10 @@ pub const DeclGen = struct {
36763552 });
36773553 const llvm_payload_value = try dg.lowerValue(.{
36783554 .ty = payload_type,
3679 .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.undef,
3555 .val = switch (error_union.val) {
3556 .err_name => try mod.intern(.{ .undef = payload_type.ip_index }),
3557 .payload => |payload| payload,
3558 }.toValue(),
36803559 });
36813560 var fields_buf: [3]*llvm.Value = undefined;
36823561
......@@ -3697,172 +3576,396 @@ pub const DeclGen = struct {
36973576 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
36983577 }
36993578 },
3700 .Struct => {
3701 const llvm_struct_ty = try dg.lowerType(tv.ty);
3702 const gpa = dg.gpa;
3579 .enum_tag => {
3580 const int_val = try tv.enumToInt(mod);
37033581
3704 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3705 .anon_struct_type => |tuple| {
3706 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3707 defer llvm_fields.deinit(gpa);
3582 var bigint_space: Value.BigIntSpace = undefined;
3583 const bigint = int_val.toBigInt(&bigint_space, mod);
37083584
3709 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
3585 const int_info = tv.ty.intInfo(mod);
3586 const llvm_type = dg.context.intType(int_info.bits);
37103587
3711 comptime assert(struct_layout_version == 2);
3712 var offset: u64 = 0;
3713 var big_align: u32 = 0;
3714 var need_unnamed = false;
3588 const unsigned_val = v: {
3589 if (bigint.limbs.len == 1) {
3590 break :v llvm_type.constInt(bigint.limbs[0], .False);
3591 }
3592 if (@sizeOf(usize) == @sizeOf(u64)) {
3593 break :v llvm_type.constIntOfArbitraryPrecision(
3594 @intCast(c_uint, bigint.limbs.len),
3595 bigint.limbs.ptr,
3596 );
3597 }
3598 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
3599 };
3600 if (!bigint.positive) {
3601 return llvm.constNeg(unsigned_val);
3602 }
3603 return unsigned_val;
3604 },
3605 .float => {
3606 const llvm_ty = try dg.lowerType(tv.ty);
3607 switch (tv.ty.floatBits(target)) {
3608 16 => {
3609 const repr = @bitCast(u16, tv.val.toFloat(f16, mod));
3610 const llvm_i16 = dg.context.intType(16);
3611 const int = llvm_i16.constInt(repr, .False);
3612 return int.constBitCast(llvm_ty);
3613 },
3614 32 => {
3615 const repr = @bitCast(u32, tv.val.toFloat(f32, mod));
3616 const llvm_i32 = dg.context.intType(32);
3617 const int = llvm_i32.constInt(repr, .False);
3618 return int.constBitCast(llvm_ty);
3619 },
3620 64 => {
3621 const repr = @bitCast(u64, tv.val.toFloat(f64, mod));
3622 const llvm_i64 = dg.context.intType(64);
3623 const int = llvm_i64.constInt(repr, .False);
3624 return int.constBitCast(llvm_ty);
3625 },
3626 80 => {
3627 const float = tv.val.toFloat(f80, mod);
3628 const repr = std.math.break_f80(float);
3629 const llvm_i80 = dg.context.intType(80);
3630 var x = llvm_i80.constInt(repr.exp, .False);
3631 x = x.constShl(llvm_i80.constInt(64, .False));
3632 x = x.constOr(llvm_i80.constInt(repr.fraction, .False));
3633 if (backendSupportsF80(target)) {
3634 return x.constBitCast(llvm_ty);
3635 } else {
3636 return x;
3637 }
3638 },
3639 128 => {
3640 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128, mod));
3641 // LLVM seems to require that the lower half of the f128 be placed first
3642 // in the buffer.
3643 if (native_endian == .Big) {
3644 std.mem.swap(u64, &buf[0], &buf[1]);
3645 }
3646 const int = dg.context.intType(128).constIntOfArbitraryPrecision(buf.len, &buf);
3647 return int.constBitCast(llvm_ty);
3648 },
3649 else => unreachable,
3650 }
3651 },
3652 .ptr => |ptr| {
3653 const ptr_tv: TypedValue = switch (ptr.len) {
3654 .none => tv,
3655 else => .{ .ty = tv.ty.slicePtrFieldType(mod), .val = tv.val.slicePtr(mod) },
3656 };
3657 const llvm_ptr_val = switch (ptr.addr) {
3658 .decl => |decl| try dg.lowerDeclRefValue(ptr_tv, decl),
3659 .mut_decl => |mut_decl| try dg.lowerDeclRefValue(ptr_tv, mut_decl.decl),
3660 .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int),
3661 .eu_payload,
3662 .opt_payload,
3663 .elem,
3664 .field,
3665 => try dg.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).bit_offset % 8 == 0),
3666 .comptime_field => unreachable,
3667 };
3668 switch (ptr.len) {
3669 .none => return llvm_ptr_val,
3670 else => {
3671 const fields: [2]*llvm.Value = .{
3672 llvm_ptr_val,
3673 try dg.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }),
3674 };
3675 return dg.context.constStruct(&fields, fields.len, .False);
3676 },
3677 }
3678 },
3679 .opt => |opt| {
3680 comptime assert(optional_layout_version == 3);
3681 const payload_ty = tv.ty.optionalChild(mod);
37153682
3716 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3717 if (field_val != .none) continue;
3718 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
3683 const llvm_i8 = dg.context.intType(8);
3684 const non_null_bit = switch (opt.val) {
3685 .none => llvm_i8.constNull(),
3686 else => llvm_i8.constInt(1, .False),
3687 };
3688 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3689 return non_null_bit;
3690 }
3691 const llvm_ty = try dg.lowerType(tv.ty);
3692 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
3693 .none => llvm_ty.constNull(),
3694 else => dg.lowerValue(.{ .ty = payload_ty, .val = opt.val.toValue() }),
3695 };
3696 assert(payload_ty.zigTypeTag(mod) != .Fn);
37193697
3720 const field_align = field_ty.toType().abiAlignment(mod);
3721 big_align = @max(big_align, field_align);
3722 const prev_offset = offset;
3723 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3698 const llvm_field_count = llvm_ty.countStructElementTypes();
3699 var fields_buf: [3]*llvm.Value = undefined;
3700 fields_buf[0] = try dg.lowerValue(.{
3701 .ty = payload_ty,
3702 .val = switch (opt.val) {
3703 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
3704 else => |payload| payload,
3705 }.toValue(),
3706 });
3707 fields_buf[1] = non_null_bit;
3708 if (llvm_field_count > 2) {
3709 assert(llvm_field_count == 3);
3710 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3711 }
3712 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3713 },
3714 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3715 .array_type => switch (aggregate.storage) {
3716 .bytes => |bytes| return dg.context.constString(
3717 bytes.ptr,
3718 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3719 .True, // Don't null terminate. Bytes has the sentinel, if any.
3720 ),
3721 .elems => |elem_vals| {
3722 const elem_ty = tv.ty.childType(mod);
3723 const gpa = dg.gpa;
3724 const llvm_elems = try gpa.alloc(*llvm.Value, elem_vals.len);
3725 defer gpa.free(llvm_elems);
3726 var need_unnamed = false;
3727 for (elem_vals, 0..) |elem_val, i| {
3728 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() });
3729 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3730 }
3731 if (need_unnamed) {
3732 return dg.context.constStruct(
3733 llvm_elems.ptr,
3734 @intCast(c_uint, llvm_elems.len),
3735 .True,
3736 );
3737 } else {
3738 const llvm_elem_ty = try dg.lowerType(elem_ty);
3739 return llvm_elem_ty.constArray(
3740 llvm_elems.ptr,
3741 @intCast(c_uint, llvm_elems.len),
3742 );
3743 }
3744 },
3745 .repeated_elem => |val| {
3746 const elem_ty = tv.ty.childType(mod);
3747 const sentinel = tv.ty.sentinel(mod);
3748 const len = @intCast(usize, tv.ty.arrayLen(mod));
3749 const len_including_sent = len + @boolToInt(sentinel != null);
3750 const gpa = dg.gpa;
3751 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3752 defer gpa.free(llvm_elems);
37243753
3725 const padding_len = offset - prev_offset;
3726 if (padding_len > 0) {
3727 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3728 // TODO make this and all other padding elsewhere in debug
3729 // builds be 0xaa not undef.
3730 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3754 var need_unnamed = false;
3755 if (len != 0) {
3756 for (llvm_elems[0..len]) |*elem| {
3757 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() });
37313758 }
3759 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3760 }
37323761
3733 const field_llvm_val = try dg.lowerValue(.{
3734 .ty = field_ty.toType(),
3735 .val = try tv.val.fieldValue(field_ty.toType(), mod, i),
3736 });
3762 if (sentinel) |sent| {
3763 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3764 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3765 }
37373766
3738 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
3767 if (need_unnamed) {
3768 return dg.context.constStruct(
3769 llvm_elems.ptr,
3770 @intCast(c_uint, llvm_elems.len),
3771 .True,
3772 );
3773 } else {
3774 const llvm_elem_ty = try dg.lowerType(elem_ty);
3775 return llvm_elem_ty.constArray(
3776 llvm_elems.ptr,
3777 @intCast(c_uint, llvm_elems.len),
3778 );
3779 }
3780 },
3781 },
3782 .vector_type => |vector_type| {
3783 const elem_ty = vector_type.child.toType();
3784 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len);
3785 defer dg.gpa.free(llvm_elems);
3786 for (llvm_elems, 0..) |*llvm_elem, i| {
3787 llvm_elem.* = try dg.lowerValue(.{
3788 .ty = elem_ty,
3789 .val = switch (aggregate.storage) {
3790 .bytes => unreachable,
3791 .elems => |elems| elems[i],
3792 .repeated_elem => |elem| elem,
3793 }.toValue(),
3794 });
3795 }
3796 return llvm.constVector(
3797 llvm_elems.ptr,
3798 @intCast(c_uint, llvm_elems.len),
3799 );
3800 },
3801 .struct_type, .anon_struct_type => {
3802 const llvm_struct_ty = try dg.lowerType(tv.ty);
3803 const gpa = dg.gpa;
37393804
3740 llvm_fields.appendAssumeCapacity(field_llvm_val);
3805 const struct_type = switch (mod.intern_pool.indexToKey(tv.ty.ip_index)) {
3806 .anon_struct_type => |tuple| {
3807 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
3808 defer llvm_fields.deinit(gpa);
37413809
3742 offset += field_ty.toType().abiSize(mod);
3743 }
3744 {
3745 const prev_offset = offset;
3746 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3747 const padding_len = offset - prev_offset;
3748 if (padding_len > 0) {
3749 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3750 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3751 }
3752 }
3810 try llvm_fields.ensureUnusedCapacity(gpa, tuple.types.len);
3811
3812 comptime assert(struct_layout_version == 2);
3813 var offset: u64 = 0;
3814 var big_align: u32 = 0;
3815 var need_unnamed = false;
37533816
3754 if (need_unnamed) {
3755 return dg.context.constStruct(
3756 llvm_fields.items.ptr,
3757 @intCast(c_uint, llvm_fields.items.len),
3758 .False,
3759 );
3760 } else {
3761 return llvm_struct_ty.constNamedStruct(
3762 llvm_fields.items.ptr,
3763 @intCast(c_uint, llvm_fields.items.len),
3764 );
3765 }
3766 },
3767 .struct_type => |struct_type| struct_type,
3768 else => unreachable,
3769 };
3817 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3818 if (field_val != .none) continue;
3819 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
3820
3821 const field_align = field_ty.toType().abiAlignment(mod);
3822 big_align = @max(big_align, field_align);
3823 const prev_offset = offset;
3824 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3825
3826 const padding_len = offset - prev_offset;
3827 if (padding_len > 0) {
3828 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3829 // TODO make this and all other padding elsewhere in debug
3830 // builds be 0xaa not undef.
3831 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3832 }
37703833
3771 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3834 const field_llvm_val = try dg.lowerValue(.{
3835 .ty = field_ty.toType(),
3836 .val = try tv.val.fieldValue(mod, i),
3837 });
37723838
3773 if (struct_obj.layout == .Packed) {
3774 assert(struct_obj.haveLayout());
3775 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3776 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3777 const fields = struct_obj.fields.values();
3778 comptime assert(Type.packed_struct_layout_version == 2);
3779 var running_int: *llvm.Value = int_llvm_ty.constNull();
3780 var running_bits: u16 = 0;
3781 for (fields, 0..) |field, i| {
3782 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3839 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
37833840
3784 const non_int_val = try dg.lowerValue(.{
3785 .ty = field.ty,
3786 .val = try tv.val.fieldValue(field.ty, mod, i),
3787 });
3788 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3789 const small_int_ty = dg.context.intType(ty_bit_size);
3790 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
3791 non_int_val.constPtrToInt(small_int_ty)
3792 else
3793 non_int_val.constBitCast(small_int_ty);
3794 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3795 // If the field is as large as the entire packed struct, this
3796 // zext would go from, e.g. i16 to i16. This is legal with
3797 // constZExtOrBitCast but not legal with constZExt.
3798 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3799 const shifted = extended_int_val.constShl(shift_rhs);
3800 running_int = running_int.constOr(shifted);
3801 running_bits += ty_bit_size;
3802 }
3803 return running_int;
3804 }
3841 llvm_fields.appendAssumeCapacity(field_llvm_val);
38053842
3806 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3807 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3808 defer llvm_fields.deinit(gpa);
3843 offset += field_ty.toType().abiSize(mod);
3844 }
3845 {
3846 const prev_offset = offset;
3847 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3848 const padding_len = offset - prev_offset;
3849 if (padding_len > 0) {
3850 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3851 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3852 }
3853 }
38093854
3810 comptime assert(struct_layout_version == 2);
3811 var offset: u64 = 0;
3812 var big_align: u32 = 0;
3813 var need_unnamed = false;
3855 if (need_unnamed) {
3856 return dg.context.constStruct(
3857 llvm_fields.items.ptr,
3858 @intCast(c_uint, llvm_fields.items.len),
3859 .False,
3860 );
3861 } else {
3862 return llvm_struct_ty.constNamedStruct(
3863 llvm_fields.items.ptr,
3864 @intCast(c_uint, llvm_fields.items.len),
3865 );
3866 }
3867 },
3868 .struct_type => |struct_type| struct_type,
3869 else => unreachable,
3870 };
38143871
3815 var it = struct_obj.runtimeFieldIterator(mod);
3816 while (it.next()) |field_and_index| {
3817 const field = field_and_index.field;
3818 const field_align = field.alignment(mod, struct_obj.layout);
3819 big_align = @max(big_align, field_align);
3820 const prev_offset = offset;
3821 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3872 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
38223873
3823 const padding_len = offset - prev_offset;
3824 if (padding_len > 0) {
3825 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3826 // TODO make this and all other padding elsewhere in debug
3827 // builds be 0xaa not undef.
3828 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3874 if (struct_obj.layout == .Packed) {
3875 assert(struct_obj.haveLayout());
3876 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3877 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3878 const fields = struct_obj.fields.values();
3879 comptime assert(Type.packed_struct_layout_version == 2);
3880 var running_int: *llvm.Value = int_llvm_ty.constNull();
3881 var running_bits: u16 = 0;
3882 for (fields, 0..) |field, i| {
3883 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3884
3885 const non_int_val = try dg.lowerValue(.{
3886 .ty = field.ty,
3887 .val = try tv.val.fieldValue(mod, i),
3888 });
3889 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3890 const small_int_ty = dg.context.intType(ty_bit_size);
3891 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
3892 non_int_val.constPtrToInt(small_int_ty)
3893 else
3894 non_int_val.constBitCast(small_int_ty);
3895 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3896 // If the field is as large as the entire packed struct, this
3897 // zext would go from, e.g. i16 to i16. This is legal with
3898 // constZExtOrBitCast but not legal with constZExt.
3899 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3900 const shifted = extended_int_val.constShl(shift_rhs);
3901 running_int = running_int.constOr(shifted);
3902 running_bits += ty_bit_size;
3903 }
3904 return running_int;
38293905 }
38303906
3831 const field_llvm_val = try dg.lowerValue(.{
3832 .ty = field.ty,
3833 .val = try tv.val.fieldValue(field.ty, mod, field_and_index.index),
3834 });
3907 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3908 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3909 defer llvm_fields.deinit(gpa);
38353910
3836 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
3911 comptime assert(struct_layout_version == 2);
3912 var offset: u64 = 0;
3913 var big_align: u32 = 0;
3914 var need_unnamed = false;
3915
3916 var it = struct_obj.runtimeFieldIterator(mod);
3917 while (it.next()) |field_and_index| {
3918 const field = field_and_index.field;
3919 const field_align = field.alignment(mod, struct_obj.layout);
3920 big_align = @max(big_align, field_align);
3921 const prev_offset = offset;
3922 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3923
3924 const padding_len = offset - prev_offset;
3925 if (padding_len > 0) {
3926 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3927 // TODO make this and all other padding elsewhere in debug
3928 // builds be 0xaa not undef.
3929 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3930 }
38373931
3838 llvm_fields.appendAssumeCapacity(field_llvm_val);
3932 const field_llvm_val = try dg.lowerValue(.{
3933 .ty = field.ty,
3934 .val = try tv.val.fieldValue(mod, field_and_index.index),
3935 });
38393936
3840 offset += field.ty.abiSize(mod);
3841 }
3842 {
3843 const prev_offset = offset;
3844 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3845 const padding_len = offset - prev_offset;
3846 if (padding_len > 0) {
3847 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3848 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3937 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
3938
3939 llvm_fields.appendAssumeCapacity(field_llvm_val);
3940
3941 offset += field.ty.abiSize(mod);
3942 }
3943 {
3944 const prev_offset = offset;
3945 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3946 const padding_len = offset - prev_offset;
3947 if (padding_len > 0) {
3948 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3949 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3950 }
38493951 }
3850 }
38513952
3852 if (need_unnamed) {
3853 return dg.context.constStruct(
3854 llvm_fields.items.ptr,
3855 @intCast(c_uint, llvm_fields.items.len),
3856 .False,
3857 );
3858 } else {
3859 return llvm_struct_ty.constNamedStruct(
3860 llvm_fields.items.ptr,
3861 @intCast(c_uint, llvm_fields.items.len),
3862 );
3863 }
3953 if (need_unnamed) {
3954 return dg.context.constStruct(
3955 llvm_fields.items.ptr,
3956 @intCast(c_uint, llvm_fields.items.len),
3957 .False,
3958 );
3959 } else {
3960 return llvm_struct_ty.constNamedStruct(
3961 llvm_fields.items.ptr,
3962 @intCast(c_uint, llvm_fields.items.len),
3963 );
3964 }
3965 },
3966 else => unreachable,
38643967 },
3865 .Union => {
3968 .un => {
38663969 const llvm_union_ty = try dg.lowerType(tv.ty);
38673970 const tag_and_val: Value.Payload.Union.Data = switch (tv.val.ip_index) {
38683971 .none => tv.val.castTag(.@"union").?.data,
......@@ -3950,96 +4053,6 @@ pub const DeclGen = struct {
39504053 return llvm_union_ty.constNamedStruct(&fields, fields_len);
39514054 }
39524055 },
3953 .Vector => switch (tv.val.tag()) {
3954 .bytes => {
3955 // Note, sentinel is not stored even if the type has a sentinel.
3956 const bytes = tv.val.castTag(.bytes).?.data;
3957 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
3958 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
3959
3960 const elem_ty = tv.ty.childType(mod);
3961 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3962 defer dg.gpa.free(llvm_elems);
3963 for (llvm_elems, 0..) |*elem, i| {
3964 elem.* = try dg.lowerValue(.{
3965 .ty = elem_ty,
3966 .val = try mod.intValue(elem_ty, bytes[i]),
3967 });
3968 }
3969 return llvm.constVector(
3970 llvm_elems.ptr,
3971 @intCast(c_uint, llvm_elems.len),
3972 );
3973 },
3974 .aggregate => {
3975 // Note, sentinel is not stored even if the type has a sentinel.
3976 // The value includes the sentinel in those cases.
3977 const elem_vals = tv.val.castTag(.aggregate).?.data;
3978 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
3979 assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len);
3980 const elem_ty = tv.ty.childType(mod);
3981 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3982 defer dg.gpa.free(llvm_elems);
3983 for (llvm_elems, 0..) |*elem, i| {
3984 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_vals[i] });
3985 }
3986 return llvm.constVector(
3987 llvm_elems.ptr,
3988 @intCast(c_uint, llvm_elems.len),
3989 );
3990 },
3991 .repeated => {
3992 // Note, sentinel is not stored even if the type has a sentinel.
3993 const val = tv.val.castTag(.repeated).?.data;
3994 const elem_ty = tv.ty.childType(mod);
3995 const len = @intCast(usize, tv.ty.arrayLen(mod));
3996 const llvm_elems = try dg.gpa.alloc(*llvm.Value, len);
3997 defer dg.gpa.free(llvm_elems);
3998 for (llvm_elems) |*elem| {
3999 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val });
4000 }
4001 return llvm.constVector(
4002 llvm_elems.ptr,
4003 @intCast(c_uint, llvm_elems.len),
4004 );
4005 },
4006 .str_lit => {
4007 // Note, sentinel is not stored
4008 const str_lit = tv.val.castTag(.str_lit).?.data;
4009 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
4010 const vector_len = @intCast(usize, tv.ty.arrayLen(mod));
4011 assert(vector_len == bytes.len);
4012
4013 const elem_ty = tv.ty.childType(mod);
4014 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
4015 defer dg.gpa.free(llvm_elems);
4016 for (llvm_elems, 0..) |*elem, i| {
4017 elem.* = try dg.lowerValue(.{
4018 .ty = elem_ty,
4019 .val = try mod.intValue(elem_ty, bytes[i]),
4020 });
4021 }
4022 return llvm.constVector(
4023 llvm_elems.ptr,
4024 @intCast(c_uint, llvm_elems.len),
4025 );
4026 },
4027 else => unreachable,
4028 },
4029
4030 .ComptimeInt => unreachable,
4031 .ComptimeFloat => unreachable,
4032 .Type => unreachable,
4033 .EnumLiteral => unreachable,
4034 .Void => unreachable,
4035 .NoReturn => unreachable,
4036 .Undefined => unreachable,
4037 .Null => unreachable,
4038 .Opaque => unreachable,
4039
4040 .Frame,
4041 .AnyFrame,
4042 => return dg.todo("implement const of type '{}'", .{tv.ty.fmtDebug()}),
40434056 }
40444057 }
40454058
......@@ -4094,10 +4107,9 @@ pub const DeclGen = struct {
40944107 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {
40954108 const mod = dg.module;
40964109 const target = mod.getTarget();
4097 if (ptr_val.ip_index != .none) return switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
4110 return switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) {
40984111 .int => |int| dg.lowerIntAsPtr(int),
40994112 .ptr => |ptr| switch (ptr.addr) {
4100 .@"var" => |@"var"| dg.lowerParentPtrDecl(ptr_val, @"var".owner_decl),
41014113 .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl),
41024114 .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl),
41034115 .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int),
......@@ -4150,7 +4162,7 @@ pub const DeclGen = struct {
41504162 const indices: [1]*llvm.Value = .{
41514163 llvm_usize.constInt(elem_ptr.index, .False),
41524164 };
4153 const elem_llvm_ty = try dg.lowerType(ptr.ty.toType().childType(mod));
4165 const elem_llvm_ty = try dg.lowerType(ptr.ty.toType().elemType2(mod));
41544166 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
41554167 },
41564168 .field => |field_ptr| {
......@@ -4185,7 +4197,7 @@ pub const DeclGen = struct {
41854197 .Struct => {
41864198 if (parent_ty.containerLayout(mod) == .Packed) {
41874199 if (!byte_aligned) return parent_llvm_ptr;
4188 const llvm_usize = dg.context.intType(target.cpu.arch.ptrBitWidth());
4200 const llvm_usize = dg.context.intType(target.ptrBitWidth());
41894201 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
41904202 // count bits of fields before this one
41914203 const prev_bits = b: {
......@@ -4230,148 +4242,6 @@ pub const DeclGen = struct {
42304242 },
42314243 else => unreachable,
42324244 };
4233 switch (ptr_val.tag()) {
4234 .decl_ref_mut => {
4235 const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;
4236 return dg.lowerParentPtrDecl(ptr_val, decl);
4237 },
4238 .decl_ref => {
4239 const decl = ptr_val.castTag(.decl_ref).?.data;
4240 return dg.lowerParentPtrDecl(ptr_val, decl);
4241 },
4242 .variable => {
4243 const decl = ptr_val.castTag(.variable).?.data.owner_decl;
4244 return dg.lowerParentPtrDecl(ptr_val, decl);
4245 },
4246 .field_ptr => {
4247 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
4248 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, byte_aligned);
4249 const parent_ty = field_ptr.container_ty;
4250
4251 const field_index = @intCast(u32, field_ptr.field_index);
4252 const llvm_u32 = dg.context.intType(32);
4253 switch (parent_ty.zigTypeTag(mod)) {
4254 .Union => {
4255 if (parent_ty.containerLayout(mod) == .Packed) {
4256 return parent_llvm_ptr;
4257 }
4258
4259 const layout = parent_ty.unionGetLayout(mod);
4260 if (layout.payload_size == 0) {
4261 // In this case a pointer to the union and a pointer to any
4262 // (void) payload is the same.
4263 return parent_llvm_ptr;
4264 }
4265 const llvm_pl_index = if (layout.tag_size == 0)
4266 0
4267 else
4268 @boolToInt(layout.tag_align >= layout.payload_align);
4269 const indices: [2]*llvm.Value = .{
4270 llvm_u32.constInt(0, .False),
4271 llvm_u32.constInt(llvm_pl_index, .False),
4272 };
4273 const parent_llvm_ty = try dg.lowerType(parent_ty);
4274 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4275 },
4276 .Struct => {
4277 if (parent_ty.containerLayout(mod) == .Packed) {
4278 if (!byte_aligned) return parent_llvm_ptr;
4279 const llvm_usize = dg.context.intType(target.ptrBitWidth());
4280 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
4281 // count bits of fields before this one
4282 const prev_bits = b: {
4283 var b: usize = 0;
4284 for (parent_ty.structFields(mod).values()[0..field_index]) |field| {
4285 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
4286 b += @intCast(usize, field.ty.bitSize(mod));
4287 }
4288 break :b b;
4289 };
4290 const byte_offset = llvm_usize.constInt(prev_bits / 8, .False);
4291 const field_addr = base_addr.constAdd(byte_offset);
4292 const final_llvm_ty = dg.context.pointerType(0);
4293 return field_addr.constIntToPtr(final_llvm_ty);
4294 }
4295
4296 const parent_llvm_ty = try dg.lowerType(parent_ty);
4297 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
4298 const indices: [2]*llvm.Value = .{
4299 llvm_u32.constInt(0, .False),
4300 llvm_u32.constInt(llvm_field.index, .False),
4301 };
4302 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4303 } else {
4304 const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False);
4305 const indices: [1]*llvm.Value = .{llvm_index};
4306 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4307 }
4308 },
4309 .Pointer => {
4310 assert(parent_ty.isSlice(mod));
4311 const indices: [2]*llvm.Value = .{
4312 llvm_u32.constInt(0, .False),
4313 llvm_u32.constInt(field_index, .False),
4314 };
4315 const parent_llvm_ty = try dg.lowerType(parent_ty);
4316 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4317 },
4318 else => unreachable,
4319 }
4320 },
4321 .elem_ptr => {
4322 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
4323 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, true);
4324
4325 const llvm_usize = try dg.lowerType(Type.usize);
4326 const indices: [1]*llvm.Value = .{
4327 llvm_usize.constInt(elem_ptr.index, .False),
4328 };
4329 const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty);
4330 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4331 },
4332 .opt_payload_ptr => {
4333 const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
4334 const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, true);
4335
4336 const payload_ty = opt_payload_ptr.container_ty.optionalChild(mod);
4337 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or
4338 payload_ty.optionalReprIsPayload(mod))
4339 {
4340 // In this case, we represent pointer to optional the same as pointer
4341 // to the payload.
4342 return parent_llvm_ptr;
4343 }
4344
4345 const llvm_u32 = dg.context.intType(32);
4346 const indices: [2]*llvm.Value = .{
4347 llvm_u32.constInt(0, .False),
4348 llvm_u32.constInt(0, .False),
4349 };
4350 const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty);
4351 return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4352 },
4353 .eu_payload_ptr => {
4354 const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
4355 const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true);
4356
4357 const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload(mod);
4358 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4359 // In this case, we represent pointer to error union the same as pointer
4360 // to the payload.
4361 return parent_llvm_ptr;
4362 }
4363
4364 const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1;
4365 const llvm_u32 = dg.context.intType(32);
4366 const indices: [2]*llvm.Value = .{
4367 llvm_u32.constInt(0, .False),
4368 llvm_u32.constInt(payload_offset, .False),
4369 };
4370 const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty);
4371 return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4372 },
4373 else => unreachable,
4374 }
43754245 }
43764246
43774247 fn lowerDeclRefValue(
......@@ -4380,20 +4250,6 @@ pub const DeclGen = struct {
43804250 decl_index: Module.Decl.Index,
43814251 ) Error!*llvm.Value {
43824252 const mod = self.module;
4383 if (tv.ty.isSlice(mod)) {
4384 const ptr_ty = tv.ty.slicePtrFieldType(mod);
4385 const fields: [2]*llvm.Value = .{
4386 try self.lowerValue(.{
4387 .ty = ptr_ty,
4388 .val = tv.val,
4389 }),
4390 try self.lowerValue(.{
4391 .ty = Type.usize,
4392 .val = try mod.intValue(Type.usize, tv.val.sliceLen(mod)),
4393 }),
4394 };
4395 return self.context.constStruct(&fields, fields.len, .False);
4396 }
43974253
43984254 // In the case of something like:
43994255 // fn foo() void {}
......@@ -4401,13 +4257,13 @@ pub const DeclGen = struct {
44014257 // ... &bar;
44024258 // `bar` is just an alias and we actually want to lower a reference to `foo`.
44034259 const decl = mod.declPtr(decl_index);
4404 if (decl.val.castTag(.function)) |func| {
4405 if (func.data.owner_decl != decl_index) {
4406 return self.lowerDeclRefValue(tv, func.data.owner_decl);
4260 if (decl.getFunction(mod)) |func| {
4261 if (func.owner_decl != decl_index) {
4262 return self.lowerDeclRefValue(tv, func.owner_decl);
44074263 }
4408 } else if (decl.val.castTag(.extern_fn)) |func| {
4409 if (func.data.owner_decl != decl_index) {
4410 return self.lowerDeclRefValue(tv, func.data.owner_decl);
4264 } else if (decl.getExternFunc(mod)) |func| {
4265 if (func.decl != decl_index) {
4266 return self.lowerDeclRefValue(tv, func.decl);
44114267 }
44124268 }
44134269
......@@ -6333,11 +6189,11 @@ pub const FuncGen = struct {
63336189 }
63346190
63356191 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6336 const mod = self.dg.module;
63376192 const dib = self.dg.object.di_builder orelse return null;
63386193 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
63396194
6340 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
6195 const mod = self.dg.module;
6196 const func = self.air.values[ty_pl.payload].getFunction(mod).?;
63416197 const decl_index = func.owner_decl;
63426198 const decl = mod.declPtr(decl_index);
63436199 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
......@@ -6395,8 +6251,8 @@ pub const FuncGen = struct {
63956251 if (self.dg.object.di_builder == null) return null;
63966252 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
63976253
6398 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
63996254 const mod = self.dg.module;
6255 const func = self.air.values[ty_pl.payload].getFunction(mod).?;
64006256 const decl = mod.declPtr(func.owner_decl);
64016257 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
64026258 self.di_file = di_file;
......@@ -8349,7 +8205,7 @@ pub const FuncGen = struct {
83498205 }
83508206
83518207 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
8352 const func = self.dg.decl.getFunction().?;
8208 const func = self.dg.decl.getFunction(mod).?;
83538209 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
83548210 const lbrace_col = func.lbrace_column + 1;
83558211 const di_local_var = dib.createParameterVariable(
......@@ -9147,7 +9003,7 @@ pub const FuncGen = struct {
91479003 defer self.gpa.free(fqn);
91489004 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
91499005
9150 const slice_ty = Type.const_slice_u8_sentinel_0;
9006 const slice_ty = Type.slice_const_u8_sentinel_0;
91519007 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
91529008 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
91539009 const slice_alignment = slice_ty.abiAlignment(mod);
......@@ -9861,7 +9717,7 @@ pub const FuncGen = struct {
98619717 }
98629718
98639719 const mod = self.dg.module;
9864 const slice_ty = Type.const_slice_u8_sentinel_0;
9720 const slice_ty = Type.slice_const_u8_sentinel_0;
98659721 const slice_alignment = slice_ty.abiAlignment(mod);
98669722 const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space
98679723
src/codegen/spirv.zig+191-121
......@@ -236,9 +236,9 @@ pub const DeclGen = struct {
236236 if (try self.air.value(inst, mod)) |val| {
237237 const ty = self.typeOf(inst);
238238 if (ty.zigTypeTag(mod) == .Fn) {
239 const fn_decl_index = switch (val.tag()) {
240 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
241 .function => val.castTag(.function).?.data.owner_decl,
239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,
242242 else => unreachable,
243243 };
244244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
......@@ -261,7 +261,7 @@ pub const DeclGen = struct {
261261 const entry = try self.decl_link.getOrPut(decl_index);
262262 if (!entry.found_existing) {
263263 // TODO: Extern fn?
264 const kind: SpvModule.DeclKind = if (decl.val.tag() == .function)
264 const kind: SpvModule.DeclKind = if (decl.getFunctionIndex(self.module) != .none)
265265 .func
266266 else
267267 .global;
......@@ -573,6 +573,7 @@ pub const DeclGen = struct {
573573
574574 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
575575 const dg = self.dg;
576 const mod = dg.module;
576577
577578 const ty_ref = try self.dg.resolveType(ty, .indirect);
578579 const ty_id = dg.typeId(ty_ref);
......@@ -580,8 +581,8 @@ pub const DeclGen = struct {
580581 const decl = dg.module.declPtr(decl_index);
581582 const spv_decl_index = try dg.resolveDecl(decl_index);
582583
583 switch (decl.val.tag()) {
584 .function => {
584 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
585 .func => {
585586 // TODO: Properly lower function pointers. For now we are going to hack around it and
586587 // just generate an empty pointer. Function pointers are represented by usize for now,
587588 // though.
......@@ -589,7 +590,7 @@ pub const DeclGen = struct {
589590 // TODO: Add dependency
590591 return;
591592 },
592 .extern_fn => unreachable, // TODO
593 .extern_func => unreachable, // TODO
593594 else => {
594595 const result_id = dg.spv.allocId();
595596 log.debug("addDeclRef: id = {}, index = {}, name = {s}", .{ result_id.id, @enumToInt(spv_decl_index), decl.name });
......@@ -610,39 +611,23 @@ pub const DeclGen = struct {
610611 }
611612 }
612613
613 fn lower(self: *@This(), ty: Type, val: Value) !void {
614 fn lower(self: *@This(), ty: Type, arg_val: Value) !void {
614615 const dg = self.dg;
615616 const mod = dg.module;
616617
617 if (val.isUndef(mod)) {
618 var val = arg_val;
619 switch (mod.intern_pool.indexToKey(val.ip_index)) {
620 .runtime_value => |rt| val = rt.val.toValue(),
621 else => {},
622 }
623
624 if (val.isUndefDeep(mod)) {
618625 const size = ty.abiSize(mod);
619626 return try self.addUndef(size);
620627 }
621628
622 switch (ty.zigTypeTag(mod)) {
623 .Int => try self.addInt(ty, val),
624 .Float => try self.addFloat(ty, val),
625 .Bool => try self.addConstBool(val.toBool(mod)),
629 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
626630 .Array => switch (val.tag()) {
627 .aggregate => {
628 const elem_vals = val.castTag(.aggregate).?.data;
629 const elem_ty = ty.childType(mod);
630 const len = @intCast(u32, ty.arrayLenIncludingSentinel(mod)); // TODO: limit spir-v to 32 bit arrays in a more elegant way.
631 for (elem_vals[0..len]) |elem_val| {
632 try self.lower(elem_ty, elem_val);
633 }
634 },
635 .repeated => {
636 const elem_val = val.castTag(.repeated).?.data;
637 const elem_ty = ty.childType(mod);
638 const len = @intCast(u32, ty.arrayLen(mod));
639 for (0..len) |_| {
640 try self.lower(elem_ty, elem_val);
641 }
642 if (ty.sentinel(mod)) |sentinel| {
643 try self.lower(elem_ty, sentinel);
644 }
645 },
646631 .str_lit => {
647632 const str_lit = val.castTag(.str_lit).?.data;
648633 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
......@@ -657,29 +642,6 @@ pub const DeclGen = struct {
657642 },
658643 else => |tag| return dg.todo("indirect array constant with tag {s}", .{@tagName(tag)}),
659644 },
660 .Pointer => switch (val.tag()) {
661 .decl_ref_mut => {
662 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
663 try self.addDeclRef(ty, decl_index);
664 },
665 .decl_ref => {
666 const decl_index = val.castTag(.decl_ref).?.data;
667 try self.addDeclRef(ty, decl_index);
668 },
669 .slice => {
670 const slice = val.castTag(.slice).?.data;
671
672 const ptr_ty = ty.slicePtrFieldType(mod);
673
674 try self.lower(ptr_ty, slice.ptr);
675 try self.addInt(Type.usize, slice.len);
676 },
677 .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)),
678 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
679 try self.addInt(Type.usize, val);
680 },
681 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
682 },
683645 .Struct => {
684646 if (ty.isSimpleTupleOrAnonStruct(mod)) {
685647 unreachable; // TODO
......@@ -705,20 +667,134 @@ pub const DeclGen = struct {
705667 }
706668 }
707669 },
708 .Optional => {
670 .Vector,
671 .Frame,
672 .AnyFrame,
673 => return dg.todo("indirect constant of type {}", .{ty.fmt(mod)}),
674 .Float,
675 .Union,
676 .Optional,
677 .ErrorUnion,
678 .ErrorSet,
679 .Int,
680 .Enum,
681 .Bool,
682 .Pointer,
683 => unreachable, // handled below
684 .Type,
685 .Void,
686 .NoReturn,
687 .ComptimeFloat,
688 .ComptimeInt,
689 .Undefined,
690 .Null,
691 .Opaque,
692 .EnumLiteral,
693 .Fn,
694 => unreachable, // comptime-only types
695 };
696
697 switch (mod.intern_pool.indexToKey(val.ip_index)) {
698 .int_type,
699 .ptr_type,
700 .array_type,
701 .vector_type,
702 .opt_type,
703 .anyframe_type,
704 .error_union_type,
705 .simple_type,
706 .struct_type,
707 .anon_struct_type,
708 .union_type,
709 .opaque_type,
710 .enum_type,
711 .func_type,
712 .error_set_type,
713 .inferred_error_set_type,
714 => unreachable, // types, not values
715
716 .undef, .runtime_value => unreachable, // handled above
717 .simple_value => |simple_value| switch (simple_value) {
718 .undefined,
719 .void,
720 .null,
721 .empty_struct,
722 .@"unreachable",
723 .generic_poison,
724 => unreachable, // non-runtime values
725 .false, .true => try self.addConstBool(val.toBool(mod)),
726 },
727 .variable,
728 .extern_func,
729 .func,
730 .enum_literal,
731 => unreachable, // non-runtime values
732 .int => try self.addInt(ty, val),
733 .err => |err| {
734 const name = mod.intern_pool.stringToSlice(err.name);
735 const kv = try mod.getErrorValue(name);
736 try self.addConstInt(u16, @intCast(u16, kv.value));
737 },
738 .error_union => |error_union| {
739 const payload_ty = ty.errorUnionPayload(mod);
740 const is_pl = val.errorUnionIsPayload(mod);
741 const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
742
743 const eu_layout = dg.errorUnionLayout(payload_ty);
744 if (!eu_layout.payload_has_bits) {
745 return try self.lower(Type.anyerror, error_val);
746 }
747
748 const payload_size = payload_ty.abiSize(mod);
749 const error_size = Type.anyerror.abiAlignment(mod);
750 const ty_size = ty.abiSize(mod);
751 const padding = ty_size - payload_size - error_size;
752
753 const payload_val = switch (error_union.val) {
754 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
755 .payload => |payload| payload,
756 }.toValue();
757
758 if (eu_layout.error_first) {
759 try self.lower(Type.anyerror, error_val);
760 try self.lower(payload_ty, payload_val);
761 } else {
762 try self.lower(payload_ty, payload_val);
763 try self.lower(Type.anyerror, error_val);
764 }
765
766 try self.addUndef(padding);
767 },
768 .enum_tag => {
769 const int_val = try val.enumToInt(ty, mod);
770
771 const int_ty = try ty.intTagType(mod);
772
773 try self.lower(int_ty, int_val);
774 },
775 .float => try self.addFloat(ty, val),
776 .ptr => |ptr| {
777 switch (ptr.addr) {
778 .decl => |decl| try self.addDeclRef(ty, decl),
779 .mut_decl => |mut_decl| try self.addDeclRef(ty, mut_decl.decl),
780 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
781 }
782 if (ptr.len != .none) {
783 try self.addInt(Type.usize, ptr.len.toValue());
784 }
785 },
786 .opt => {
709787 const payload_ty = ty.optionalChild(mod);
710 const has_payload = !val.isNull(mod);
788 const payload_val = val.optionalValue(mod);
711789 const abi_size = ty.abiSize(mod);
712790
713791 if (!payload_ty.hasRuntimeBits(mod)) {
714 try self.addConstBool(has_payload);
792 try self.addConstBool(payload_val != null);
715793 return;
716794 } else if (ty.optionalReprIsPayload(mod)) {
717795 // Optional representation is a nullable pointer or slice.
718 if (val.castTag(.opt_payload)) |payload| {
719 try self.lower(payload_ty, payload.data);
720 } else if (has_payload) {
721 try self.lower(payload_ty, val);
796 if (payload_val) |pl_val| {
797 try self.lower(payload_ty, pl_val);
722798 } else {
723799 const ptr_ty_ref = try dg.resolveType(ty, .indirect);
724800 try self.addNullPtr(ptr_ty_ref);
......@@ -734,27 +810,63 @@ pub const DeclGen = struct {
734810 const payload_size = payload_ty.abiSize(mod);
735811 const padding = abi_size - payload_size - 1;
736812
737 if (val.castTag(.opt_payload)) |payload| {
738 try self.lower(payload_ty, payload.data);
813 if (payload_val) |pl_val| {
814 try self.lower(payload_ty, pl_val);
739815 } else {
740816 try self.addUndef(payload_size);
741817 }
742 try self.addConstBool(has_payload);
818 try self.addConstBool(payload_val != null);
743819 try self.addUndef(padding);
744820 },
745 .Enum => {
746 const int_val = try val.enumToInt(ty, mod);
821 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
822 .array_type => |array_type| {
823 const elem_ty = array_type.child.toType();
824 switch (aggregate.storage) {
825 .bytes => |bytes| try self.addBytes(bytes),
826 .elems, .repeated_elem => {
827 for (0..array_type.len) |i| {
828 try self.lower(elem_ty, switch (aggregate.storage) {
829 .bytes => unreachable,
830 .elems => |elem_vals| elem_vals[@intCast(usize, i)].toValue(),
831 .repeated_elem => |elem_val| elem_val.toValue(),
832 });
833 }
834 },
835 }
836 if (array_type.sentinel != .none) {
837 try self.lower(elem_ty, array_type.sentinel.toValue());
838 }
839 },
840 .vector_type => return dg.todo("indirect constant of type {}", .{ty.fmt(mod)}),
841 .struct_type => {
842 const struct_ty = mod.typeToStruct(ty).?;
747843
748 const int_ty = try ty.intTagType(mod);
844 if (struct_ty.layout == .Packed) {
845 return dg.todo("packed struct constants", .{});
846 }
749847
750 try self.lower(int_ty, int_val);
848 const struct_begin = self.size;
849 const field_vals = val.castTag(.aggregate).?.data;
850 for (struct_ty.fields.values(), 0..) |field, i| {
851 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
852 try self.lower(field.ty, field_vals[i]);
853
854 // Add padding if required.
855 // TODO: Add to type generation as well?
856 const unpadded_field_end = self.size - struct_begin;
857 const padded_field_end = ty.structFieldOffset(i + 1, mod);
858 const padding = padded_field_end - unpadded_field_end;
859 try self.addUndef(padding);
860 }
861 },
862 .anon_struct_type => unreachable, // TODO
863 else => unreachable,
751864 },
752 .Union => {
753 const tag_and_val = val.castTag(.@"union").?.data;
865 .un => |un| {
754866 const layout = ty.unionGetLayout(mod);
755867
756868 if (layout.payload_size == 0) {
757 return try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag);
869 return try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
758870 }
759871
760872 const union_ty = mod.typeToUnion(ty).?;
......@@ -762,18 +874,18 @@ pub const DeclGen = struct {
762874 return dg.todo("packed union constants", .{});
763875 }
764876
765 const active_field = ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;
877 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), dg.module).?;
766878 const active_field_ty = union_ty.fields.values()[active_field].ty;
767879
768880 const has_tag = layout.tag_size != 0;
769881 const tag_first = layout.tag_align >= layout.payload_align;
770882
771883 if (has_tag and tag_first) {
772 try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag);
884 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
773885 }
774886
775887 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
776 try self.lower(active_field_ty, tag_and_val.val);
888 try self.lower(active_field_ty, un.val.toValue());
777889 break :blk active_field_ty.abiSize(mod);
778890 } else 0;
779891
......@@ -781,53 +893,11 @@ pub const DeclGen = struct {
781893 try self.addUndef(payload_padding_len);
782894
783895 if (has_tag and !tag_first) {
784 try self.lower(ty.unionTagTypeSafety(mod).?, tag_and_val.tag);
896 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
785897 }
786898
787899 try self.addUndef(layout.padding);
788900 },
789 .ErrorSet => switch (val.ip_index) {
790 .none => switch (val.tag()) {
791 .@"error" => {
792 const err_name = val.castTag(.@"error").?.data.name;
793 const kv = try dg.module.getErrorValue(err_name);
794 try self.addConstInt(u16, @intCast(u16, kv.value));
795 },
796 else => unreachable,
797 },
798 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
799 .int => |int| try self.addConstInt(u16, @intCast(u16, int.storage.u64)),
800 else => unreachable,
801 },
802 },
803 .ErrorUnion => {
804 const payload_ty = ty.errorUnionPayload(mod);
805 const is_pl = val.errorUnionIsPayload();
806 const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
807
808 const eu_layout = dg.errorUnionLayout(payload_ty);
809 if (!eu_layout.payload_has_bits) {
810 return try self.lower(Type.anyerror, error_val);
811 }
812
813 const payload_size = payload_ty.abiSize(mod);
814 const error_size = Type.anyerror.abiAlignment(mod);
815 const ty_size = ty.abiSize(mod);
816 const padding = ty_size - payload_size - error_size;
817
818 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
819
820 if (eu_layout.error_first) {
821 try self.lower(Type.anyerror, error_val);
822 try self.lower(payload_ty, payload_val);
823 } else {
824 try self.lower(payload_ty, payload_val);
825 try self.lower(Type.anyerror, error_val);
826 }
827
828 try self.addUndef(padding);
829 },
830 else => |tag| return dg.todo("indirect constant of type {s}", .{@tagName(tag)}),
831901 }
832902 }
833903 };
......@@ -1542,7 +1612,7 @@ pub const DeclGen = struct {
15421612 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
15431613 log.debug("genDecl: id = {}, index = {}, name = {s}", .{ decl_id.id, @enumToInt(spv_decl_index), decl.name });
15441614
1545 if (decl.val.castTag(.function)) |_| {
1615 if (decl.getFunction(mod)) |_| {
15461616 assert(decl.ty.zigTypeTag(mod) == .Fn);
15471617 const prototype_id = try self.resolveTypeId(decl.ty);
15481618 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
......@@ -1595,8 +1665,8 @@ pub const DeclGen = struct {
15951665 try self.generateTestEntryPoint(fqn, spv_decl_index);
15961666 }
15971667 } else {
1598 const init_val = if (decl.val.castTag(.variable)) |payload|
1599 payload.data.init
1668 const init_val = if (decl.getVariable(mod)) |payload|
1669 payload.init.toValue()
16001670 else
16011671 decl.val;
16021672
src/link.zig+10-9
......@@ -564,7 +564,8 @@ pub const File = struct {
564564 }
565565
566566 /// May be called before or after updateDeclExports for any given Decl.
567 pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void {
567 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
568 const func = module.funcPtr(func_index);
568569 const owner_decl = module.declPtr(func.owner_decl);
569570 log.debug("updateFunc {*} ({s}), type={}", .{
570571 owner_decl, owner_decl.name, owner_decl.ty.fmt(module),
......@@ -575,14 +576,14 @@ pub const File = struct {
575576 }
576577 switch (base.tag) {
577578 // zig fmt: off
578 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),
579 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func, air, liveness),
580 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func, air, liveness),
581 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness),
582 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func, air, liveness),
583 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func, air, liveness),
584 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func, air, liveness),
585 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func, air, liveness),
579 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness),
580 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness),
581 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness),
582 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness),
583 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness),
584 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness),
585 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness),
586 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness),
586587 // zig fmt: on
587588 }
588589 }
src/link/C.zig+6-4
......@@ -87,12 +87,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
8787 }
8888}
8989
90pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
90pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
9191 const tracy = trace(@src());
9292 defer tracy.end();
9393
9494 const gpa = self.base.allocator;
9595
96 const func = module.funcPtr(func_index);
9697 const decl_index = func.owner_decl;
9798 const gop = try self.decl_table.getOrPut(gpa, decl_index);
9899 if (!gop.found_existing) {
......@@ -111,7 +112,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
111112 .value_map = codegen.CValueMap.init(gpa),
112113 .air = air,
113114 .liveness = liveness,
114 .func = func,
115 .func_index = func_index,
115116 .object = .{
116117 .dg = .{
117118 .gpa = gpa,
......@@ -555,7 +556,8 @@ fn flushDecl(
555556 export_names: std.StringHashMapUnmanaged(void),
556557) FlushDeclError!void {
557558 const gpa = self.base.allocator;
558 const decl = self.base.options.module.?.declPtr(decl_index);
559 const mod = self.base.options.module.?;
560 const decl = mod.declPtr(decl_index);
559561 // Before flushing any particular Decl we must ensure its
560562 // dependencies are already flushed, so that the order in the .c
561563 // file comes out correctly.
......@@ -569,7 +571,7 @@ fn flushDecl(
569571
570572 try self.flushLazyFns(f, decl_block.lazy_fns);
571573 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
572 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
574 if (!(decl.isExtern(mod) and export_names.contains(mem.span(decl.name))))
573575 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
574576}
575577
src/link/Coff.zig+9-9
......@@ -1032,18 +1032,19 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
10321032 self.getAtomPtr(atom_index).sym_index = 0;
10331033}
10341034
1035pub fn updateFunc(self: *Coff, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
10361036 if (build_options.skip_non_native and builtin.object_format != .coff) {
10371037 @panic("Attempted to compile for object format that was disabled by build configuration");
10381038 }
10391039 if (build_options.have_llvm) {
10401040 if (self.llvm_object) |llvm_object| {
1041 return llvm_object.updateFunc(mod, func, air, liveness);
1041 return llvm_object.updateFunc(mod, func_index, air, liveness);
10421042 }
10431043 }
10441044 const tracy = trace(@src());
10451045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
10471048 const decl_index = func.owner_decl;
10481049 const decl = mod.declPtr(decl_index);
10491050
......@@ -1057,7 +1058,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func: *Module.Fn, air: Air, livenes
10571058 const res = try codegen.generateFunction(
10581059 &self.base,
10591060 decl.srcLoc(mod),
1060 func,
1061 func_index,
10611062 air,
10621063 liveness,
10631064 &code_buffer,
......@@ -1155,11 +1156,10 @@ pub fn updateDecl(
11551156
11561157 const decl = mod.declPtr(decl_index);
11571158
1158 if (decl.val.tag() == .extern_fn) {
1159 if (decl.getExternFunc(mod)) |_| {
11591160 return; // TODO Should we do more when front-end analyzed extern decl?
11601161 }
1161 if (decl.val.castTag(.variable)) |payload| {
1162 const variable = payload.data;
1162 if (decl.getVariable(mod)) |variable| {
11631163 if (variable.is_extern) {
11641164 return; // TODO Should we do more when front-end analyzed extern decl?
11651165 }
......@@ -1172,7 +1172,7 @@ pub fn updateDecl(
11721172 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
11731173 defer code_buffer.deinit();
11741174
1175 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
1175 const decl_val = if (decl.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
11761176 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
11771177 .ty = decl.ty,
11781178 .val = decl_val,
......@@ -1313,7 +1313,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
13131313 // TODO: what if this is a function pointer?
13141314 .Fn => break :blk self.text_section_index.?,
13151315 else => {
1316 if (val.castTag(.variable)) |_| {
1316 if (decl.getVariable(mod)) |_| {
13171317 break :blk self.data_section_index.?;
13181318 }
13191319 break :blk self.rdata_section_index.?;
......@@ -1425,7 +1425,7 @@ pub fn updateDeclExports(
14251425 // detect the default subsystem.
14261426 for (exports) |exp| {
14271427 const exported_decl = mod.declPtr(exp.exported_decl);
1428 if (exported_decl.getFunction() == null) continue;
1428 if (exported_decl.getFunctionIndex(mod) == .none) continue;
14291429 const winapi_cc = switch (self.base.options.target.cpu.arch) {
14301430 .x86 => std.builtin.CallingConvention.Stdcall,
14311431 else => std.builtin.CallingConvention.C,
src/link/Dwarf.zig+4-4
......@@ -971,7 +971,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
971971 // For functions we need to add a prologue to the debug line program.
972972 try dbg_line_buffer.ensureTotalCapacity(26);
973973
974 const func = decl.val.castTag(.function).?.data;
974 const func = decl.getFunction(mod).?;
975975 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
976976 decl.src_line,
977977 func.lbrace_line,
......@@ -1514,7 +1514,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
15141514 }
15151515}
15161516
1517pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.Decl.Index) !void {
1517pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !void {
15181518 const tracy = trace(@src());
15191519 defer tracy.end();
15201520
......@@ -1522,8 +1522,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De
15221522 const atom = self.getAtom(.src_fn, atom_index);
15231523 if (atom.len == 0) return;
15241524
1525 const decl = module.declPtr(decl_index);
1526 const func = decl.val.castTag(.function).?.data;
1525 const decl = mod.declPtr(decl_index);
1526 const func = decl.getFunction(mod).?;
15271527 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
15281528 decl.src_line,
15291529 func.lbrace_line,
src/link/Elf.zig+9-9
......@@ -2465,7 +2465,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
24652465 // TODO: what if this is a function pointer?
24662466 .Fn => break :blk self.text_section_index.?,
24672467 else => {
2468 if (val.castTag(.variable)) |_| {
2468 if (decl.getVariable(mod)) |_| {
24692469 break :blk self.data_section_index.?;
24702470 }
24712471 break :blk self.rodata_section_index.?;
......@@ -2574,17 +2574,18 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
25742574 return local_sym;
25752575}
25762576
2577pub fn updateFunc(self: *Elf, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
2577pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
25782578 if (build_options.skip_non_native and builtin.object_format != .elf) {
25792579 @panic("Attempted to compile for object format that was disabled by build configuration");
25802580 }
25812581 if (build_options.have_llvm) {
2582 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
2582 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
25832583 }
25842584
25852585 const tracy = trace(@src());
25862586 defer tracy.end();
25872587
2588 const func = mod.funcPtr(func_index);
25882589 const decl_index = func.owner_decl;
25892590 const decl = mod.declPtr(decl_index);
25902591
......@@ -2599,11 +2600,11 @@ pub fn updateFunc(self: *Elf, mod: *Module, func: *Module.Fn, air: Air, liveness
25992600 defer if (decl_state) |*ds| ds.deinit();
26002601
26012602 const res = if (decl_state) |*ds|
2602 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func, air, liveness, &code_buffer, .{
2603 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .{
26032604 .dwarf = ds,
26042605 })
26052606 else
2606 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func, air, liveness, &code_buffer, .none);
2607 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .none);
26072608
26082609 const code = switch (res) {
26092610 .ok => code_buffer.items,
......@@ -2646,11 +2647,10 @@ pub fn updateDecl(
26462647
26472648 const decl = mod.declPtr(decl_index);
26482649
2649 if (decl.val.tag() == .extern_fn) {
2650 if (decl.getExternFunc(mod)) |_| {
26502651 return; // TODO Should we do more when front-end analyzed extern decl?
26512652 }
2652 if (decl.val.castTag(.variable)) |payload| {
2653 const variable = payload.data;
2653 if (decl.getVariable(mod)) |variable| {
26542654 if (variable.is_extern) {
26552655 return; // TODO Should we do more when front-end analyzed extern decl?
26562656 }
......@@ -2667,7 +2667,7 @@ pub fn updateDecl(
26672667 defer if (decl_state) |*ds| ds.deinit();
26682668
26692669 // TODO implement .debug_info for global variables
2670 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2670 const decl_val = if (decl.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
26712671 const res = if (decl_state) |*ds|
26722672 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
26732673 .ty = decl.ty,
src/link/MachO.zig+14-14
......@@ -1847,16 +1847,17 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
18471847 self.markRelocsDirtyByTarget(target);
18481848}
18491849
1850pub fn updateFunc(self: *MachO, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1850pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
18511851 if (build_options.skip_non_native and builtin.object_format != .macho) {
18521852 @panic("Attempted to compile for object format that was disabled by build configuration");
18531853 }
18541854 if (build_options.have_llvm) {
1855 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
1855 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
18561856 }
18571857 const tracy = trace(@src());
18581858 defer tracy.end();
18591859
1860 const func = mod.funcPtr(func_index);
18601861 const decl_index = func.owner_decl;
18611862 const decl = mod.declPtr(decl_index);
18621863
......@@ -1874,11 +1875,11 @@ pub fn updateFunc(self: *MachO, mod: *Module, func: *Module.Fn, air: Air, livene
18741875 defer if (decl_state) |*ds| ds.deinit();
18751876
18761877 const res = if (decl_state) |*ds|
1877 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func, air, liveness, &code_buffer, .{
1878 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .{
18781879 .dwarf = ds,
18791880 })
18801881 else
1881 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func, air, liveness, &code_buffer, .none);
1882 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .none);
18821883
18831884 var code = switch (res) {
18841885 .ok => code_buffer.items,
......@@ -1983,18 +1984,17 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo
19831984
19841985 const decl = mod.declPtr(decl_index);
19851986
1986 if (decl.val.tag() == .extern_fn) {
1987 if (decl.getExternFunc(mod)) |_| {
19871988 return; // TODO Should we do more when front-end analyzed extern decl?
19881989 }
1989 if (decl.val.castTag(.variable)) |payload| {
1990 const variable = payload.data;
1990 if (decl.getVariable(mod)) |variable| {
19911991 if (variable.is_extern) {
19921992 return; // TODO Should we do more when front-end analyzed extern decl?
19931993 }
19941994 }
19951995
1996 const is_threadlocal = if (decl.val.castTag(.variable)) |payload|
1997 payload.data.is_threadlocal and !self.base.options.single_threaded
1996 const is_threadlocal = if (decl.getVariable(mod)) |variable|
1997 variable.is_threadlocal and !self.base.options.single_threaded
19981998 else
19991999 false;
20002000 if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index);
......@@ -2012,7 +2012,7 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo
20122012 null;
20132013 defer if (decl_state) |*ds| ds.deinit();
20142014
2015 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2015 const decl_val = if (decl.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
20162016 const res = if (decl_state) |*ds|
20172017 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
20182018 .ty = decl.ty,
......@@ -2177,7 +2177,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
21772177
21782178 const decl = module.declPtr(decl_index);
21792179 const decl_metadata = self.decls.get(decl_index).?;
2180 const decl_val = decl.val.castTag(.variable).?.data.init;
2180 const decl_val = decl.getVariable(mod).?.init.toValue();
21812181 const res = if (decl_state) |*ds|
21822182 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
21832183 .ty = decl.ty,
......@@ -2278,8 +2278,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
22782278 }
22792279 }
22802280
2281 if (val.castTag(.variable)) |variable| {
2282 if (variable.data.is_threadlocal and !single_threaded) {
2281 if (decl.getVariable(mod)) |variable| {
2282 if (variable.is_threadlocal and !single_threaded) {
22832283 break :blk self.thread_data_section_index.?;
22842284 }
22852285 break :blk self.data_section_index.?;
......@@ -2289,7 +2289,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
22892289 // TODO: what if this is a function pointer?
22902290 .Fn => break :blk self.text_section_index.?,
22912291 else => {
2292 if (val.castTag(.variable)) |_| {
2292 if (decl.getVariable(mod)) |_| {
22932293 break :blk self.data_section_index.?;
22942294 }
22952295 break :blk self.data_const_section_index.?;
src/link/NvPtx.zig+2-2
......@@ -68,9 +68,9 @@ pub fn deinit(self: *NvPtx) void {
6868 self.base.allocator.free(self.ptx_file_name);
6969}
7070
71pub fn updateFunc(self: *NvPtx, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
71pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
7272 if (!build_options.have_llvm) return;
73 try self.llvm_object.updateFunc(module, func, air, liveness);
73 try self.llvm_object.updateFunc(module, func_index, air, liveness);
7474}
7575
7676pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void {
src/link/Plan9.zig+7-7
......@@ -276,11 +276,12 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
276276 }
277277}
278278
279pub fn updateFunc(self: *Plan9, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
279pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
280280 if (build_options.skip_non_native and builtin.object_format != .plan9) {
281281 @panic("Attempted to compile for object format that was disabled by build configuration");
282282 }
283283
284 const func = mod.funcPtr(func_index);
284285 const decl_index = func.owner_decl;
285286 const decl = mod.declPtr(decl_index);
286287 self.freeUnnamedConsts(decl_index);
......@@ -299,7 +300,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func: *Module.Fn, air: Air, livene
299300 const res = try codegen.generateFunction(
300301 &self.base,
301302 decl.srcLoc(mod),
302 func,
303 func_index,
303304 air,
304305 liveness,
305306 &code_buffer,
......@@ -391,11 +392,10 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
391392pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {
392393 const decl = mod.declPtr(decl_index);
393394
394 if (decl.val.tag() == .extern_fn) {
395 if (decl.getExternFunc(mod)) |_| {
395396 return; // TODO Should we do more when front-end analyzed extern decl?
396397 }
397 if (decl.val.castTag(.variable)) |payload| {
398 const variable = payload.data;
398 if (decl.getVariable(mod)) |variable| {
399399 if (variable.is_extern) {
400400 return; // TODO Should we do more when front-end analyzed extern decl?
401401 }
......@@ -407,7 +407,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !vo
407407
408408 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
409409 defer code_buffer.deinit();
410 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
410 const decl_val = if (decl.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
411411 // TODO we need the symbol index for symbol in the table of locals for the containing atom
412412 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
413413 .ty = decl.ty,
......@@ -771,7 +771,7 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
771771 // in the deleteUnusedDecl function.
772772 const mod = self.base.options.module.?;
773773 const decl = mod.declPtr(decl_index);
774 const is_fn = (decl.val.tag() == .function);
774 const is_fn = decl.getFunctionIndex(mod) != .none;
775775 if (is_fn) {
776776 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
777777 var submap = symidx_and_submap.functions;
src/link/SpirV.zig+4-2
......@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {
103103 self.decl_link.deinit();
104104}
105105
106pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
106pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
107107 if (build_options.skip_non_native) {
108108 @panic("Attempted to compile for architecture that was disabled by build configuration");
109109 }
110110
111 const func = module.funcPtr(func_index);
112
111113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
112114 defer decl_gen.deinit();
113115
......@@ -136,7 +138,7 @@ pub fn updateDeclExports(
136138 exports: []const *Module.Export,
137139) !void {
138140 const decl = mod.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention(mod) == .Kernel) {
141 if (decl.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
140142 // TODO: Unify with resolveDecl in spirv.zig.
141143 const entry = try self.decl_link.getOrPut(decl_index);
142144 if (!entry.found_existing) {
src/link/Wasm.zig+21-19
......@@ -1324,17 +1324,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
13241324 return index;
13251325}
13261326
1327pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1327pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
13281328 if (build_options.skip_non_native and builtin.object_format != .wasm) {
13291329 @panic("Attempted to compile for object format that was disabled by build configuration");
13301330 }
13311331 if (build_options.have_llvm) {
1332 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
1332 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
13331333 }
13341334
13351335 const tracy = trace(@src());
13361336 defer tracy.end();
13371337
1338 const func = mod.funcPtr(func_index);
13381339 const decl_index = func.owner_decl;
13391340 const decl = mod.declPtr(decl_index);
13401341 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
......@@ -1358,7 +1359,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
13581359 const result = try codegen.generateFunction(
13591360 &wasm.base,
13601361 decl.srcLoc(mod),
1361 func,
1362 func_index,
13621363 air,
13631364 liveness,
13641365 &code_writer,
......@@ -1403,9 +1404,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
14031404 defer tracy.end();
14041405
14051406 const decl = mod.declPtr(decl_index);
1406 if (decl.val.castTag(.function)) |_| {
1407 if (decl.getFunction(mod)) |_| {
14071408 return;
1408 } else if (decl.val.castTag(.extern_fn)) |_| {
1409 } else if (decl.getExternFunc(mod)) |_| {
14091410 return;
14101411 }
14111412
......@@ -1413,12 +1414,13 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
14131414 const atom = wasm.getAtomPtr(atom_index);
14141415 atom.clear();
14151416
1416 if (decl.isExtern()) {
1417 const variable = decl.getVariable().?;
1417 if (decl.isExtern(mod)) {
1418 const variable = decl.getVariable(mod).?;
14181419 const name = mem.sliceTo(decl.name, 0);
1419 return wasm.addOrUpdateImport(name, atom.sym_index, variable.lib_name, null);
1420 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
1421 return wasm.addOrUpdateImport(name, atom.sym_index, lib_name, null);
14201422 }
1421 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
1423 const val = if (decl.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
14221424
14231425 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
14241426 defer code_writer.deinit();
......@@ -1791,7 +1793,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
17911793 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
17921794 }
17931795
1794 if (decl.isExtern()) {
1796 if (decl.isExtern(mod)) {
17951797 _ = wasm.imports.remove(atom.symbolLoc());
17961798 }
17971799 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
......@@ -1852,7 +1854,7 @@ pub fn addOrUpdateImport(
18521854 /// Symbol index that is external
18531855 symbol_index: u32,
18541856 /// Optional library name (i.e. `extern "c" fn foo() void`
1855 lib_name: ?[*:0]const u8,
1857 lib_name: ?[:0]const u8,
18561858 /// The index of the type that represents the function signature
18571859 /// when the extern is a function. When this is null, a data-symbol
18581860 /// is asserted instead.
......@@ -1863,7 +1865,7 @@ pub fn addOrUpdateImport(
18631865 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same
18641866 // name but different module can be resolved correctly.
18651867 const mangle_name = lib_name != null and
1866 !std.mem.eql(u8, std.mem.sliceTo(lib_name.?, 0), "c");
1868 !std.mem.eql(u8, lib_name.?, "c");
18671869 const full_name = if (mangle_name) full_name: {
18681870 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });
18691871 } else name;
......@@ -1889,7 +1891,7 @@ pub fn addOrUpdateImport(
18891891 if (type_index) |ty_index| {
18901892 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });
18911893 const module_name = if (lib_name) |l_name| blk: {
1892 break :blk mem.sliceTo(l_name, 0);
1894 break :blk l_name;
18931895 } else wasm.host_name;
18941896 if (!gop.found_existing) {
18951897 gop.value_ptr.* = .{
......@@ -2931,7 +2933,7 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
29312933
29322934 const atom_index = try wasm.createAtom();
29332935 const atom = wasm.getAtomPtr(atom_index);
2934 const slice_ty = Type.const_slice_u8_sentinel_0;
2936 const slice_ty = Type.slice_const_u8_sentinel_0;
29352937 const mod = wasm.base.options.module.?;
29362938 atom.alignment = slice_ty.abiAlignment(mod);
29372939 const sym_index = atom.sym_index;
......@@ -2988,7 +2990,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
29882990 for (mod.error_name_list.items) |error_name| {
29892991 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted
29902992
2991 const slice_ty = Type.const_slice_u8_sentinel_0;
2993 const slice_ty = Type.slice_const_u8_sentinel_0;
29922994 const offset = @intCast(u32, atom.code.items.len);
29932995 // first we create the data for the slice of the name
29942996 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated
......@@ -3366,15 +3368,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
33663368 var decl_it = wasm.decls.iterator();
33673369 while (decl_it.next()) |entry| {
33683370 const decl = mod.declPtr(entry.key_ptr.*);
3369 if (decl.isExtern()) continue;
3371 if (decl.isExtern(mod)) continue;
33703372 const atom_index = entry.value_ptr.*;
33713373 const atom = wasm.getAtomPtr(atom_index);
33723374 if (decl.ty.zigTypeTag(mod) == .Fn) {
33733375 try wasm.parseAtom(atom_index, .function);
3374 } else if (decl.getVariable()) |variable| {
3375 if (!variable.is_mutable) {
3376 } else if (decl.getVariable(mod)) |variable| {
3377 if (variable.is_const) {
33763378 try wasm.parseAtom(atom_index, .{ .data = .read_only });
3377 } else if (variable.init.isUndefDeep(mod)) {
3379 } else if (variable.init.toValue().isUndefDeep(mod)) {
33783380 // for safe build modes, we store the atom in the data segment,
33793381 // whereas for unsafe build modes we store it in bss.
33803382 const is_initialized = wasm.base.options.optimize_mode == .Debug or
src/print_air.zig+2-2
......@@ -699,8 +699,8 @@ const Writer = struct {
699699
700700 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
701701 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
702 const function = w.air.values[ty_pl.payload].castTag(.function).?.data;
703 const owner_decl = w.module.declPtr(function.owner_decl);
702 const func_index = w.module.intern_pool.indexToFunc(w.air.values[ty_pl.payload].ip_index);
703 const owner_decl = w.module.declPtr(w.module.funcPtrUnwrap(func_index).?.owner_decl);
704704 try s.print("{s}", .{owner_decl.name});
705705 }
706706
src/type.zig+290-173
......@@ -93,16 +93,23 @@ pub const Type = struct {
9393 },
9494
9595 // values, not types
96 .undef => unreachable,
97 .un => unreachable,
98 .extern_func => unreachable,
99 .int => unreachable,
100 .float => unreachable,
101 .ptr => unreachable,
102 .opt => unreachable,
103 .enum_tag => unreachable,
104 .simple_value => unreachable,
105 .aggregate => unreachable,
96 .undef,
97 .runtime_value,
98 .simple_value,
99 .variable,
100 .extern_func,
101 .func,
102 .int,
103 .err,
104 .error_union,
105 .enum_literal,
106 .enum_tag,
107 .float,
108 .ptr,
109 .opt,
110 .aggregate,
111 .un,
112 => unreachable,
106113 };
107114 }
108115
......@@ -358,7 +365,7 @@ pub const Type = struct {
358365 const func = ies.func;
359366
360367 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
361 const owner_decl = mod.declPtr(func.owner_decl);
368 const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
362369 try owner_decl.renderFullyQualifiedName(mod, writer);
363370 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
364371 },
......@@ -467,16 +474,23 @@ pub const Type = struct {
467474 },
468475
469476 // values, not types
470 .undef => unreachable,
471 .un => unreachable,
472 .simple_value => unreachable,
473 .extern_func => unreachable,
474 .int => unreachable,
475 .float => unreachable,
476 .ptr => unreachable,
477 .opt => unreachable,
478 .enum_tag => unreachable,
479 .aggregate => unreachable,
477 .undef,
478 .runtime_value,
479 .simple_value,
480 .variable,
481 .extern_func,
482 .func,
483 .int,
484 .err,
485 .error_union,
486 .enum_literal,
487 .enum_tag,
488 .float,
489 .ptr,
490 .opt,
491 .aggregate,
492 .un,
493 => unreachable,
480494 }
481495 }
482496
......@@ -675,16 +689,23 @@ pub const Type = struct {
675689 .enum_type => |enum_type| enum_type.tag_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
676690
677691 // values, not types
678 .undef => unreachable,
679 .un => unreachable,
680 .simple_value => unreachable,
681 .extern_func => unreachable,
682 .int => unreachable,
683 .float => unreachable,
684 .ptr => unreachable,
685 .opt => unreachable,
686 .enum_tag => unreachable,
687 .aggregate => unreachable,
692 .undef,
693 .runtime_value,
694 .simple_value,
695 .variable,
696 .extern_func,
697 .func,
698 .int,
699 .err,
700 .error_union,
701 .enum_literal,
702 .enum_tag,
703 .float,
704 .ptr,
705 .opt,
706 .aggregate,
707 .un,
708 => unreachable,
688709 },
689710 };
690711 }
......@@ -777,16 +798,23 @@ pub const Type = struct {
777798 },
778799
779800 // values, not types
780 .undef => unreachable,
781 .un => unreachable,
782 .simple_value => unreachable,
783 .extern_func => unreachable,
784 .int => unreachable,
785 .float => unreachable,
786 .ptr => unreachable,
787 .opt => unreachable,
788 .enum_tag => unreachable,
789 .aggregate => unreachable,
801 .undef,
802 .runtime_value,
803 .simple_value,
804 .variable,
805 .extern_func,
806 .func,
807 .int,
808 .err,
809 .error_union,
810 .enum_literal,
811 .enum_tag,
812 .float,
813 .ptr,
814 .opt,
815 .aggregate,
816 .un,
817 => unreachable,
790818 };
791819 }
792820
......@@ -866,8 +894,8 @@ pub const Type = struct {
866894
867895 /// May capture a reference to `ty`.
868896 /// Returned value has type `comptime_int`.
869 pub fn lazyAbiAlignment(ty: Type, mod: *Module, arena: Allocator) !Value {
870 switch (try ty.abiAlignmentAdvanced(mod, .{ .lazy = arena })) {
897 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
898 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
871899 .val => |val| return val,
872900 .scalar => |x| return mod.intValue(Type.comptime_int, x),
873901 }
......@@ -880,7 +908,7 @@ pub const Type = struct {
880908
881909 pub const AbiAlignmentAdvancedStrat = union(enum) {
882910 eager,
883 lazy: Allocator,
911 lazy,
884912 sema: *Sema,
885913 };
886914
......@@ -1019,16 +1047,18 @@ pub const Type = struct {
10191047 if (!struct_obj.haveFieldTypes()) switch (strat) {
10201048 .eager => unreachable, // struct layout not resolved
10211049 .sema => unreachable, // handled above
1022 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1050 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1051 .ty = .comptime_int_type,
1052 .storage = .{ .lazy_align = ty.ip_index },
1053 } })).toValue() },
10231054 };
10241055 if (struct_obj.layout == .Packed) {
10251056 switch (strat) {
10261057 .sema => |sema| try sema.resolveTypeLayout(ty),
1027 .lazy => |arena| {
1028 if (!struct_obj.haveLayout()) {
1029 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
1030 }
1031 },
1058 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1059 .ty = .comptime_int_type,
1060 .storage = .{ .lazy_align = ty.ip_index },
1061 } })).toValue() },
10321062 .eager => {},
10331063 }
10341064 assert(struct_obj.haveLayout());
......@@ -1039,7 +1069,10 @@ pub const Type = struct {
10391069 var big_align: u32 = 0;
10401070 for (fields.values()) |field| {
10411071 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1042 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
1072 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1073 .ty = .comptime_int_type,
1074 .storage = .{ .lazy_align = ty.ip_index },
1075 } })).toValue() },
10431076 else => |e| return e,
10441077 })) continue;
10451078
......@@ -1050,7 +1083,10 @@ pub const Type = struct {
10501083 .val => switch (strat) {
10511084 .eager => unreachable, // struct layout not resolved
10521085 .sema => unreachable, // handled above
1053 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1086 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1087 .ty = .comptime_int_type,
1088 .storage = .{ .lazy_align = ty.ip_index },
1089 } })).toValue() },
10541090 },
10551091 };
10561092 big_align = @max(big_align, field_align);
......@@ -1077,7 +1113,10 @@ pub const Type = struct {
10771113 .val => switch (strat) {
10781114 .eager => unreachable, // field type alignment not resolved
10791115 .sema => unreachable, // passed to abiAlignmentAdvanced above
1080 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1116 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1117 .ty = .comptime_int_type,
1118 .storage = .{ .lazy_align = ty.ip_index },
1119 } })).toValue() },
10811120 },
10821121 }
10831122 }
......@@ -1092,16 +1131,23 @@ pub const Type = struct {
10921131 .enum_type => |enum_type| return AbiAlignmentAdvanced{ .scalar = enum_type.tag_ty.toType().abiAlignment(mod) },
10931132
10941133 // values, not types
1095 .undef => unreachable,
1096 .un => unreachable,
1097 .simple_value => unreachable,
1098 .extern_func => unreachable,
1099 .int => unreachable,
1100 .float => unreachable,
1101 .ptr => unreachable,
1102 .opt => unreachable,
1103 .enum_tag => unreachable,
1104 .aggregate => unreachable,
1134 .undef,
1135 .runtime_value,
1136 .simple_value,
1137 .variable,
1138 .extern_func,
1139 .func,
1140 .int,
1141 .err,
1142 .error_union,
1143 .enum_literal,
1144 .enum_tag,
1145 .float,
1146 .ptr,
1147 .opt,
1148 .aggregate,
1149 .un,
1150 => unreachable,
11051151 },
11061152 }
11071153 }
......@@ -1118,7 +1164,10 @@ pub const Type = struct {
11181164 switch (strat) {
11191165 .eager, .sema => {
11201166 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1121 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
1167 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1168 .ty = .comptime_int_type,
1169 .storage = .{ .lazy_align = ty.ip_index },
1170 } })).toValue() },
11221171 else => |e| return e,
11231172 })) {
11241173 return AbiAlignmentAdvanced{ .scalar = code_align };
......@@ -1128,7 +1177,7 @@ pub const Type = struct {
11281177 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,
11291178 ) };
11301179 },
1131 .lazy => |arena| {
1180 .lazy => {
11321181 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {
11331182 .scalar => |payload_align| {
11341183 return AbiAlignmentAdvanced{
......@@ -1137,7 +1186,10 @@ pub const Type = struct {
11371186 },
11381187 .val => {},
11391188 }
1140 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
1189 return .{ .val = (try mod.intern(.{ .int = .{
1190 .ty = .comptime_int_type,
1191 .storage = .{ .lazy_align = ty.ip_index },
1192 } })).toValue() };
11411193 },
11421194 }
11431195 }
......@@ -1160,16 +1212,22 @@ pub const Type = struct {
11601212 switch (strat) {
11611213 .eager, .sema => {
11621214 if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1163 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
1215 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1216 .ty = .comptime_int_type,
1217 .storage = .{ .lazy_align = ty.ip_index },
1218 } })).toValue() },
11641219 else => |e| return e,
11651220 })) {
11661221 return AbiAlignmentAdvanced{ .scalar = 1 };
11671222 }
11681223 return child_type.abiAlignmentAdvanced(mod, strat);
11691224 },
1170 .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
1225 .lazy => switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
11711226 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },
1172 .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1227 .val => return .{ .val = (try mod.intern(.{ .int = .{
1228 .ty = .comptime_int_type,
1229 .storage = .{ .lazy_align = ty.ip_index },
1230 } })).toValue() },
11731231 },
11741232 }
11751233 }
......@@ -1198,7 +1256,10 @@ pub const Type = struct {
11981256 if (!union_obj.haveFieldTypes()) switch (strat) {
11991257 .eager => unreachable, // union layout not resolved
12001258 .sema => unreachable, // handled above
1201 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1259 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1260 .ty = .comptime_int_type,
1261 .storage = .{ .lazy_align = ty.ip_index },
1262 } })).toValue() },
12021263 };
12031264 if (union_obj.fields.count() == 0) {
12041265 if (have_tag) {
......@@ -1212,7 +1273,10 @@ pub const Type = struct {
12121273 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(mod);
12131274 for (union_obj.fields.values()) |field| {
12141275 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1215 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
1276 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1277 .ty = .comptime_int_type,
1278 .storage = .{ .lazy_align = ty.ip_index },
1279 } })).toValue() },
12161280 else => |e| return e,
12171281 })) continue;
12181282
......@@ -1223,7 +1287,10 @@ pub const Type = struct {
12231287 .val => switch (strat) {
12241288 .eager => unreachable, // struct layout not resolved
12251289 .sema => unreachable, // handled above
1226 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1290 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1291 .ty = .comptime_int_type,
1292 .storage = .{ .lazy_align = ty.ip_index },
1293 } })).toValue() },
12271294 },
12281295 };
12291296 max_align = @max(max_align, field_align);
......@@ -1232,8 +1299,8 @@ pub const Type = struct {
12321299 }
12331300
12341301 /// May capture a reference to `ty`.
1235 pub fn lazyAbiSize(ty: Type, mod: *Module, arena: Allocator) !Value {
1236 switch (try ty.abiSizeAdvanced(mod, .{ .lazy = arena })) {
1302 pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
1303 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
12371304 .val => |val| return val,
12381305 .scalar => |x| return mod.intValue(Type.comptime_int, x),
12391306 }
......@@ -1283,7 +1350,10 @@ pub const Type = struct {
12831350 .scalar => |elem_size| return .{ .scalar = len * elem_size },
12841351 .val => switch (strat) {
12851352 .sema, .eager => unreachable,
1286 .lazy => |arena| return .{ .val = try Value.Tag.lazy_size.create(arena, ty) },
1353 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1354 .ty = .comptime_int_type,
1355 .storage = .{ .lazy_size = ty.ip_index },
1356 } })).toValue() },
12871357 },
12881358 }
12891359 },
......@@ -1291,9 +1361,10 @@ pub const Type = struct {
12911361 const opt_sema = switch (strat) {
12921362 .sema => |sema| sema,
12931363 .eager => null,
1294 .lazy => |arena| return AbiSizeAdvanced{
1295 .val = try Value.Tag.lazy_size.create(arena, ty),
1296 },
1364 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1365 .ty = .comptime_int_type,
1366 .storage = .{ .lazy_size = ty.ip_index },
1367 } })).toValue() },
12971368 };
12981369 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
12991370 const elem_bits = @intCast(u32, elem_bits_u64);
......@@ -1301,9 +1372,10 @@ pub const Type = struct {
13011372 const total_bytes = (total_bits + 7) / 8;
13021373 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
13031374 .scalar => |x| x,
1304 .val => return AbiSizeAdvanced{
1305 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),
1306 },
1375 .val => return .{ .val = (try mod.intern(.{ .int = .{
1376 .ty = .comptime_int_type,
1377 .storage = .{ .lazy_size = ty.ip_index },
1378 } })).toValue() },
13071379 };
13081380 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
13091381 return AbiSizeAdvanced{ .scalar = result };
......@@ -1320,7 +1392,10 @@ pub const Type = struct {
13201392 // in abiAlignmentAdvanced.
13211393 const code_size = abiSize(Type.anyerror, mod);
13221394 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1323 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
1395 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1396 .ty = .comptime_int_type,
1397 .storage = .{ .lazy_size = ty.ip_index },
1398 } })).toValue() },
13241399 else => |e| return e,
13251400 })) {
13261401 // Same as anyerror.
......@@ -1333,7 +1408,10 @@ pub const Type = struct {
13331408 .val => switch (strat) {
13341409 .sema => unreachable,
13351410 .eager => unreachable,
1336 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
1411 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1412 .ty = .comptime_int_type,
1413 .storage = .{ .lazy_size = ty.ip_index },
1414 } })).toValue() },
13371415 },
13381416 };
13391417
......@@ -1420,11 +1498,10 @@ pub const Type = struct {
14201498
14211499 switch (strat) {
14221500 .sema => |sema| try sema.resolveTypeLayout(ty),
1423 .lazy => |arena| {
1424 if (!struct_obj.haveLayout()) {
1425 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
1426 }
1427 },
1501 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1502 .ty = .comptime_int_type,
1503 .storage = .{ .lazy_size = ty.ip_index },
1504 } })).toValue() },
14281505 .eager => {},
14291506 }
14301507 assert(struct_obj.haveLayout());
......@@ -1433,12 +1510,13 @@ pub const Type = struct {
14331510 else => {
14341511 switch (strat) {
14351512 .sema => |sema| try sema.resolveTypeLayout(ty),
1436 .lazy => |arena| {
1513 .lazy => {
14371514 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
14381515 return AbiSizeAdvanced{ .scalar = 0 };
1439 if (!struct_obj.haveLayout()) {
1440 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
1441 }
1516 if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1517 .ty = .comptime_int_type,
1518 .storage = .{ .lazy_size = ty.ip_index },
1519 } })).toValue() };
14421520 },
14431521 .eager => {},
14441522 }
......@@ -1469,16 +1547,23 @@ pub const Type = struct {
14691547 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
14701548
14711549 // values, not types
1472 .undef => unreachable,
1473 .un => unreachable,
1474 .simple_value => unreachable,
1475 .extern_func => unreachable,
1476 .int => unreachable,
1477 .float => unreachable,
1478 .ptr => unreachable,
1479 .opt => unreachable,
1480 .enum_tag => unreachable,
1481 .aggregate => unreachable,
1550 .undef,
1551 .runtime_value,
1552 .simple_value,
1553 .variable,
1554 .extern_func,
1555 .func,
1556 .int,
1557 .err,
1558 .error_union,
1559 .enum_literal,
1560 .enum_tag,
1561 .float,
1562 .ptr,
1563 .opt,
1564 .aggregate,
1565 .un,
1566 => unreachable,
14821567 },
14831568 }
14841569 }
......@@ -1492,11 +1577,10 @@ pub const Type = struct {
14921577 ) Module.CompileError!AbiSizeAdvanced {
14931578 switch (strat) {
14941579 .sema => |sema| try sema.resolveTypeLayout(ty),
1495 .lazy => |arena| {
1496 if (!union_obj.haveLayout()) {
1497 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
1498 }
1499 },
1580 .lazy => if (!union_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1581 .ty = .comptime_int_type,
1582 .storage = .{ .lazy_size = ty.ip_index },
1583 } })).toValue() },
15001584 .eager => {},
15011585 }
15021586 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) };
......@@ -1514,7 +1598,10 @@ pub const Type = struct {
15141598 }
15151599
15161600 if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1517 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
1601 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1602 .ty = .comptime_int_type,
1603 .storage = .{ .lazy_size = ty.ip_index },
1604 } })).toValue() },
15181605 else => |e| return e,
15191606 })) return AbiSizeAdvanced{ .scalar = 1 };
15201607
......@@ -1527,7 +1614,10 @@ pub const Type = struct {
15271614 .val => switch (strat) {
15281615 .sema => unreachable,
15291616 .eager => unreachable,
1530 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
1617 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1618 .ty = .comptime_int_type,
1619 .storage = .{ .lazy_size = ty.ip_index },
1620 } })).toValue() },
15311621 },
15321622 };
15331623
......@@ -1690,16 +1780,23 @@ pub const Type = struct {
16901780 .enum_type => |enum_type| return bitSizeAdvanced(enum_type.tag_ty.toType(), mod, opt_sema),
16911781
16921782 // values, not types
1693 .undef => unreachable,
1694 .un => unreachable,
1695 .simple_value => unreachable,
1696 .extern_func => unreachable,
1697 .int => unreachable,
1698 .float => unreachable,
1699 .ptr => unreachable,
1700 .opt => unreachable,
1701 .enum_tag => unreachable,
1702 .aggregate => unreachable,
1783 .undef,
1784 .runtime_value,
1785 .simple_value,
1786 .variable,
1787 .extern_func,
1788 .func,
1789 .int,
1790 .err,
1791 .error_union,
1792 .enum_literal,
1793 .enum_tag,
1794 .float,
1795 .ptr,
1796 .opt,
1797 .aggregate,
1798 .un,
1799 => unreachable,
17031800 }
17041801 }
17051802
......@@ -2270,16 +2367,23 @@ pub const Type = struct {
22702367 .opaque_type => unreachable,
22712368
22722369 // values, not types
2273 .undef => unreachable,
2274 .un => unreachable,
2275 .simple_value => unreachable,
2276 .extern_func => unreachable,
2277 .int => unreachable,
2278 .float => unreachable,
2279 .ptr => unreachable,
2280 .opt => unreachable,
2281 .enum_tag => unreachable,
2282 .aggregate => unreachable,
2370 .undef,
2371 .runtime_value,
2372 .simple_value,
2373 .variable,
2374 .extern_func,
2375 .func,
2376 .int,
2377 .err,
2378 .error_union,
2379 .enum_literal,
2380 .enum_tag,
2381 .float,
2382 .ptr,
2383 .opt,
2384 .aggregate,
2385 .un,
2386 => unreachable,
22832387 },
22842388 };
22852389 }
......@@ -2443,16 +2547,17 @@ pub const Type = struct {
24432547 .inferred_error_set_type,
24442548 => return null,
24452549
2446 .array_type => |array_type| {
2447 if (array_type.len == 0)
2448 return Value.initTag(.empty_array);
2449 if ((try array_type.child.toType().onePossibleValue(mod)) != null)
2450 return Value.initTag(.the_only_possible_value);
2451 return null;
2452 },
2453 .vector_type => |vector_type| {
2454 if (vector_type.len == 0) return Value.initTag(.empty_array);
2455 if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;
2550 inline .array_type, .vector_type => |seq_type| {
2551 if (seq_type.len == 0) return (try mod.intern(.{ .aggregate = .{
2552 .ty = ty.ip_index,
2553 .storage = .{ .elems = &.{} },
2554 } })).toValue();
2555 if (try seq_type.child.toType().onePossibleValue(mod)) |opv| {
2556 return (try mod.intern(.{ .aggregate = .{
2557 .ty = ty.ip_index,
2558 .storage = .{ .repeated_elem = opv.ip_index },
2559 } })).toValue();
2560 }
24562561 return null;
24572562 },
24582563 .opt_type => |child| {
......@@ -2595,16 +2700,23 @@ pub const Type = struct {
25952700 },
25962701
25972702 // values, not types
2598 .undef => unreachable,
2599 .un => unreachable,
2600 .simple_value => unreachable,
2601 .extern_func => unreachable,
2602 .int => unreachable,
2603 .float => unreachable,
2604 .ptr => unreachable,
2605 .opt => unreachable,
2606 .enum_tag => unreachable,
2607 .aggregate => unreachable,
2703 .undef,
2704 .runtime_value,
2705 .simple_value,
2706 .variable,
2707 .extern_func,
2708 .func,
2709 .int,
2710 .err,
2711 .error_union,
2712 .enum_literal,
2713 .enum_tag,
2714 .float,
2715 .ptr,
2716 .opt,
2717 .aggregate,
2718 .un,
2719 => unreachable,
26082720 },
26092721 };
26102722 }
......@@ -2733,16 +2845,23 @@ pub const Type = struct {
27332845 .enum_type => |enum_type| enum_type.tag_ty.toType().comptimeOnly(mod),
27342846
27352847 // values, not types
2736 .undef => unreachable,
2737 .un => unreachable,
2738 .simple_value => unreachable,
2739 .extern_func => unreachable,
2740 .int => unreachable,
2741 .float => unreachable,
2742 .ptr => unreachable,
2743 .opt => unreachable,
2744 .enum_tag => unreachable,
2745 .aggregate => unreachable,
2848 .undef,
2849 .runtime_value,
2850 .simple_value,
2851 .variable,
2852 .extern_func,
2853 .func,
2854 .int,
2855 .err,
2856 .error_union,
2857 .enum_literal,
2858 .enum_tag,
2859 .float,
2860 .ptr,
2861 .opt,
2862 .aggregate,
2863 .un,
2864 => unreachable,
27462865 },
27472866 };
27482867 }
......@@ -2802,13 +2921,12 @@ pub const Type = struct {
28022921 }
28032922
28042923 // Works for vectors and vectors of integers.
2805 pub fn minInt(ty: Type, arena: Allocator, mod: *Module) !Value {
2924 pub fn minInt(ty: Type, mod: *Module) !Value {
28062925 const scalar = try minIntScalar(ty.scalarType(mod), mod);
2807 if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) {
2808 return Value.Tag.repeated.create(arena, scalar);
2809 } else {
2810 return scalar;
2811 }
2926 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2927 .ty = ty.ip_index,
2928 .storage = .{ .repeated_elem = scalar.ip_index },
2929 } })).toValue() else scalar;
28122930 }
28132931
28142932 /// Asserts that the type is an integer.
......@@ -2832,13 +2950,12 @@ pub const Type = struct {
28322950
28332951 // Works for vectors and vectors of integers.
28342952 /// The returned Value will have type dest_ty.
2835 pub fn maxInt(ty: Type, arena: Allocator, mod: *Module, dest_ty: Type) !Value {
2953 pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
28362954 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty);
2837 if (ty.zigTypeTag(mod) == .Vector and scalar.tag() != .the_only_possible_value) {
2838 return Value.Tag.repeated.create(arena, scalar);
2839 } else {
2840 return scalar;
2841 }
2955 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2956 .ty = ty.ip_index,
2957 .storage = .{ .repeated_elem = scalar.ip_index },
2958 } })).toValue() else scalar;
28422959 }
28432960
28442961 /// The returned Value will have type dest_ty.
......@@ -3386,12 +3503,12 @@ pub const Type = struct {
33863503 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
33873504 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
33883505
3389 pub const const_slice_u8: Type = .{ .ip_index = .const_slice_u8_type };
3506 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
33903507 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
33913508 pub const single_const_pointer_to_comptime_int: Type = .{
33923509 .ip_index = .single_const_pointer_to_comptime_int_type,
33933510 };
3394 pub const const_slice_u8_sentinel_0: Type = .{ .ip_index = .const_slice_u8_sentinel_0_type };
3511 pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
33953512 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
33963513
33973514 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
src/value.zig+422-1353
......@@ -33,64 +33,12 @@ pub const Value = struct {
3333 // Keep in sync with tools/stage2_pretty_printers_common.py
3434 pub const Tag = enum(usize) {
3535 // The first section of this enum are tags that require no payload.
36 /// The only possible value for a particular type, which is stored externally.
37 the_only_possible_value,
38
39 empty_array, // See last_no_payload_tag below.
4036 // After this, the tag requires a payload.
4137
42 function,
43 extern_fn,
44 /// A comptime-known pointer can point to the address of a global
45 /// variable. The child element value in this case will have this tag.
46 variable,
47 /// A wrapper for values which are comptime-known but should
48 /// semantically be runtime-known.
49 runtime_value,
50 /// Represents a pointer to a Decl.
51 /// When machine codegen backend sees this, it must set the Decl's `alive` field to true.
52 decl_ref,
53 /// Pointer to a Decl, but allows comptime code to mutate the Decl's Value.
54 /// This Tag will never be seen by machine codegen backends. It is changed into a
55 /// `decl_ref` when a comptime variable goes out of scope.
56 decl_ref_mut,
57 /// Behaves like `decl_ref_mut` but validates that the stored value matches the field value.
58 comptime_field_ptr,
59 /// Pointer to a specific element of an array, vector or slice.
60 elem_ptr,
61 /// Pointer to a specific field of a struct or union.
62 field_ptr,
6338 /// A slice of u8 whose memory is managed externally.
6439 bytes,
6540 /// Similar to bytes however it stores an index relative to `Module.string_literal_bytes`.
6641 str_lit,
67 /// This value is repeated some number of times. The amount of times to repeat
68 /// is stored externally.
69 repeated,
70 /// An array with length 0 but it has a sentinel.
71 empty_array_sentinel,
72 /// Pointer and length as sub `Value` objects.
73 slice,
74 enum_literal,
75 @"error",
76 /// When the type is error union:
77 /// * If the tag is `.@"error"`, the error union is an error.
78 /// * If the tag is `.eu_payload`, the error union is a payload.
79 /// * A nested error such as `anyerror!(anyerror!T)` in which the the outer error union
80 /// is non-error, but the inner error union is an error, is represented as
81 /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.
82 eu_payload,
83 /// A pointer to the payload of an error union, based on a pointer to an error union.
84 eu_payload_ptr,
85 /// When the type is optional:
86 /// * If the tag is `.null_value`, the optional is null.
87 /// * If the tag is `.opt_payload`, the optional is a payload.
88 /// * A nested optional such as `??T` in which the the outer optional
89 /// is non-null, but the inner optional is null, is represented as
90 /// a tag of `.opt_payload`, with a sub-tag of `.null_value`.
91 opt_payload,
92 /// A pointer to the payload of an optional, based on a pointer to an optional.
93 opt_payload_ptr,
9442 /// An instance of a struct, array, or vector.
9543 /// Each element/field stored as a `Value`.
9644 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
......@@ -104,57 +52,19 @@ pub const Value = struct {
10452 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
10553 /// instructions for comptime code.
10654 inferred_alloc_comptime,
107 /// The ABI alignment of the payload type.
108 lazy_align,
109 /// The ABI size of the payload type.
110 lazy_size,
11155
112 pub const last_no_payload_tag = Tag.empty_array;
113 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
56 pub const no_payload_count = 0;
11457
11558 pub fn Type(comptime t: Tag) type {
11659 return switch (t) {
117 .the_only_possible_value,
118 .empty_array,
119 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
120
121 .extern_fn => Payload.ExternFn,
122
123 .decl_ref => Payload.Decl,
124
125 .repeated,
126 .eu_payload,
127 .opt_payload,
128 .empty_array_sentinel,
129 .runtime_value,
130 => Payload.SubValue,
131
132 .eu_payload_ptr,
133 .opt_payload_ptr,
134 => Payload.PayloadPtr,
135
136 .bytes,
137 .enum_literal,
138 => Payload.Bytes,
60 .bytes => Payload.Bytes,
13961
14062 .str_lit => Payload.StrLit,
141 .slice => Payload.Slice,
142
143 .lazy_align,
144 .lazy_size,
145 => Payload.Ty,
146
147 .function => Payload.Function,
148 .variable => Payload.Variable,
149 .decl_ref_mut => Payload.DeclRefMut,
150 .elem_ptr => Payload.ElemPtr,
151 .field_ptr => Payload.FieldPtr,
152 .@"error" => Payload.Error,
63
15364 .inferred_alloc => Payload.InferredAlloc,
15465 .inferred_alloc_comptime => Payload.InferredAllocComptime,
15566 .aggregate => Payload.Aggregate,
15667 .@"union" => Payload.Union,
157 .comptime_field_ptr => Payload.ComptimeFieldPtr,
15868 };
15969 }
16070
......@@ -249,91 +159,6 @@ pub const Value = struct {
249159 .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough },
250160 };
251161 } else switch (self.legacy.ptr_otherwise.tag) {
252 .the_only_possible_value,
253 .empty_array,
254 => unreachable,
255
256 .lazy_align, .lazy_size => {
257 const payload = self.cast(Payload.Ty).?;
258 const new_payload = try arena.create(Payload.Ty);
259 new_payload.* = .{
260 .base = payload.base,
261 .data = payload.data,
262 };
263 return Value{
264 .ip_index = .none,
265 .legacy = .{ .ptr_otherwise = &new_payload.base },
266 };
267 },
268 .function => return self.copyPayloadShallow(arena, Payload.Function),
269 .extern_fn => return self.copyPayloadShallow(arena, Payload.ExternFn),
270 .variable => return self.copyPayloadShallow(arena, Payload.Variable),
271 .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),
272 .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),
273 .eu_payload_ptr,
274 .opt_payload_ptr,
275 => {
276 const payload = self.cast(Payload.PayloadPtr).?;
277 const new_payload = try arena.create(Payload.PayloadPtr);
278 new_payload.* = .{
279 .base = payload.base,
280 .data = .{
281 .container_ptr = try payload.data.container_ptr.copy(arena),
282 .container_ty = payload.data.container_ty,
283 },
284 };
285 return Value{
286 .ip_index = .none,
287 .legacy = .{ .ptr_otherwise = &new_payload.base },
288 };
289 },
290 .comptime_field_ptr => {
291 const payload = self.cast(Payload.ComptimeFieldPtr).?;
292 const new_payload = try arena.create(Payload.ComptimeFieldPtr);
293 new_payload.* = .{
294 .base = payload.base,
295 .data = .{
296 .field_val = try payload.data.field_val.copy(arena),
297 .field_ty = payload.data.field_ty,
298 },
299 };
300 return Value{
301 .ip_index = .none,
302 .legacy = .{ .ptr_otherwise = &new_payload.base },
303 };
304 },
305 .elem_ptr => {
306 const payload = self.castTag(.elem_ptr).?;
307 const new_payload = try arena.create(Payload.ElemPtr);
308 new_payload.* = .{
309 .base = payload.base,
310 .data = .{
311 .array_ptr = try payload.data.array_ptr.copy(arena),
312 .elem_ty = payload.data.elem_ty,
313 .index = payload.data.index,
314 },
315 };
316 return Value{
317 .ip_index = .none,
318 .legacy = .{ .ptr_otherwise = &new_payload.base },
319 };
320 },
321 .field_ptr => {
322 const payload = self.castTag(.field_ptr).?;
323 const new_payload = try arena.create(Payload.FieldPtr);
324 new_payload.* = .{
325 .base = payload.base,
326 .data = .{
327 .container_ptr = try payload.data.container_ptr.copy(arena),
328 .container_ty = payload.data.container_ty,
329 .field_index = payload.data.field_index,
330 },
331 };
332 return Value{
333 .ip_index = .none,
334 .legacy = .{ .ptr_otherwise = &new_payload.base },
335 };
336 },
337162 .bytes => {
338163 const bytes = self.castTag(.bytes).?.data;
339164 const new_payload = try arena.create(Payload.Bytes);
......@@ -347,52 +172,6 @@ pub const Value = struct {
347172 };
348173 },
349174 .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit),
350 .repeated,
351 .eu_payload,
352 .opt_payload,
353 .empty_array_sentinel,
354 .runtime_value,
355 => {
356 const payload = self.cast(Payload.SubValue).?;
357 const new_payload = try arena.create(Payload.SubValue);
358 new_payload.* = .{
359 .base = payload.base,
360 .data = try payload.data.copy(arena),
361 };
362 return Value{
363 .ip_index = .none,
364 .legacy = .{ .ptr_otherwise = &new_payload.base },
365 };
366 },
367 .slice => {
368 const payload = self.castTag(.slice).?;
369 const new_payload = try arena.create(Payload.Slice);
370 new_payload.* = .{
371 .base = payload.base,
372 .data = .{
373 .ptr = try payload.data.ptr.copy(arena),
374 .len = try payload.data.len.copy(arena),
375 },
376 };
377 return Value{
378 .ip_index = .none,
379 .legacy = .{ .ptr_otherwise = &new_payload.base },
380 };
381 },
382 .enum_literal => {
383 const payload = self.castTag(.enum_literal).?;
384 const new_payload = try arena.create(Payload.Bytes);
385 new_payload.* = .{
386 .base = payload.base,
387 .data = try arena.dupe(u8, payload.data),
388 };
389 return Value{
390 .ip_index = .none,
391 .legacy = .{ .ptr_otherwise = &new_payload.base },
392 };
393 },
394 .@"error" => return self.copyPayloadShallow(arena, Payload.Error),
395
396175 .aggregate => {
397176 const payload = self.castTag(.aggregate).?;
398177 const new_payload = try arena.create(Payload.Aggregate);
......@@ -453,7 +232,7 @@ pub const Value = struct {
453232 pub fn dump(
454233 start_val: Value,
455234 comptime fmt: []const u8,
456 options: std.fmt.FormatOptions,
235 _: std.fmt.FormatOptions,
457236 out_stream: anytype,
458237 ) !void {
459238 comptime assert(fmt.len == 0);
......@@ -469,44 +248,6 @@ pub const Value = struct {
469248 .@"union" => {
470249 return out_stream.writeAll("(union value)");
471250 },
472 .the_only_possible_value => return out_stream.writeAll("(the only possible value)"),
473 .lazy_align => {
474 try out_stream.writeAll("@alignOf(");
475 try val.castTag(.lazy_align).?.data.dump("", options, out_stream);
476 return try out_stream.writeAll(")");
477 },
478 .lazy_size => {
479 try out_stream.writeAll("@sizeOf(");
480 try val.castTag(.lazy_size).?.data.dump("", options, out_stream);
481 return try out_stream.writeAll(")");
482 },
483 .runtime_value => return out_stream.writeAll("[runtime value]"),
484 .function => return out_stream.print("(function decl={d})", .{val.castTag(.function).?.data.owner_decl}),
485 .extern_fn => return out_stream.writeAll("(extern function)"),
486 .variable => return out_stream.writeAll("(variable)"),
487 .decl_ref_mut => {
488 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
489 return out_stream.print("(decl_ref_mut {d})", .{decl_index});
490 },
491 .decl_ref => {
492 const decl_index = val.castTag(.decl_ref).?.data;
493 return out_stream.print("(decl_ref {d})", .{decl_index});
494 },
495 .comptime_field_ptr => {
496 return out_stream.writeAll("(comptime_field_ptr)");
497 },
498 .elem_ptr => {
499 const elem_ptr = val.castTag(.elem_ptr).?.data;
500 try out_stream.print("&[{}] ", .{elem_ptr.index});
501 val = elem_ptr.array_ptr;
502 },
503 .field_ptr => {
504 const field_ptr = val.castTag(.field_ptr).?.data;
505 try out_stream.print("fieldptr({d}) ", .{field_ptr.field_index});
506 val = field_ptr.container_ptr;
507 },
508 .empty_array => return out_stream.writeAll(".{}"),
509 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}),
510251 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
511252 .str_lit => {
512253 const str_lit = val.castTag(.str_lit).?.data;
......@@ -514,31 +255,8 @@ pub const Value = struct {
514255 str_lit.index, str_lit.len,
515256 });
516257 },
517 .repeated => {
518 try out_stream.writeAll("(repeated) ");
519 val = val.castTag(.repeated).?.data;
520 },
521 .empty_array_sentinel => return out_stream.writeAll("(empty array with sentinel)"),
522 .slice => return out_stream.writeAll("(slice)"),
523 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
524 .eu_payload => {
525 try out_stream.writeAll("(eu_payload) ");
526 val = val.castTag(.eu_payload).?.data;
527 },
528 .opt_payload => {
529 try out_stream.writeAll("(opt_payload) ");
530 val = val.castTag(.opt_payload).?.data;
531 },
532258 .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
533259 .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
534 .eu_payload_ptr => {
535 try out_stream.writeAll("(eu_payload_ptr)");
536 val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
537 },
538 .opt_payload_ptr => {
539 try out_stream.writeAll("(opt_payload_ptr)");
540 val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
541 },
542260 };
543261 }
544262
......@@ -569,30 +287,23 @@ pub const Value = struct {
569287 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
570288 return allocator.dupe(u8, bytes);
571289 },
572 .enum_literal => return allocator.dupe(u8, val.castTag(.enum_literal).?.data),
573 .repeated => {
574 const byte = @intCast(u8, val.castTag(.repeated).?.data.toUnsignedInt(mod));
575 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen(mod)));
576 @memset(result, byte);
577 return result;
578 },
579 .decl_ref => {
580 const decl_index = val.castTag(.decl_ref).?.data;
581 const decl = mod.declPtr(decl_index);
582 const decl_val = try decl.value();
583 return decl_val.toAllocatedBytes(decl.ty, allocator, mod);
584 },
585 .the_only_possible_value => return &[_]u8{},
586 .slice => {
587 const slice = val.castTag(.slice).?.data;
588 return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(mod), allocator, mod);
589 },
590290 else => return arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),
591291 },
592 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
292 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
293 .enum_literal => |enum_literal| allocator.dupe(u8, mod.intern_pool.stringToSlice(enum_literal)),
593294 .ptr => |ptr| switch (ptr.len) {
594295 .none => unreachable,
595 else => return arrayToAllocatedBytes(val, ptr.len.toValue().toUnsignedInt(mod), allocator, mod),
296 else => arrayToAllocatedBytes(val, ptr.len.toValue().toUnsignedInt(mod), allocator, mod),
297 },
298 .aggregate => |aggregate| switch (aggregate.storage) {
299 .bytes => |bytes| try allocator.dupe(u8, bytes),
300 .elems => arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),
301 .repeated_elem => |elem| {
302 const byte = @intCast(u8, elem.toValue().toUnsignedInt(mod));
303 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen(mod)));
304 @memset(result, byte);
305 return result;
306 },
596307 },
597308 else => unreachable,
598309 },
......@@ -611,29 +322,6 @@ pub const Value = struct {
611322 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
612323 if (val.ip_index != .none) return mod.intern_pool.getCoerced(mod.gpa, val.ip_index, ty.ip_index);
613324 switch (val.tag()) {
614 .elem_ptr => {
615 const pl = val.castTag(.elem_ptr).?.data;
616 return mod.intern(.{ .ptr = .{
617 .ty = ty.ip_index,
618 .addr = .{ .elem = .{
619 .base = pl.array_ptr.ip_index,
620 .index = pl.index,
621 } },
622 } });
623 },
624 .slice => {
625 const pl = val.castTag(.slice).?.data;
626 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
627 return mod.intern(.{ .ptr = .{
628 .ty = ty.ip_index,
629 .addr = mod.intern_pool.indexToKey(ptr).ptr.addr,
630 .len = try pl.len.intern(Type.usize, mod),
631 } });
632 },
633 .opt_payload => return mod.intern(.{ .opt = .{
634 .ty = ty.ip_index,
635 .val = try val.castTag(.opt_payload).?.data.intern(ty.childType(mod), mod),
636 } }),
637325 .aggregate => {
638326 const old_elems = val.castTag(.aggregate).?.data;
639327 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
......@@ -651,13 +339,6 @@ pub const Value = struct {
651339 .storage = .{ .elems = new_elems },
652340 } });
653341 },
654 .repeated => return mod.intern(.{ .aggregate = .{
655 .ty = ty.ip_index,
656 .storage = .{ .repeated_elem = try val.castTag(.repeated).?.data.intern(
657 ty.structFieldType(0, mod),
658 mod,
659 ) },
660 } }),
661342 .@"union" => {
662343 const pl = val.castTag(.@"union").?.data;
663344 return mod.intern(.{ .un = .{
......@@ -679,7 +360,6 @@ pub const Value = struct {
679360 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue();
680361 return Tag.aggregate.create(arena, new_elems);
681362 },
682 .repeated_elem => |elem| return Tag.repeated.create(arena, elem.toValue()),
683363 },
684364 else => return val,
685365 }
......@@ -698,31 +378,21 @@ pub const Value = struct {
698378 pub fn enumToInt(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
699379 const ip = &mod.intern_pool;
700380 switch (val.ip_index) {
701 .none => {
702 const field_index = switch (val.tag()) {
703 .the_only_possible_value => blk: {
704 assert(ty.enumFieldCount(mod) == 1);
705 break :blk 0;
706 },
707 .enum_literal => i: {
708 const name = val.castTag(.enum_literal).?.data;
709 break :i ty.enumFieldIndex(name, mod).?;
710 },
711 else => unreachable,
712 };
713 return switch (ip.indexToKey(ty.ip_index)) {
714 // Assume it is already an integer and return it directly.
715 .simple_type, .int_type => val,
716 .enum_type => |enum_type| if (enum_type.values.len != 0)
717 enum_type.values[field_index].toValue()
718 else // Field index and integer values are the same.
719 mod.intValue(enum_type.tag_ty.toType(), field_index),
720 else => unreachable,
721 };
722 },
723381 else => return switch (ip.indexToKey(ip.typeOf(val.ip_index))) {
724382 // Assume it is already an integer and return it directly.
725383 .simple_type, .int_type => val,
384 .enum_literal => |enum_literal| {
385 const field_index = ty.enumFieldIndex(ip.stringToSlice(enum_literal), mod).?;
386 return switch (ip.indexToKey(ty.ip_index)) {
387 // Assume it is already an integer and return it directly.
388 .simple_type, .int_type => val,
389 .enum_type => |enum_type| if (enum_type.values.len != 0)
390 enum_type.values[field_index].toValue()
391 else // Field index and integer values are the same.
392 mod.intValue(enum_type.tag_ty.toType(), field_index),
393 else => unreachable,
394 };
395 },
726396 .enum_type => |enum_type| (try ip.getCoerced(
727397 mod.gpa,
728398 val.ip_index,
......@@ -733,18 +403,12 @@ pub const Value = struct {
733403 }
734404 }
735405
736 pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 {
737 _ = ty; // TODO: remove this parameter now that we use InternPool
738
739 if (val.castTag(.enum_literal)) |payload| {
740 return payload.data;
741 }
742
406 pub fn tagName(val: Value, mod: *Module) []const u8 {
743407 const ip = &mod.intern_pool;
744
745408 const enum_tag = switch (ip.indexToKey(val.ip_index)) {
746409 .un => |un| ip.indexToKey(un.tag).enum_tag,
747410 .enum_tag => |x| x,
411 .enum_literal => |name| return ip.stringToSlice(name),
748412 else => unreachable,
749413 };
750414 const enum_type = ip.indexToKey(enum_tag.ty).enum_type;
......@@ -773,49 +437,61 @@ pub const Value = struct {
773437 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
774438 .undef => unreachable,
775439 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
776 .none => switch (val.tag()) {
777 .the_only_possible_value, // i0, u0
778 => BigIntMutable.init(&space.limbs, 0).toConst(),
779
780 .runtime_value => {
781 const sub_val = val.castTag(.runtime_value).?.data;
782 return sub_val.toBigIntAdvanced(space, mod, opt_sema);
783 },
784 .lazy_align => {
785 const ty = val.castTag(.lazy_align).?.data;
786 if (opt_sema) |sema| {
787 try sema.resolveTypeLayout(ty);
788 }
789 const x = ty.abiAlignment(mod);
790 return BigIntMutable.init(&space.limbs, x).toConst();
791 },
792 .lazy_size => {
793 const ty = val.castTag(.lazy_size).?.data;
794 if (opt_sema) |sema| {
795 try sema.resolveTypeLayout(ty);
796 }
797 const x = ty.abiSize(mod);
798 return BigIntMutable.init(&space.limbs, x).toConst();
440 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
441 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
442 .int => |int| switch (int.storage) {
443 .u64, .i64, .big_int => int.storage.toBigInt(space),
444 .lazy_align, .lazy_size => |ty| {
445 if (opt_sema) |sema| try sema.resolveTypeLayout(ty.toType());
446 const x = switch (int.storage) {
447 else => unreachable,
448 .lazy_align => ty.toType().abiAlignment(mod),
449 .lazy_size => ty.toType().abiSize(mod),
450 };
451 return BigIntMutable.init(&space.limbs, x).toConst();
452 },
799453 },
800
801 .elem_ptr => {
802 const elem_ptr = val.castTag(.elem_ptr).?.data;
803 const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(mod, opt_sema)).?;
804 const elem_size = elem_ptr.elem_ty.abiSize(mod);
805 const new_addr = array_addr + elem_size * elem_ptr.index;
806 return BigIntMutable.init(&space.limbs, new_addr).toConst();
454 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
455 .ptr => |ptr| switch (ptr.len) {
456 .none => switch (ptr.addr) {
457 .int => |int| int.toValue().toBigIntAdvanced(space, mod, opt_sema),
458 .elem => |elem| {
459 const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)).?;
460 const elem_size = ptr.ty.toType().elemType2(mod).abiSize(mod);
461 const new_addr = base_addr + elem.index * elem_size;
462 return BigIntMutable.init(&space.limbs, new_addr).toConst();
463 },
464 else => unreachable,
465 },
466 else => unreachable,
807467 },
808
809 else => unreachable,
810 },
811 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
812 .int => |int| int.storage.toBigInt(space),
813 .enum_tag => |enum_tag| mod.intern_pool.indexToKey(enum_tag.int).int.storage.toBigInt(space),
814468 else => unreachable,
815469 },
816470 };
817471 }
818472
473 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
474 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
475 }
476
477 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
478 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.ip_index) else .none;
479 }
480
481 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
482 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.ip_index)) {
483 .extern_func => |extern_func| extern_func,
484 else => null,
485 } else null;
486 }
487
488 pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {
489 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.ip_index)) {
490 .variable => |variable| variable,
491 else => null,
492 } else null;
493 }
494
819495 /// If the value fits in a u64, return it, otherwise null.
820496 /// Asserts not undefined.
821497 pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {
......@@ -825,42 +501,27 @@ pub const Value = struct {
825501 /// If the value fits in a u64, return it, otherwise null.
826502 /// Asserts not undefined.
827503 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
828 switch (val.ip_index) {
829 .bool_false => return 0,
830 .bool_true => return 1,
504 return switch (val.ip_index) {
505 .bool_false => 0,
506 .bool_true => 1,
831507 .undef => unreachable,
832 .none => switch (val.tag()) {
833 .the_only_possible_value, // i0, u0
834 => return 0,
835
836 .lazy_align => {
837 const ty = val.castTag(.lazy_align).?.data;
838 if (opt_sema) |sema| {
839 return (try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar;
840 } else {
841 return ty.abiAlignment(mod);
842 }
843 },
844 .lazy_size => {
845 const ty = val.castTag(.lazy_size).?.data;
846 if (opt_sema) |sema| {
847 return (try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar;
848 } else {
849 return ty.abiSize(mod);
850 }
851 },
852
853 else => return null,
854 },
855 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
508 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
856509 .int => |int| switch (int.storage) {
857510 .big_int => |big_int| big_int.to(u64) catch null,
858511 .u64 => |x| x,
859512 .i64 => |x| std.math.cast(u64, x),
513 .lazy_align => |ty| if (opt_sema) |sema|
514 (try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar
515 else
516 ty.toType().abiAlignment(mod),
517 .lazy_size => |ty| if (opt_sema) |sema|
518 (try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar
519 else
520 ty.toType().abiSize(mod),
860521 },
861522 else => null,
862523 },
863 }
524 };
864525 }
865526
866527 /// Asserts the value is an integer and it fits in a u64
......@@ -870,58 +531,40 @@ pub const Value = struct {
870531
871532 /// Asserts the value is an integer and it fits in a i64
872533 pub fn toSignedInt(val: Value, mod: *Module) i64 {
873 switch (val.ip_index) {
874 .bool_false => return 0,
875 .bool_true => return 1,
534 return switch (val.ip_index) {
535 .bool_false => 0,
536 .bool_true => 1,
876537 .undef => unreachable,
877 .none => switch (val.tag()) {
878 .the_only_possible_value, // i0, u0
879 => return 0,
880
881 .lazy_align => {
882 const ty = val.castTag(.lazy_align).?.data;
883 return @intCast(i64, ty.abiAlignment(mod));
884 },
885 .lazy_size => {
886 const ty = val.castTag(.lazy_size).?.data;
887 return @intCast(i64, ty.abiSize(mod));
888 },
889
890 else => unreachable,
891 },
892 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
538 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
893539 .int => |int| switch (int.storage) {
894540 .big_int => |big_int| big_int.to(i64) catch unreachable,
895541 .i64 => |x| x,
896542 .u64 => |x| @intCast(i64, x),
543 .lazy_align => |ty| @intCast(i64, ty.toType().abiAlignment(mod)),
544 .lazy_size => |ty| @intCast(i64, ty.toType().abiSize(mod)),
897545 },
898546 else => unreachable,
899547 },
900 }
548 };
901549 }
902550
903 pub fn toBool(val: Value, mod: *const Module) bool {
551 pub fn toBool(val: Value, _: *const Module) bool {
904552 return switch (val.ip_index) {
905553 .bool_true => true,
906554 .bool_false => false,
907 .none => unreachable,
908 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
909 .int => |int| switch (int.storage) {
910 .big_int => |big_int| !big_int.eqZero(),
911 inline .u64, .i64 => |x| x != 0,
912 },
913 else => unreachable,
914 },
555 else => unreachable,
915556 };
916557 }
917558
918 fn isDeclRef(val: Value) bool {
559 fn isDeclRef(val: Value, mod: *Module) bool {
919560 var check = val;
920 while (true) switch (check.tag()) {
921 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return true,
922 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
923 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
924 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
561 while (true) switch (mod.intern_pool.indexToKey(check.ip_index)) {
562 .ptr => |ptr| switch (ptr.addr) {
563 .decl, .mut_decl, .comptime_field => return true,
564 .eu_payload, .opt_payload => |index| check = index.toValue(),
565 .elem, .field => |base_index| check = base_index.base.toValue(),
566 else => return false,
567 },
925568 else => return false,
926569 };
927570 }
......@@ -953,24 +596,9 @@ pub const Value = struct {
953596 const bits = int_info.bits;
954597 const byte_count = (bits + 7) / 8;
955598
956 const int_val = try val.enumToInt(ty, mod);
957
958 if (byte_count <= @sizeOf(u64)) {
959 const ip_key = mod.intern_pool.indexToKey(int_val.ip_index);
960 const int: u64 = switch (ip_key.int.storage) {
961 .u64 => |x| x,
962 .i64 => |x| @bitCast(u64, x),
963 .big_int => unreachable,
964 };
965 for (buffer[0..byte_count], 0..) |_, i| switch (endian) {
966 .Little => buffer[i] = @truncate(u8, (int >> @intCast(u6, (8 * i)))),
967 .Big => buffer[byte_count - i - 1] = @truncate(u8, (int >> @intCast(u6, (8 * i)))),
968 };
969 } else {
970 var bigint_buffer: BigIntSpace = undefined;
971 const bigint = int_val.toBigInt(&bigint_buffer, mod);
972 bigint.writeTwosComplement(buffer[0..byte_count], endian);
973 }
599 var bigint_buffer: BigIntSpace = undefined;
600 const bigint = val.toBigInt(&bigint_buffer, mod);
601 bigint.writeTwosComplement(buffer[0..byte_count], endian);
974602 },
975603 .Float => switch (ty.floatBits(target)) {
976604 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16, mod)), endian),
......@@ -1016,7 +644,12 @@ pub const Value = struct {
1016644 .ErrorSet => {
1017645 // TODO revisit this when we have the concept of the error tag type
1018646 const Int = u16;
1019 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
647 const name = switch (mod.intern_pool.indexToKey(val.ip_index)) {
648 .err => |err| err.name,
649 .error_union => |error_union| error_union.val.err_name,
650 else => unreachable,
651 };
652 const int = mod.global_error_set.get(mod.intern_pool.stringToSlice(name)).?;
1020653 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
1021654 },
1022655 .Union => switch (ty.containerLayout(mod)) {
......@@ -1029,7 +662,7 @@ pub const Value = struct {
1029662 },
1030663 .Pointer => {
1031664 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
1032 if (val.isDeclRef()) return error.ReinterpretDeclRef;
665 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1033666 return val.writeToMemory(Type.usize, mod, buffer);
1034667 },
1035668 .Optional => {
......@@ -1141,14 +774,14 @@ pub const Value = struct {
1141774 .Packed => {
1142775 const field_index = ty.unionTagFieldIndex(val.unionTag(mod), mod);
1143776 const field_type = ty.unionFields(mod).values()[field_index.?].ty;
1144 const field_val = try val.fieldValue(field_type, mod, field_index.?);
777 const field_val = try val.fieldValue(mod, field_index.?);
1145778
1146779 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
1147780 },
1148781 },
1149782 .Pointer => {
1150783 assert(!ty.isSlice(mod)); // No well defined layout.
1151 if (val.isDeclRef()) return error.ReinterpretDeclRef;
784 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1152785 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
1153786 },
1154787 .Optional => {
......@@ -1262,13 +895,11 @@ pub const Value = struct {
1262895 // TODO revisit this when we have the concept of the error tag type
1263896 const Int = u16;
1264897 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
1265
1266 const payload = try arena.create(Value.Payload.Error);
1267 payload.* = .{
1268 .base = .{ .tag = .@"error" },
1269 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },
1270 };
1271 return Value.initPayload(&payload.base);
898 const name = mod.error_name_list.items[@intCast(usize, int)];
899 return (try mod.intern(.{ .err = .{
900 .ty = ty.ip_index,
901 .name = mod.intern_pool.getString(name).unwrap().?,
902 } })).toValue();
1272903 },
1273904 .Pointer => {
1274905 assert(!ty.isSlice(mod)); // No well defined layout.
......@@ -1383,7 +1014,7 @@ pub const Value = struct {
13831014 }
13841015
13851016 /// Asserts that the value is a float or an integer.
1386 pub fn toFloat(val: Value, comptime T: type, mod: *const Module) T {
1017 pub fn toFloat(val: Value, comptime T: type, mod: *Module) T {
13871018 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
13881019 .int => |int| switch (int.storage) {
13891020 .big_int => |big_int| @floatCast(T, bigIntToFloat(big_int.limbs, big_int.positive)),
......@@ -1393,6 +1024,8 @@ pub const Value = struct {
13931024 }
13941025 return @intToFloat(T, x);
13951026 },
1027 .lazy_align => |ty| @intToFloat(T, ty.toType().abiAlignment(mod)),
1028 .lazy_size => |ty| @intToFloat(T, ty.toType().abiSize(mod)),
13961029 },
13971030 .float => |float| switch (float.storage) {
13981031 inline else => |x| @floatCast(T, x),
......@@ -1421,89 +1054,24 @@ pub const Value = struct {
14211054 }
14221055
14231056 pub fn clz(val: Value, ty: Type, mod: *Module) u64 {
1424 const ty_bits = ty.intInfo(mod).bits;
1425 return switch (val.ip_index) {
1426 .bool_false => ty_bits,
1427 .bool_true => ty_bits - 1,
1428 .none => switch (val.tag()) {
1429 .the_only_possible_value => {
1430 assert(ty_bits == 0);
1431 return ty_bits;
1432 },
1433
1434 .lazy_align, .lazy_size => {
1435 var bigint_buf: BigIntSpace = undefined;
1436 const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable;
1437 return bigint.clz(ty_bits);
1438 },
1439
1440 else => unreachable,
1441 },
1442 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1443 .int => |int| switch (int.storage) {
1444 .big_int => |big_int| big_int.clz(ty_bits),
1445 .u64 => |x| @clz(x) + ty_bits - 64,
1446 .i64 => @panic("TODO implement i64 Value clz"),
1447 },
1448 else => unreachable,
1449 },
1450 };
1057 var bigint_buf: BigIntSpace = undefined;
1058 const bigint = val.toBigInt(&bigint_buf, mod);
1059 return bigint.clz(ty.intInfo(mod).bits);
14511060 }
14521061
1453 pub fn ctz(val: Value, ty: Type, mod: *Module) u64 {
1454 const ty_bits = ty.intInfo(mod).bits;
1455 return switch (val.ip_index) {
1456 .bool_false => ty_bits,
1457 .bool_true => 0,
1458 .none => switch (val.tag()) {
1459 .the_only_possible_value => {
1460 assert(ty_bits == 0);
1461 return ty_bits;
1462 },
1463
1464 .lazy_align, .lazy_size => {
1465 var bigint_buf: BigIntSpace = undefined;
1466 const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable;
1467 return bigint.ctz();
1468 },
1469
1470 else => unreachable,
1471 },
1472 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1473 .int => |int| switch (int.storage) {
1474 .big_int => |big_int| big_int.ctz(),
1475 .u64 => |x| {
1476 const big = @ctz(x);
1477 return if (big == 64) ty_bits else big;
1478 },
1479 .i64 => @panic("TODO implement i64 Value ctz"),
1480 },
1481 else => unreachable,
1482 },
1483 };
1062 pub fn ctz(val: Value, _: Type, mod: *Module) u64 {
1063 var bigint_buf: BigIntSpace = undefined;
1064 const bigint = val.toBigInt(&bigint_buf, mod);
1065 return bigint.ctz();
14841066 }
14851067
14861068 pub fn popCount(val: Value, ty: Type, mod: *Module) u64 {
1487 assert(!val.isUndef(mod));
1488 switch (val.ip_index) {
1489 .bool_false => return 0,
1490 .bool_true => return 1,
1491 .none => unreachable,
1492 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1493 .int => |int| {
1494 const info = ty.intInfo(mod);
1495 var buffer: Value.BigIntSpace = undefined;
1496 const big_int = int.storage.toBigInt(&buffer);
1497 return @intCast(u64, big_int.popCount(info.bits));
1498 },
1499 else => unreachable,
1500 },
1501 }
1069 var bigint_buf: BigIntSpace = undefined;
1070 const bigint = val.toBigInt(&bigint_buf, mod);
1071 return @intCast(u64, bigint.popCount(ty.intInfo(mod).bits));
15021072 }
15031073
15041074 pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1505 assert(!val.isUndef(mod));
1506
15071075 const info = ty.intInfo(mod);
15081076
15091077 var buffer: Value.BigIntSpace = undefined;
......@@ -1520,8 +1088,6 @@ pub const Value = struct {
15201088 }
15211089
15221090 pub fn byteSwap(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1523 assert(!val.isUndef(mod));
1524
15251091 const info = ty.intInfo(mod);
15261092
15271093 // Bit count must be evenly divisible by 8
......@@ -1543,41 +1109,9 @@ pub const Value = struct {
15431109 /// Asserts the value is an integer and not undefined.
15441110 /// Returns the number of bits the value requires to represent stored in twos complement form.
15451111 pub fn intBitCountTwosComp(self: Value, mod: *Module) usize {
1546 const target = mod.getTarget();
1547 return switch (self.ip_index) {
1548 .bool_false => 0,
1549 .bool_true => 1,
1550 .none => switch (self.tag()) {
1551 .the_only_possible_value => 0,
1552
1553 .decl_ref_mut,
1554 .comptime_field_ptr,
1555 .extern_fn,
1556 .decl_ref,
1557 .function,
1558 .variable,
1559 .eu_payload_ptr,
1560 .opt_payload_ptr,
1561 => target.ptrBitWidth(),
1562
1563 else => {
1564 var buffer: BigIntSpace = undefined;
1565 return self.toBigInt(&buffer, mod).bitCountTwosComp();
1566 },
1567 },
1568 else => switch (mod.intern_pool.indexToKey(self.ip_index)) {
1569 .int => |int| switch (int.storage) {
1570 .big_int => |big_int| big_int.bitCountTwosComp(),
1571 .u64 => |x| if (x == 0) 0 else @intCast(usize, std.math.log2(x) + 1),
1572 .i64 => {
1573 var buffer: Value.BigIntSpace = undefined;
1574 const big_int = int.storage.toBigInt(&buffer);
1575 return big_int.bitCountTwosComp();
1576 },
1577 },
1578 else => unreachable,
1579 },
1580 };
1112 var buffer: BigIntSpace = undefined;
1113 const big_int = self.toBigInt(&buffer, mod);
1114 return big_int.bitCountTwosComp();
15811115 }
15821116
15831117 /// Converts an integer or a float to a float. May result in a loss of information.
......@@ -1616,84 +1150,39 @@ pub const Value = struct {
16161150 mod: *Module,
16171151 opt_sema: ?*Sema,
16181152 ) Module.CompileError!std.math.Order {
1619 switch (lhs.ip_index) {
1620 .bool_false => return .eq,
1621 .bool_true => return .gt,
1622 .none => return switch (lhs.tag()) {
1623 .the_only_possible_value => .eq,
1624
1625 .decl_ref,
1626 .decl_ref_mut,
1627 .comptime_field_ptr,
1628 .extern_fn,
1629 .function,
1630 .variable,
1631 => .gt,
1632
1633 .runtime_value => {
1634 // This is needed to correctly handle hashing the value.
1635 // Checks in Sema should prevent direct comparisons from reaching here.
1636 const val = lhs.castTag(.runtime_value).?.data;
1637 return val.orderAgainstZeroAdvanced(mod, opt_sema);
1638 },
1639
1640 .lazy_align => {
1641 const ty = lhs.castTag(.lazy_align).?.data;
1642 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
1643 if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1644 error.NeedLazy => unreachable,
1645 else => |e| return e,
1646 }) {
1647 return .gt;
1648 } else {
1649 return .eq;
1650 }
1651 },
1652 .lazy_size => {
1653 const ty = lhs.castTag(.lazy_size).?.data;
1654 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
1655 if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1656 error.NeedLazy => unreachable,
1657 else => |e| return e,
1658 }) {
1659 return .gt;
1660 } else {
1661 return .eq;
1662 }
1663 },
1664
1665 .elem_ptr => {
1666 const elem_ptr = lhs.castTag(.elem_ptr).?.data;
1667 switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(mod, opt_sema)) {
1153 return switch (lhs.ip_index) {
1154 .bool_false => .eq,
1155 .bool_true => .gt,
1156 else => switch (mod.intern_pool.indexToKey(lhs.ip_index)) {
1157 .ptr => |ptr| switch (ptr.addr) {
1158 .decl, .mut_decl, .comptime_field => .gt,
1159 .int => |int| int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1160 .elem => |elem| switch (try elem.base.toValue().orderAgainstZeroAdvanced(mod, opt_sema)) {
16681161 .lt => unreachable,
1669 .gt => return .gt,
1670 .eq => {
1671 if (elem_ptr.index == 0) {
1672 return .eq;
1673 } else {
1674 return .gt;
1675 }
1676 },
1677 }
1162 .gt => .gt,
1163 .eq => if (elem.index == 0) .eq else .gt,
1164 },
1165 else => unreachable,
16781166 },
1679
1680 else => unreachable,
1681 },
1682 else => return switch (mod.intern_pool.indexToKey(lhs.ip_index)) {
16831167 .int => |int| switch (int.storage) {
16841168 .big_int => |big_int| big_int.orderAgainstScalar(0),
16851169 inline .u64, .i64 => |x| std.math.order(x, 0),
1170 .lazy_align, .lazy_size => |ty| return if (ty.toType().hasRuntimeBitsAdvanced(
1171 mod,
1172 false,
1173 if (opt_sema) |sema| .{ .sema = sema } else .eager,
1174 ) catch |err| switch (err) {
1175 error.NeedLazy => unreachable,
1176 else => |e| return e,
1177 }) .gt else .eq,
16861178 },
1687 .enum_tag => |enum_tag| switch (mod.intern_pool.indexToKey(enum_tag.int).int.storage) {
1688 .big_int => |big_int| big_int.orderAgainstScalar(0),
1689 inline .u64, .i64 => |x| std.math.order(x, 0),
1690 },
1179 .enum_tag => |enum_tag| enum_tag.int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
16911180 .float => |float| switch (float.storage) {
16921181 inline else => |x| std.math.order(x, 0),
16931182 },
16941183 else => unreachable,
16951184 },
1696 }
1185 };
16971186 }
16981187
16991188 /// Asserts the value is comparable.
......@@ -1760,8 +1249,8 @@ pub const Value = struct {
17601249 mod: *Module,
17611250 opt_sema: ?*Sema,
17621251 ) !bool {
1763 if (lhs.pointerDecl()) |lhs_decl| {
1764 if (rhs.pointerDecl()) |rhs_decl| {
1252 if (lhs.pointerDecl(mod)) |lhs_decl| {
1253 if (rhs.pointerDecl(mod)) |rhs_decl| {
17651254 switch (op) {
17661255 .eq => return lhs_decl == rhs_decl,
17671256 .neq => return lhs_decl != rhs_decl,
......@@ -1774,7 +1263,7 @@ pub const Value = struct {
17741263 else => {},
17751264 }
17761265 }
1777 } else if (rhs.pointerDecl()) |_| {
1266 } else if (rhs.pointerDecl(mod)) |_| {
17781267 switch (op) {
17791268 .eq => return false,
17801269 .neq => return true,
......@@ -1849,7 +1338,6 @@ pub const Value = struct {
18491338
18501339 switch (lhs.ip_index) {
18511340 .none => switch (lhs.tag()) {
1852 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
18531341 .aggregate => {
18541342 for (lhs.castTag(.aggregate).?.data) |elem_val| {
18551343 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
......@@ -1877,6 +1365,15 @@ pub const Value = struct {
18771365 .float => |float| switch (float.storage) {
18781366 inline else => |x| if (std.math.isNan(x)) return op == .neq,
18791367 },
1368 .aggregate => |aggregate| return switch (aggregate.storage) {
1369 .bytes => |bytes| for (bytes) |byte| {
1370 if (!std.math.order(byte, 0).compare(op)) break false;
1371 } else true,
1372 .elems => |elems| for (elems) |elem| {
1373 if (!try elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema)) break false;
1374 } else true,
1375 .repeated_elem => |elem| elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
1376 },
18801377 else => {},
18811378 },
18821379 }
......@@ -1910,69 +1407,6 @@ pub const Value = struct {
19101407 const a_tag = a.tag();
19111408 const b_tag = b.tag();
19121409 if (a_tag == b_tag) switch (a_tag) {
1913 .the_only_possible_value => return true,
1914 .enum_literal => {
1915 const a_name = a.castTag(.enum_literal).?.data;
1916 const b_name = b.castTag(.enum_literal).?.data;
1917 return std.mem.eql(u8, a_name, b_name);
1918 },
1919 .opt_payload => {
1920 const a_payload = a.castTag(.opt_payload).?.data;
1921 const b_payload = b.castTag(.opt_payload).?.data;
1922 const payload_ty = ty.optionalChild(mod);
1923 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
1924 },
1925 .slice => {
1926 const a_payload = a.castTag(.slice).?.data;
1927 const b_payload = b.castTag(.slice).?.data;
1928 if (!(try eqlAdvanced(a_payload.len, Type.usize, b_payload.len, Type.usize, mod, opt_sema))) {
1929 return false;
1930 }
1931
1932 const ptr_ty = ty.slicePtrFieldType(mod);
1933
1934 return eqlAdvanced(a_payload.ptr, ptr_ty, b_payload.ptr, ptr_ty, mod, opt_sema);
1935 },
1936 .elem_ptr => {
1937 const a_payload = a.castTag(.elem_ptr).?.data;
1938 const b_payload = b.castTag(.elem_ptr).?.data;
1939 if (a_payload.index != b_payload.index) return false;
1940
1941 return eqlAdvanced(a_payload.array_ptr, ty, b_payload.array_ptr, ty, mod, opt_sema);
1942 },
1943 .field_ptr => {
1944 const a_payload = a.castTag(.field_ptr).?.data;
1945 const b_payload = b.castTag(.field_ptr).?.data;
1946 if (a_payload.field_index != b_payload.field_index) return false;
1947
1948 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
1949 },
1950 .@"error" => {
1951 const a_name = a.castTag(.@"error").?.data.name;
1952 const b_name = b.castTag(.@"error").?.data.name;
1953 return std.mem.eql(u8, a_name, b_name);
1954 },
1955 .eu_payload => {
1956 const a_payload = a.castTag(.eu_payload).?.data;
1957 const b_payload = b.castTag(.eu_payload).?.data;
1958 const payload_ty = ty.errorUnionPayload(mod);
1959 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
1960 },
1961 .eu_payload_ptr => {
1962 const a_payload = a.castTag(.eu_payload_ptr).?.data;
1963 const b_payload = b.castTag(.eu_payload_ptr).?.data;
1964 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
1965 },
1966 .opt_payload_ptr => {
1967 const a_payload = a.castTag(.opt_payload_ptr).?.data;
1968 const b_payload = b.castTag(.opt_payload_ptr).?.data;
1969 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
1970 },
1971 .function => {
1972 const a_payload = a.castTag(.function).?.data;
1973 const b_payload = b.castTag(.function).?.data;
1974 return a_payload == b_payload;
1975 },
19761410 .aggregate => {
19771411 const a_field_vals = a.castTag(.aggregate).?.data;
19781412 const b_field_vals = b.castTag(.aggregate).?.data;
......@@ -2035,17 +1469,15 @@ pub const Value = struct {
20351469 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
20361470 },
20371471 else => {},
2038 } else if (b_tag == .@"error") {
2039 return false;
2040 }
1472 };
20411473
2042 if (a.pointerDecl()) |a_decl| {
2043 if (b.pointerDecl()) |b_decl| {
1474 if (a.pointerDecl(mod)) |a_decl| {
1475 if (b.pointerDecl(mod)) |b_decl| {
20441476 return a_decl == b_decl;
20451477 } else {
20461478 return false;
20471479 }
2048 } else if (b.pointerDecl()) |_| {
1480 } else if (b.pointerDecl(mod)) |_| {
20491481 return false;
20501482 }
20511483
......@@ -2130,25 +1562,11 @@ pub const Value = struct {
21301562 if (a_nan) return true;
21311563 return a_float == b_float;
21321564 },
2133 .Optional => if (b_tag == .opt_payload) {
2134 var sub_pl: Payload.SubValue = .{
2135 .base = .{ .tag = b.tag() },
2136 .data = a,
2137 };
2138 const sub_val = Value.initPayload(&sub_pl.base);
2139 return eqlAdvanced(sub_val, ty, b, ty, mod, opt_sema);
2140 },
2141 .ErrorUnion => if (a_tag != .@"error" and b_tag == .eu_payload) {
2142 var sub_pl: Payload.SubValue = .{
2143 .base = .{ .tag = b.tag() },
2144 .data = a,
2145 };
2146 const sub_val = Value.initPayload(&sub_pl.base);
2147 return eqlAdvanced(sub_val, ty, b, ty, mod, opt_sema);
2148 },
1565 .Optional,
1566 .ErrorUnion,
1567 => unreachable, // handled by InternPool
21491568 else => {},
21501569 }
2151 if (a_tag == .@"error") return false;
21521570 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
21531571 }
21541572
......@@ -2166,7 +1584,7 @@ pub const Value = struct {
21661584 std.hash.autoHash(hasher, zig_ty_tag);
21671585 if (val.isUndef(mod)) return;
21681586 // The value is runtime-known and shouldn't affect the hash.
2169 if (val.isRuntimeValue()) return;
1587 if (val.isRuntimeValue(mod)) return;
21701588
21711589 switch (zig_ty_tag) {
21721590 .Opaque => unreachable, // Cannot hash opaque types
......@@ -2177,38 +1595,20 @@ pub const Value = struct {
21771595 .Null,
21781596 => {},
21791597
2180 .Type => unreachable, // handled via ip_index check above
2181 .Float => {
2182 // For hash/eql purposes, we treat floats as their IEEE integer representation.
2183 switch (ty.floatBits(mod.getTarget())) {
2184 16 => std.hash.autoHash(hasher, @bitCast(u16, val.toFloat(f16, mod))),
2185 32 => std.hash.autoHash(hasher, @bitCast(u32, val.toFloat(f32, mod))),
2186 64 => std.hash.autoHash(hasher, @bitCast(u64, val.toFloat(f64, mod))),
2187 80 => std.hash.autoHash(hasher, @bitCast(u80, val.toFloat(f80, mod))),
2188 128 => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),
2189 else => unreachable,
2190 }
2191 },
2192 .ComptimeFloat => {
2193 const float = val.toFloat(f128, mod);
2194 const is_nan = std.math.isNan(float);
2195 std.hash.autoHash(hasher, is_nan);
2196 if (!is_nan) {
2197 std.hash.autoHash(hasher, @bitCast(u128, float));
2198 } else {
2199 std.hash.autoHash(hasher, std.math.signbit(float));
2200 }
2201 },
2202 .Bool, .Int, .ComptimeInt, .Pointer => switch (val.tag()) {
2203 .slice => {
2204 const slice = val.castTag(.slice).?.data;
2205 const ptr_ty = ty.slicePtrFieldType(mod);
2206 hash(slice.ptr, ptr_ty, hasher, mod);
2207 hash(slice.len, Type.usize, hasher, mod);
2208 },
2209
2210 else => return hashPtr(val, hasher, mod),
2211 },
1598 .Type,
1599 .Float,
1600 .ComptimeFloat,
1601 .Bool,
1602 .Int,
1603 .ComptimeInt,
1604 .Pointer,
1605 .Optional,
1606 .ErrorUnion,
1607 .ErrorSet,
1608 .Enum,
1609 .EnumLiteral,
1610 .Fn,
1611 => unreachable, // handled via ip_index check above
22121612 .Array, .Vector => {
22131613 const len = ty.arrayLen(mod);
22141614 const elem_ty = ty.childType(mod);
......@@ -2233,42 +1633,6 @@ pub const Value = struct {
22331633 else => unreachable,
22341634 }
22351635 },
2236 .Optional => {
2237 if (val.castTag(.opt_payload)) |payload| {
2238 std.hash.autoHash(hasher, true); // non-null
2239 const sub_val = payload.data;
2240 const sub_ty = ty.optionalChild(mod);
2241 sub_val.hash(sub_ty, hasher, mod);
2242 } else {
2243 std.hash.autoHash(hasher, false); // null
2244 }
2245 },
2246 .ErrorUnion => {
2247 if (val.tag() == .@"error") {
2248 std.hash.autoHash(hasher, false); // error
2249 const sub_ty = ty.errorUnionSet(mod);
2250 val.hash(sub_ty, hasher, mod);
2251 return;
2252 }
2253
2254 if (val.castTag(.eu_payload)) |payload| {
2255 std.hash.autoHash(hasher, true); // payload
2256 const sub_ty = ty.errorUnionPayload(mod);
2257 payload.data.hash(sub_ty, hasher, mod);
2258 return;
2259 } else unreachable;
2260 },
2261 .ErrorSet => {
2262 // just hash the literal error value. this is the most stable
2263 // thing between compiler invocations. we can't use the error
2264 // int cause (1) its not stable and (2) we don't have access to mod.
2265 hasher.update(val.getError().?);
2266 },
2267 .Enum => {
2268 // This panic will go away when enum values move to be stored in the intern pool.
2269 const int_val = val.enumToInt(ty, mod) catch @panic("OOM");
2270 hashInt(int_val, hasher, mod);
2271 },
22721636 .Union => {
22731637 const union_obj = val.cast(Payload.Union).?.data;
22741638 if (ty.unionTagType(mod)) |tag_ty| {
......@@ -2277,27 +1641,12 @@ pub const Value = struct {
22771641 const active_field_ty = ty.unionFieldType(union_obj.tag, mod);
22781642 union_obj.val.hash(active_field_ty, hasher, mod);
22791643 },
2280 .Fn => {
2281 // Note that this hashes the *Fn/*ExternFn rather than the *Decl.
2282 // This is to differentiate function bodies from function pointers.
2283 // This is currently redundant since we already hash the zig type tag
2284 // at the top of this function.
2285 if (val.castTag(.function)) |func| {
2286 std.hash.autoHash(hasher, func.data);
2287 } else if (val.castTag(.extern_fn)) |func| {
2288 std.hash.autoHash(hasher, func.data);
2289 } else unreachable;
2290 },
22911644 .Frame => {
22921645 @panic("TODO implement hashing frame values");
22931646 },
22941647 .AnyFrame => {
22951648 @panic("TODO implement hashing anyframe values");
22961649 },
2297 .EnumLiteral => {
2298 const bytes = val.castTag(.enum_literal).?.data;
2299 hasher.update(bytes);
2300 },
23011650 }
23021651 }
23031652
......@@ -2308,7 +1657,7 @@ pub const Value = struct {
23081657 pub fn hashUncoerced(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
23091658 if (val.isUndef(mod)) return;
23101659 // The value is runtime-known and shouldn't affect the hash.
2311 if (val.isRuntimeValue()) return;
1660 if (val.isRuntimeValue(mod)) return;
23121661
23131662 if (val.ip_index != .none) {
23141663 // The InternPool data structure hashes based on Key to make interned objects
......@@ -2326,16 +1675,20 @@ pub const Value = struct {
23261675 .Null,
23271676 .Struct, // It sure would be nice to do something clever with structs.
23281677 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),
2329 .Type => unreachable, // handled above with the ip_index check
2330 .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128, mod))),
2331 .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) {
2332 .slice => {
2333 const slice = val.castTag(.slice).?.data;
2334 const ptr_ty = ty.slicePtrFieldType(mod);
2335 slice.ptr.hashUncoerced(ptr_ty, hasher, mod);
2336 },
2337 else => val.hashPtr(hasher, mod),
2338 },
1678 .Type,
1679 .Float,
1680 .ComptimeFloat,
1681 .Bool,
1682 .Int,
1683 .ComptimeInt,
1684 .Pointer,
1685 .Fn,
1686 .Optional,
1687 .ErrorSet,
1688 .ErrorUnion,
1689 .Enum,
1690 .EnumLiteral,
1691 => unreachable, // handled above with the ip_index check
23391692 .Array, .Vector => {
23401693 const len = ty.arrayLen(mod);
23411694 const elem_ty = ty.childType(mod);
......@@ -2348,21 +1701,16 @@ pub const Value = struct {
23481701 elem_val.hashUncoerced(elem_ty, hasher, mod);
23491702 }
23501703 },
2351 .Optional => if (val.castTag(.opt_payload)) |payload| {
2352 const child_ty = ty.optionalChild(mod);
2353 payload.data.hashUncoerced(child_ty, hasher, mod);
2354 } else std.hash.autoHash(hasher, std.builtin.TypeId.Null),
2355 .ErrorSet, .ErrorUnion => if (val.getError()) |err| hasher.update(err) else {
2356 const pl_ty = ty.errorUnionPayload(mod);
2357 val.castTag(.eu_payload).?.data.hashUncoerced(pl_ty, hasher, mod);
2358 },
2359 .Enum, .EnumLiteral, .Union => {
2360 hasher.update(val.tagName(ty, mod));
2361 if (val.cast(Payload.Union)) |union_obj| {
2362 const active_field_ty = ty.unionFieldType(union_obj.data.tag, mod);
2363 union_obj.data.val.hashUncoerced(active_field_ty, hasher, mod);
2364 } else std.hash.autoHash(hasher, std.builtin.TypeId.Void);
2365 },
1704 .Union => {
1705 hasher.update(val.tagName(mod));
1706 switch (mod.intern_pool.indexToKey(val.ip_index)) {
1707 .un => |un| {
1708 const active_field_ty = ty.unionFieldType(un.tag.toValue(), mod);
1709 un.val.toValue().hashUncoerced(active_field_ty, hasher, mod);
1710 },
1711 else => std.hash.autoHash(hasher, std.builtin.TypeId.Void),
1712 }
1713 },
23661714 .Frame => @panic("TODO implement hashing frame values"),
23671715 .AnyFrame => @panic("TODO implement hashing anyframe values"),
23681716 }
......@@ -2397,57 +1745,53 @@ pub const Value = struct {
23971745 }
23981746 };
23991747
2400 pub fn isComptimeMutablePtr(val: Value) bool {
2401 return switch (val.ip_index) {
2402 .none => switch (val.tag()) {
2403 .decl_ref_mut, .comptime_field_ptr => true,
2404 .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr),
2405 .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr),
2406 .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr),
2407 .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr),
2408 .slice => isComptimeMutablePtr(val.castTag(.slice).?.data.ptr),
2409
1748 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
1749 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1750 .ptr => |ptr| switch (ptr.addr) {
1751 .mut_decl, .comptime_field => true,
1752 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isComptimeMutablePtr(mod),
1753 .elem, .field => |base_index| base_index.base.toValue().isComptimeMutablePtr(mod),
24101754 else => false,
24111755 },
24121756 else => false,
24131757 };
24141758 }
24151759
2416 pub fn canMutateComptimeVarState(val: Value) bool {
2417 if (val.isComptimeMutablePtr()) return true;
2418 return switch (val.ip_index) {
2419 .none => switch (val.tag()) {
2420 .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),
2421 .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),
2422 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
2423 .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),
2424 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
2425 .aggregate => {
2426 const fields = val.castTag(.aggregate).?.data;
2427 for (fields) |field| {
2428 if (field.canMutateComptimeVarState()) return true;
2429 }
2430 return false;
1760 pub fn canMutateComptimeVarState(val: Value, mod: *Module) bool {
1761 return val.isComptimeMutablePtr(mod) or switch (val.ip_index) {
1762 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1763 .error_union => |error_union| switch (error_union.val) {
1764 .err_name => false,
1765 .payload => |payload| payload.toValue().canMutateComptimeVarState(mod),
24311766 },
2432 .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(),
2433 .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(),
2434 else => return false,
1767 .ptr => |ptr| switch (ptr.addr) {
1768 .eu_payload, .opt_payload => |base| base.toValue().canMutateComptimeVarState(mod),
1769 else => false,
1770 },
1771 .opt => |opt| switch (opt.val) {
1772 .none => false,
1773 else => opt.val.toValue().canMutateComptimeVarState(mod),
1774 },
1775 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
1776 if (elem.toValue().canMutateComptimeVarState(mod)) break true;
1777 } else false,
1778 .un => |un| un.val.toValue().canMutateComptimeVarState(mod),
1779 else => false,
24351780 },
2436 else => return false,
24371781 };
24381782 }
24391783
24401784 /// Gets the decl referenced by this pointer. If the pointer does not point
24411785 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
24421786 /// this function returns null.
2443 pub fn pointerDecl(val: Value) ?Module.Decl.Index {
2444 return switch (val.ip_index) {
2445 .none => switch (val.tag()) {
2446 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,
2447 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
2448 .function => val.castTag(.function).?.data.owner_decl,
2449 .variable => val.castTag(.variable).?.data.owner_decl,
2450 .decl_ref => val.cast(Payload.Decl).?.data,
1787 pub fn pointerDecl(val: Value, mod: *Module) ?Module.Decl.Index {
1788 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1789 .variable => |variable| variable.decl,
1790 .extern_func => |extern_func| extern_func.decl,
1791 .func => |func| mod.funcPtr(func.index).owner_decl,
1792 .ptr => |ptr| switch (ptr.addr) {
1793 .decl => |decl| decl,
1794 .mut_decl => |mut_decl| mut_decl.decl,
24511795 else => null,
24521796 },
24531797 else => null,
......@@ -2463,95 +1807,15 @@ pub const Value = struct {
24631807 }
24641808 }
24651809
2466 fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, mod: *Module) void {
2467 switch (ptr_val.tag()) {
2468 .decl_ref,
2469 .decl_ref_mut,
2470 .extern_fn,
2471 .function,
2472 .variable,
2473 => {
2474 const decl: Module.Decl.Index = ptr_val.pointerDecl().?;
2475 std.hash.autoHash(hasher, decl);
2476 },
2477 .comptime_field_ptr => {
2478 std.hash.autoHash(hasher, Value.Tag.comptime_field_ptr);
2479 },
2480
2481 .elem_ptr => {
2482 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2483 hashPtr(elem_ptr.array_ptr, hasher, mod);
2484 std.hash.autoHash(hasher, Value.Tag.elem_ptr);
2485 std.hash.autoHash(hasher, elem_ptr.index);
2486 },
2487 .field_ptr => {
2488 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
2489 std.hash.autoHash(hasher, Value.Tag.field_ptr);
2490 hashPtr(field_ptr.container_ptr, hasher, mod);
2491 std.hash.autoHash(hasher, field_ptr.field_index);
2492 },
2493 .eu_payload_ptr => {
2494 const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
2495 std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr);
2496 hashPtr(err_union_ptr.container_ptr, hasher, mod);
2497 },
2498 .opt_payload_ptr => {
2499 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
2500 std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr);
2501 hashPtr(opt_ptr.container_ptr, hasher, mod);
2502 },
2503
2504 .the_only_possible_value,
2505 .lazy_align,
2506 .lazy_size,
2507 => return hashInt(ptr_val, hasher, mod),
2508
2509 else => unreachable,
2510 }
2511 }
1810 pub const slice_ptr_index = 0;
1811 pub const slice_len_index = 1;
25121812
25131813 pub fn slicePtr(val: Value, mod: *Module) Value {
2514 if (val.ip_index != .none) return mod.intern_pool.slicePtr(val.ip_index).toValue();
2515 return switch (val.tag()) {
2516 .slice => val.castTag(.slice).?.data.ptr,
2517 // TODO this should require being a slice tag, and not allow decl_ref, field_ptr, etc.
2518 .decl_ref, .decl_ref_mut, .field_ptr, .elem_ptr, .comptime_field_ptr => val,
2519 else => unreachable,
2520 };
1814 return mod.intern_pool.slicePtr(val.ip_index).toValue();
25211815 }
25221816
25231817 pub fn sliceLen(val: Value, mod: *Module) u64 {
2524 if (val.ip_index != .none) return mod.intern_pool.sliceLen(val.ip_index).toValue().toUnsignedInt(mod);
2525 return switch (val.tag()) {
2526 .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod),
2527 .decl_ref => {
2528 const decl_index = val.castTag(.decl_ref).?.data;
2529 const decl = mod.declPtr(decl_index);
2530 if (decl.ty.zigTypeTag(mod) == .Array) {
2531 return decl.ty.arrayLen(mod);
2532 } else {
2533 return 1;
2534 }
2535 },
2536 .decl_ref_mut => {
2537 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
2538 const decl = mod.declPtr(decl_index);
2539 if (decl.ty.zigTypeTag(mod) == .Array) {
2540 return decl.ty.arrayLen(mod);
2541 } else {
2542 return 1;
2543 }
2544 },
2545 .comptime_field_ptr => {
2546 const payload = val.castTag(.comptime_field_ptr).?.data;
2547 if (payload.field_ty.zigTypeTag(mod) == .Array) {
2548 return payload.field_ty.arrayLen(mod);
2549 } else {
2550 return 1;
2551 }
2552 },
2553 else => unreachable,
2554 };
1818 return mod.intern_pool.sliceLen(val.ip_index).toValue().toUnsignedInt(mod);
25551819 }
25561820
25571821 /// Asserts the value is a single-item pointer to an array, or an array,
......@@ -2560,14 +1824,6 @@ pub const Value = struct {
25601824 switch (val.ip_index) {
25611825 .undef => return Value.undef,
25621826 .none => switch (val.tag()) {
2563 // This is the case of accessing an element of an undef array.
2564 .empty_array => unreachable, // out of bounds array index
2565
2566 .empty_array_sentinel => {
2567 assert(index == 0); // The only valid index for an empty array with sentinel.
2568 return val.castTag(.empty_array_sentinel).?.data;
2569 },
2570
25711827 .bytes => {
25721828 const byte = val.castTag(.bytes).?.data[index];
25731829 return mod.intValue(Type.u8, byte);
......@@ -2579,128 +1835,101 @@ pub const Value = struct {
25791835 return mod.intValue(Type.u8, byte);
25801836 },
25811837
2582 // No matter the index; all the elements are the same!
2583 .repeated => return val.castTag(.repeated).?.data,
2584
25851838 .aggregate => return val.castTag(.aggregate).?.data[index],
2586 .slice => return val.castTag(.slice).?.data.ptr.elemValue(mod, index),
2587
2588 .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValue(mod, index),
2589 .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValue(mod, index),
2590 .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValue(mod, index),
2591 .elem_ptr => {
2592 const data = val.castTag(.elem_ptr).?.data;
2593 return data.array_ptr.elemValue(mod, index + data.index);
2594 },
2595 .field_ptr => {
2596 const data = val.castTag(.field_ptr).?.data;
2597 if (data.container_ptr.pointerDecl()) |decl_index| {
2598 const container_decl = mod.declPtr(decl_index);
2599 const field_type = data.container_ty.structFieldType(data.field_index, mod);
2600 const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index);
2601 return field_val.elemValue(mod, index);
2602 } else unreachable;
2603 },
2604
2605 // The child type of arrays which have only one possible value need
2606 // to have only one possible value itself.
2607 .the_only_possible_value => return val,
2608
2609 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValue(mod, index),
2610 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValue(mod, index),
2611
2612 .opt_payload => return val.castTag(.opt_payload).?.data.elemValue(mod, index),
2613 .eu_payload => return val.castTag(.eu_payload).?.data.elemValue(mod, index),
26141839
26151840 else => unreachable,
26161841 },
26171842 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
26181843 .ptr => |ptr| switch (ptr.addr) {
2619 .@"var" => unreachable,
26201844 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
26211845 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),
26221846 .int, .eu_payload, .opt_payload => unreachable,
26231847 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
26241848 .elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
2625 .field => unreachable,
2626 },
2627 .aggregate => |aggregate| switch (aggregate.storage) {
2628 .elems => |elems| elems[index].toValue(),
2629 .repeated_elem => |elem| elem.toValue(),
1849 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
1850 const base_decl = mod.declPtr(decl_index);
1851 const field_val = try base_decl.val.fieldValue(mod, field.index);
1852 return field_val.elemValue(mod, index);
1853 } else unreachable,
1854 },
1855 .aggregate => |aggregate| {
1856 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
1857 if (index < len) return switch (aggregate.storage) {
1858 .bytes => |bytes| try mod.intern(.{ .int = .{
1859 .ty = .u8_type,
1860 .storage = .{ .u64 = bytes[index] },
1861 } }),
1862 .elems => |elems| elems[index],
1863 .repeated_elem => |elem| elem,
1864 }.toValue();
1865 assert(index == len);
1866 return mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel.toValue();
26301867 },
26311868 else => unreachable,
26321869 },
26331870 }
26341871 }
26351872
2636 pub fn isLazyAlign(val: Value) bool {
2637 return val.ip_index == .none and val.tag() == .lazy_align;
2638 }
2639
2640 pub fn isLazySize(val: Value) bool {
2641 return val.ip_index == .none and val.tag() == .lazy_size;
1873 pub fn isLazyAlign(val: Value, mod: *Module) bool {
1874 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1875 .int => |int| int.storage == .lazy_align,
1876 else => false,
1877 };
26421878 }
26431879
2644 pub fn isRuntimeValue(val: Value) bool {
2645 return val.ip_index == .none and val.tag() == .runtime_value;
1880 pub fn isLazySize(val: Value, mod: *Module) bool {
1881 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1882 .int => |int| int.storage == .lazy_size,
1883 else => false,
1884 };
26461885 }
26471886
2648 pub fn tagIsVariable(val: Value) bool {
2649 return val.ip_index == .none and val.tag() == .variable;
1887 pub fn isRuntimeValue(val: Value, mod: *Module) bool {
1888 return mod.intern_pool.indexToKey(val.ip_index) == .runtime_value;
26501889 }
26511890
26521891 /// Returns true if a Value is backed by a variable
26531892 pub fn isVariable(val: Value, mod: *Module) bool {
2654 return switch (val.ip_index) {
2655 .none => switch (val.tag()) {
2656 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
2657 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
2658 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
2659 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
2660 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
2661 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
2662 .decl_ref => {
2663 const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
1893 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1894 .variable => true,
1895 .ptr => |ptr| switch (ptr.addr) {
1896 .decl => |decl_index| {
1897 const decl = mod.declPtr(decl_index);
26641898 assert(decl.has_tv);
26651899 return decl.val.isVariable(mod);
26661900 },
2667 .decl_ref_mut => {
2668 const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
1901 .mut_decl => |mut_decl| {
1902 const decl = mod.declPtr(mut_decl.decl);
26691903 assert(decl.has_tv);
26701904 return decl.val.isVariable(mod);
26711905 },
2672
2673 .variable => true,
2674 else => false,
1906 .int => false,
1907 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isVariable(mod),
1908 .comptime_field => |comptime_field| comptime_field.toValue().isVariable(mod),
1909 .elem, .field => |base_index| base_index.base.toValue().isVariable(mod),
26751910 },
26761911 else => false,
26771912 };
26781913 }
26791914
26801915 pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {
2681 return switch (val.ip_index) {
2682 .none => switch (val.tag()) {
2683 .variable => false,
2684 else => val.isPtrToThreadLocalInner(mod),
2685 },
2686 else => val.isPtrToThreadLocalInner(mod),
2687 };
2688 }
2689
2690 fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
2691 return switch (val.ip_index) {
2692 .none => switch (val.tag()) {
2693 .slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),
2694 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),
2695 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),
2696 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2697 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2698 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2699 .decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isPtrToThreadLocalInner(mod),
2700 .decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isPtrToThreadLocalInner(mod),
2701
2702 .variable => val.castTag(.variable).?.data.is_threadlocal,
2703 else => false,
1916 return switch (mod.intern_pool.indexToKey(val.ip_index)) {
1917 .variable => |variable| variable.is_threadlocal,
1918 .ptr => |ptr| switch (ptr.addr) {
1919 .decl => |decl_index| {
1920 const decl = mod.declPtr(decl_index);
1921 assert(decl.has_tv);
1922 return decl.val.isPtrToThreadLocal(mod);
1923 },
1924 .mut_decl => |mut_decl| {
1925 const decl = mod.declPtr(mut_decl.decl);
1926 assert(decl.has_tv);
1927 return decl.val.isPtrToThreadLocal(mod);
1928 },
1929 .int => false,
1930 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocal(mod),
1931 .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocal(mod),
1932 .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocal(mod),
27041933 },
27051934 else => false,
27061935 };
......@@ -2714,39 +1943,42 @@ pub const Value = struct {
27141943 start: usize,
27151944 end: usize,
27161945 ) error{OutOfMemory}!Value {
2717 return switch (val.tag()) {
2718 .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array),
2719 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
2720 .str_lit => {
2721 const str_lit = val.castTag(.str_lit).?.data;
2722 return Tag.str_lit.create(arena, .{
2723 .index = @intCast(u32, str_lit.index + start),
2724 .len = @intCast(u32, end - start),
2725 });
1946 return switch (val.ip_index) {
1947 .none => switch (val.tag()) {
1948 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
1949 .str_lit => {
1950 const str_lit = val.castTag(.str_lit).?.data;
1951 return Tag.str_lit.create(arena, .{
1952 .index = @intCast(u32, str_lit.index + start),
1953 .len = @intCast(u32, end - start),
1954 });
1955 },
1956 else => unreachable,
27261957 },
2727 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
2728 .slice => sliceArray(val.castTag(.slice).?.data.ptr, mod, arena, start, end),
2729
2730 .decl_ref => sliceArray(mod.declPtr(val.castTag(.decl_ref).?.data).val, mod, arena, start, end),
2731 .decl_ref_mut => sliceArray(mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val, mod, arena, start, end),
2732 .comptime_field_ptr => sliceArray(val.castTag(.comptime_field_ptr).?.data.field_val, mod, arena, start, end),
2733 .elem_ptr => blk: {
2734 const elem_ptr = val.castTag(.elem_ptr).?.data;
2735 break :blk sliceArray(elem_ptr.array_ptr, mod, arena, start + elem_ptr.index, end + elem_ptr.index);
1958 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
1959 .ptr => |ptr| switch (ptr.addr) {
1960 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
1961 .mut_decl => |mut_decl| try mod.declPtr(mut_decl.decl).val.sliceArray(mod, arena, start, end),
1962 .comptime_field => |comptime_field| try comptime_field.toValue().sliceArray(mod, arena, start, end),
1963 .elem => |elem| try elem.base.toValue().sliceArray(mod, arena, start + elem.index, end + elem.index),
1964 else => unreachable,
1965 },
1966 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
1967 .ty = mod.intern_pool.typeOf(val.ip_index),
1968 .storage = switch (aggregate.storage) {
1969 .bytes => |bytes| .{ .bytes = bytes[start..end] },
1970 .elems => |elems| .{ .elems = elems[start..end] },
1971 .repeated_elem => |elem| .{ .repeated_elem = elem },
1972 },
1973 } })).toValue(),
1974 else => unreachable,
27361975 },
2737
2738 .repeated,
2739 .the_only_possible_value,
2740 => val,
2741
2742 else => unreachable,
27431976 };
27441977 }
27451978
2746 pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
1979 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
27471980 switch (val.ip_index) {
27481981 .undef => return Value.undef,
2749
27501982 .none => switch (val.tag()) {
27511983 .aggregate => {
27521984 const field_values = val.castTag(.aggregate).?.data;
......@@ -2757,13 +1989,14 @@ pub const Value = struct {
27571989 // TODO assert the tag is correct
27581990 return payload.val;
27591991 },
2760
2761 .the_only_possible_value => return (try ty.onePossibleValue(mod)).?,
2762
27631992 else => unreachable,
27641993 },
27651994 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
27661995 .aggregate => |aggregate| switch (aggregate.storage) {
1996 .bytes => |bytes| try mod.intern(.{ .int = .{
1997 .ty = .u8_type,
1998 .storage = .{ .u64 = bytes[index] },
1999 } }),
27672000 .elems => |elems| elems[index],
27682001 .repeated_elem => |elem| elem,
27692002 }.toValue(),
......@@ -2785,40 +2018,37 @@ pub const Value = struct {
27852018 pub fn elemPtr(
27862019 val: Value,
27872020 ty: Type,
2788 arena: Allocator,
27892021 index: usize,
27902022 mod: *Module,
27912023 ) Allocator.Error!Value {
27922024 const elem_ty = ty.elemType2(mod);
2793 const ptr_val = switch (val.ip_index) {
2794 .none => switch (val.tag()) {
2795 .slice => val.castTag(.slice).?.data.ptr,
2796 else => val,
2797 },
2798 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2799 .ptr => |ptr| switch (ptr.len) {
2025 const ptr_val = switch (mod.intern_pool.indexToKey(val.ip_index)) {
2026 .ptr => |ptr| ptr: {
2027 switch (ptr.addr) {
2028 .elem => |elem| if (mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).eql(elem_ty, mod))
2029 return (try mod.intern(.{ .ptr = .{
2030 .ty = ty.ip_index,
2031 .addr = .{ .elem = .{
2032 .base = elem.base,
2033 .index = elem.index + index,
2034 } },
2035 } })).toValue(),
2036 else => {},
2037 }
2038 break :ptr switch (ptr.len) {
28002039 .none => val,
28012040 else => val.slicePtr(mod),
2802 },
2803 else => val,
2041 };
28042042 },
2043 else => val,
28052044 };
2806
2807 if (ptr_val.ip_index == .none and ptr_val.tag() == .elem_ptr) {
2808 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2809 if (elem_ptr.elem_ty.eql(elem_ty, mod)) {
2810 return Tag.elem_ptr.create(arena, .{
2811 .array_ptr = elem_ptr.array_ptr,
2812 .elem_ty = elem_ptr.elem_ty,
2813 .index = elem_ptr.index + index,
2814 });
2815 }
2816 }
2817 return Tag.elem_ptr.create(arena, .{
2818 .array_ptr = ptr_val,
2819 .elem_ty = elem_ty,
2820 .index = index,
2821 });
2045 return (try mod.intern(.{ .ptr = .{
2046 .ty = ty.ip_index,
2047 .addr = .{ .elem = .{
2048 .base = ptr_val.ip_index,
2049 .index = index,
2050 } },
2051 } })).toValue();
28222052 }
28232053
28242054 pub fn isUndef(val: Value, mod: *Module) bool {
......@@ -2840,69 +2070,44 @@ pub const Value = struct {
28402070 /// Returns true if any value contained in `self` is undefined.
28412071 pub fn anyUndef(val: Value, mod: *Module) !bool {
28422072 if (val.ip_index == .none) return false;
2843 switch (val.ip_index) {
2844 .undef => return true,
2073 return switch (val.ip_index) {
2074 .undef => true,
28452075 .none => switch (val.tag()) {
2846 .slice => {
2847 const payload = val.castTag(.slice).?;
2848 const len = payload.data.len.toUnsignedInt(mod);
2849
2850 for (0..len) |i| {
2851 const elem_val = try payload.data.ptr.elemValue(mod, i);
2852 if (try elem_val.anyUndef(mod)) return true;
2853 }
2854 },
2855
2856 .aggregate => {
2857 const payload = val.castTag(.aggregate).?;
2858 for (payload.data) |field| {
2859 if (try field.anyUndef(mod)) return true;
2860 }
2861 },
2862 else => {},
2076 .aggregate => for (val.castTag(.aggregate).?.data) |field| {
2077 if (try field.anyUndef(mod)) break true;
2078 } else false,
2079 else => false,
28632080 },
28642081 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2865 .undef => return true,
2866 .simple_value => |v| if (v == .undefined) return true,
2867 .aggregate => |aggregate| switch (aggregate.storage) {
2868 .elems => |elems| for (elems) |elem| {
2869 if (try anyUndef(elem.toValue(), mod)) return true;
2870 },
2871 .repeated_elem => |elem| if (try anyUndef(elem.toValue(), mod)) return true,
2872 },
2873 else => {},
2082 .undef => true,
2083 .simple_value => |v| v == .undefined,
2084 .ptr => |ptr| switch (ptr.len) {
2085 .none => false,
2086 else => for (0..@intCast(usize, ptr.len.toValue().toUnsignedInt(mod))) |index| {
2087 if (try (try val.elemValue(mod, index)).anyUndef(mod)) break true;
2088 } else false,
2089 },
2090 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
2091 if (try anyUndef(elem.toValue(), mod)) break true;
2092 } else false,
2093 else => false,
28742094 },
2875 }
2876
2877 return false;
2095 };
28782096 }
28792097
28802098 /// Asserts the value is not undefined and not unreachable.
28812099 /// Integer value 0 is considered null because of C pointers.
2882 pub fn isNull(val: Value, mod: *const Module) bool {
2100 pub fn isNull(val: Value, mod: *Module) bool {
28832101 return switch (val.ip_index) {
28842102 .undef => unreachable,
28852103 .unreachable_value => unreachable,
28862104
28872105 .null_value => true,
28882106
2889 .none => switch (val.tag()) {
2890 .opt_payload => false,
2891
2892 // If it's not one of those two tags then it must be a C pointer value,
2893 // in which case the value 0 is null and other values are non-null.
2894
2895 .the_only_possible_value => true,
2896
2897 .inferred_alloc => unreachable,
2898 .inferred_alloc_comptime => unreachable,
2899
2900 else => false,
2901 },
29022107 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
2903 .int => |int| switch (int.storage) {
2904 .big_int => |big_int| big_int.eqZero(),
2905 inline .u64, .i64 => |x| x == 0,
2108 .int => {
2109 var buf: BigIntSpace = undefined;
2110 return val.toBigInt(&buf, mod).eqZero();
29062111 },
29072112 .opt => |opt| opt.val == .none,
29082113 else => false,
......@@ -2914,53 +2119,28 @@ pub const Value = struct {
29142119 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether
29152120 /// something is an error or not because it works without having to figure out the
29162121 /// string.
2917 pub fn getError(self: Value) ?[]const u8 {
2918 return switch (self.ip_index) {
2919 .undef => unreachable,
2920 .unreachable_value => unreachable,
2921 .none => switch (self.tag()) {
2922 .@"error" => self.castTag(.@"error").?.data.name,
2923 .eu_payload => null,
2924
2925 .inferred_alloc => unreachable,
2926 .inferred_alloc_comptime => unreachable,
2927 else => unreachable,
2122 pub fn getError(self: Value, mod: *const Module) ?[]const u8 {
2123 return mod.intern_pool.stringToSliceUnwrap(switch (mod.intern_pool.indexToKey(self.ip_index)) {
2124 .err => |err| err.name.toOptional(),
2125 .error_union => |error_union| switch (error_union.val) {
2126 .err_name => |err_name| err_name.toOptional(),
2127 .payload => .none,
29282128 },
29292129 else => unreachable,
2930 };
2130 });
29312131 }
29322132
29332133 /// Assumes the type is an error union. Returns true if and only if the value is
29342134 /// the error union payload, not an error.
2935 pub fn errorUnionIsPayload(val: Value) bool {
2936 return switch (val.ip_index) {
2937 .undef => unreachable,
2938 .none => switch (val.tag()) {
2939 .eu_payload => true,
2940 else => false,
2941
2942 .inferred_alloc => unreachable,
2943 .inferred_alloc_comptime => unreachable,
2944 },
2945 else => false,
2946 };
2135 pub fn errorUnionIsPayload(val: Value, mod: *const Module) bool {
2136 return mod.intern_pool.indexToKey(val.ip_index).error_union.val == .payload;
29472137 }
29482138
29492139 /// Value of the optional, null if optional has no payload.
29502140 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2951 return switch (val.ip_index) {
2952 .none => if (val.isNull(mod)) null
2953 // Valid for optional representation to be the direct value
2954 // and not use opt_payload.
2955 else if (val.castTag(.opt_payload)) |p| p.data else val,
2956 .null_value => null,
2957 else => switch (mod.intern_pool.indexToKey(val.ip_index)) {
2958 .opt => |opt| switch (opt.val) {
2959 .none => null,
2960 else => opt.val.toValue(),
2961 },
2962 else => unreachable,
2963 },
2141 return switch (mod.intern_pool.indexToKey(val.ip_index).opt.val) {
2142 .none => null,
2143 else => |index| index.toValue(),
29642144 };
29652145 }
29662146
......@@ -3001,28 +2181,8 @@ pub const Value = struct {
30012181 }
30022182
30032183 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
3004 switch (val.ip_index) {
3005 .undef => return val,
3006 .none => switch (val.tag()) {
3007 .the_only_possible_value => return mod.floatValue(float_ty, 0), // for i0, u0
3008 .lazy_align => {
3009 const ty = val.castTag(.lazy_align).?.data;
3010 if (opt_sema) |sema| {
3011 return intToFloatInner((try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
3012 } else {
3013 return intToFloatInner(ty.abiAlignment(mod), float_ty, mod);
3014 }
3015 },
3016 .lazy_size => {
3017 const ty = val.castTag(.lazy_size).?.data;
3018 if (opt_sema) |sema| {
3019 return intToFloatInner((try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
3020 } else {
3021 return intToFloatInner(ty.abiSize(mod), float_ty, mod);
3022 }
3023 },
3024 else => unreachable,
3025 },
2184 return switch (val.ip_index) {
2185 .undef => val,
30262186 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
30272187 .int => |int| switch (int.storage) {
30282188 .big_int => |big_int| {
......@@ -3030,10 +2190,20 @@ pub const Value = struct {
30302190 return mod.floatValue(float_ty, float);
30312191 },
30322192 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
2193 .lazy_align => |ty| if (opt_sema) |sema| {
2194 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2195 } else {
2196 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
2197 },
2198 .lazy_size => |ty| if (opt_sema) |sema| {
2199 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
2200 } else {
2201 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
2202 },
30332203 },
30342204 else => unreachable,
30352205 },
3036 }
2206 };
30372207 }
30382208
30392209 fn intToFloatInner(x: anytype, dest_ty: Type, mod: *Module) !Value {
......@@ -4768,81 +3938,6 @@ pub const Value = struct {
47683938 pub const Payload = struct {
47693939 tag: Tag,
47703940
4771 pub const Function = struct {
4772 base: Payload,
4773 data: *Module.Fn,
4774 };
4775
4776 pub const ExternFn = struct {
4777 base: Payload,
4778 data: *Module.ExternFn,
4779 };
4780
4781 pub const Decl = struct {
4782 base: Payload,
4783 data: Module.Decl.Index,
4784 };
4785
4786 pub const Variable = struct {
4787 base: Payload,
4788 data: *Module.Var,
4789 };
4790
4791 pub const SubValue = struct {
4792 base: Payload,
4793 data: Value,
4794 };
4795
4796 pub const DeclRefMut = struct {
4797 pub const base_tag = Tag.decl_ref_mut;
4798
4799 base: Payload = Payload{ .tag = base_tag },
4800 data: Data,
4801
4802 pub const Data = struct {
4803 decl_index: Module.Decl.Index,
4804 runtime_index: RuntimeIndex,
4805 };
4806 };
4807
4808 pub const PayloadPtr = struct {
4809 base: Payload,
4810 data: struct {
4811 container_ptr: Value,
4812 container_ty: Type,
4813 },
4814 };
4815
4816 pub const ComptimeFieldPtr = struct {
4817 base: Payload,
4818 data: struct {
4819 field_val: Value,
4820 field_ty: Type,
4821 },
4822 };
4823
4824 pub const ElemPtr = struct {
4825 pub const base_tag = Tag.elem_ptr;
4826
4827 base: Payload = Payload{ .tag = base_tag },
4828 data: struct {
4829 array_ptr: Value,
4830 elem_ty: Type,
4831 index: usize,
4832 },
4833 };
4834
4835 pub const FieldPtr = struct {
4836 pub const base_tag = Tag.field_ptr;
4837
4838 base: Payload = Payload{ .tag = base_tag },
4839 data: struct {
4840 container_ptr: Value,
4841 container_ty: Type,
4842 field_index: usize,
4843 },
4844 };
4845
48463941 pub const Bytes = struct {
48473942 base: Payload,
48483943 /// Includes the sentinel, if any.
......@@ -4861,32 +3956,6 @@ pub const Value = struct {
48613956 data: []Value,
48623957 };
48633958
4864 pub const Slice = struct {
4865 base: Payload,
4866 data: struct {
4867 ptr: Value,
4868 len: Value,
4869 },
4870
4871 pub const ptr_index = 0;
4872 pub const len_index = 1;
4873 };
4874
4875 pub const Ty = struct {
4876 base: Payload,
4877 data: Type,
4878 };
4879
4880 pub const Error = struct {
4881 base: Payload = .{ .tag = .@"error" },
4882 data: struct {
4883 /// `name` is owned by `Module` and will be valid for the entire
4884 /// duration of the compilation.
4885 /// TODO revisit this when we have the concept of the error tag type
4886 name: []const u8,
4887 },
4888 };
4889
48903959 pub const InferredAlloc = struct {
48913960 pub const base_tag = Tag.inferred_alloc;
48923961
tools/lldb_pretty_printers.py+3-3
......@@ -533,8 +533,8 @@ type_tag_handlers = {
533533 'empty_struct_literal': lambda payload: '@TypeOf(.{})',
534534
535535 'anyerror_void_error_union': lambda payload: 'anyerror!void',
536 'const_slice_u8': lambda payload: '[]const u8',
537 'const_slice_u8_sentinel_0': lambda payload: '[:0]const u8',
536 'slice_const_u8': lambda payload: '[]const u8',
537 'slice_const_u8_sentinel_0': lambda payload: '[:0]const u8',
538538 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',
539539 'fn_void_no_args': lambda payload: 'fn() void',
540540 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',
......@@ -560,7 +560,7 @@ type_tag_handlers = {
560560 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),
561561 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),
562562 'c_mut_pointer': lambda payload: '[*c]%s' % type_Type_SummaryProvider(payload),
563 'const_slice': lambda payload: '[]const %s' % type_Type_SummaryProvider(payload),
563 'slice_const': lambda payload: '[]const %s' % type_Type_SummaryProvider(payload),
564564 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),
565565 'int_signed': lambda payload: 'i%d' % payload.unsigned,
566566 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,
tools/stage2_gdb_pretty_printers.py+1-1
......@@ -18,7 +18,7 @@ class TypePrinter:
1818 'many_mut_pointer': 'Type.Payload.ElemType',
1919 'c_const_pointer': 'Type.Payload.ElemType',
2020 'c_mut_pointer': 'Type.Payload.ElemType',
21 'const_slice': 'Type.Payload.ElemType',
21 'slice_const': 'Type.Payload.ElemType',
2222 'mut_slice': 'Type.Payload.ElemType',
2323 'optional': 'Type.Payload.ElemType',
2424 'optional_single_mut_pointer': 'Type.Payload.ElemType',